Skip to content

[release/2.7] Fix VHD ownership during distribution moves - #41354

Merged
Ben Hillis (benhillis) merged 5 commits into
release/2.7from
backport/2.7-move-distribution-owner
Aug 17, 2026
Merged

[release/2.7] Fix VHD ownership during distribution moves#41354
Ben Hillis (benhillis) merged 5 commits into
release/2.7from
backport/2.7-move-distribution-owner

Conversation

@benhillis

Copy link
Copy Markdown
Member

Summary of the Pull Request

Backports #41333 to release/2.7.

Distribution moves now use a duplicated caller token whose default owner is the caller's user SID. Move and rollback filesystem operations run under that token, avoiding a post-move owner rewrite.

PR Checklist

  • Closes: Link to issue #xxx
  • Communication: I've discussed this with core contributors already. If work hasn't been agreed, this work might be rejected
  • Tests: Added/updated if needed and all pass
  • Localization: All end user facing strings can be localized
  • Dev docs: Added/updated if needed
  • Documentation updated: If checked, please file a pull request on our docs repo and link it here: #xxx

Detailed Description of the Pull Request / Additional comments

This is a direct backport of the distribution move ownership change from #41333. The test conflict was resolved by retaining the admin-owner regression test, which is not otherwise present on release/2.7.

Validation Steps Performed

  • Backport applied cleanly to the implementation; the test conflict was resolved by retaining the upstream regression test.
  • cmake --build . -- -m was attempted. The build is blocked before compiling the changed service code by vendored GSL warning C4875 being promoted to an error with the installed compiler.
  • The original change passed the full PR pipeline on master, including x64/ARM64 builds and WSL1/WSL2/WSLC tests.
Copilot AI lite review requested due to automatic review settings August 14, 2026 00:34
@benhillis
Ben Hillis (benhillis) requested a review from a team as a code owner August 14, 2026 00:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Backports the MoveDistribution VHD ownership fix to release/2.7 by ensuring cross-volume moves create the destination VHD with the caller’s user SID as the default owner, eliminating the need for post-move owner rewrites. Adds a regression unit test covering same-volume moves when the VHD is owned by BUILTIN\Administrators.

Changes:

  • Update MoveDistribution to normalize the impersonation token’s default owner to the caller’s user SID and run move/rollback under that token.
  • Simplify rollback by using the same impersonation token for revert operations.
  • Add MoveVhdWithAdminOwner regression test validating non-elevated same-volume moves succeed and preserve the VHD owner.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
test/windows/UnitTests.cpp Adds regression coverage for moving a distro whose VHD is owned by BUILTIN\\Administrators.
src/windows/service/exe/LxssUserSession.cpp Adjusts move/rollback token handling to prevent elevated moves from producing admin-owned VHDs.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread test/windows/UnitTests.cpp
Comment thread src/windows/service/exe/LxssUserSession.cpp
@OneBlue

Copy link
Copy Markdown
Collaborator

If you refresh this PR it should build

Run distribution moves under a duplicated caller token whose default owner is the caller's user SID. This keeps cross-volume copies accessible without reopening the destination to rewrite its owner.

Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 14, 2026 14:33
@benhillis
Ben Hillis (benhillis) force-pushed the backport/2.7-move-distribution-owner branch from ddffe1c to abf2715 Compare August 14, 2026 14:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/windows/service/exe/LxssUserSession.cpp:936

  • userToken is used here but is not declared in MoveDistribution, which will not compile. Also, the token returned by wsl::windows::common::security::GetUserToken() is duplicated without TOKEN_ADJUST_DEFAULT, so SetTokenInformation(TokenOwner, ...) can fail with access denied even after userToken is added.

Consider creating a dedicated duplicated caller token in this method with TOKEN_ADJUST_DEFAULT and then setting TokenOwner on that token before impersonating it for the filesystem operations.

    auto tokenUser = wil::get_token_information<TOKEN_USER>(userToken.get());
    TOKEN_OWNER tokenOwner{tokenUser->User.Sid};
    THROW_IF_WIN32_BOOL_FALSE(SetTokenInformation(userToken.get(), TokenOwner, &tokenOwner, sizeof(tokenOwner)));
Copilot AI review requested due to automatic review settings August 14, 2026 20:45
Ben Hillis and others added 2 commits August 14, 2026 13:46
Save the duplicated caller token's original default owner before normalizing it for a distribution move. Restore that owner before a rollback so cross-volume rollback copies retain the caller token's prior ownership behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Capture the source VHD owner before moving it and use that SID as the duplicated token's default owner for a cross-volume rollback. This leaves ownership unchanged when the operation fails.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/windows/service/exe/LxssUserSession.cpp:937

  • GetUserToken(TokenImpersonation) duplicates the caller token without TOKEN_ADJUST_DEFAULT (see src/windows/common/WslSecurity.cpp:159-161). This means SetTokenInformation(..., TokenOwner, ...) is likely to fail with access denied at runtime, preventing distribution moves.

Consider duplicating userToken with TOKEN_ADJUST_DEFAULT for the move/rollback path and then setting TokenOwner on that duplicated token.

    auto tokenUser = wil::get_token_information<TOKEN_USER>(userToken.get());
    TOKEN_OWNER tokenOwner{tokenUser->User.Sid};
    THROW_IF_WIN32_BOOL_FALSE(SetTokenInformation(userToken.get(), TokenOwner, &tokenOwner, sizeof(tokenOwner)));
Copilot AI review requested due to automatic review settings August 14, 2026 20:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/windows/service/exe/LxssUserSession.cpp:946

  • SetTokenInformation(..., TokenOwner, ...) requires the token to have TOKEN_ADJUST_DEFAULT, but wsl::windows::common::security::GetUserToken() currently duplicates the client token without requesting TOKEN_ADJUST_DEFAULT (see src/windows/common/WslSecurity.cpp:159-162). As a result, this call will reliably fail with ERROR_ACCESS_DENIED, breaking MoveDistribution. Please either update GetUserToken() to include TOKEN_ADJUST_DEFAULT in the DuplicateTokenEx desired access mask, or re-duplicate the token locally with TOKEN_ADJUST_DEFAULT before calling SetTokenInformation.
    auto tokenUser = wil::get_token_information<TOKEN_USER>(userToken.get());
    TOKEN_OWNER tokenOwner{tokenUser->User.Sid};
    THROW_IF_WIN32_BOOL_FALSE(SetTokenInformation(userToken.get(), TokenOwner, &tokenOwner, sizeof(tokenOwner)));

MoveDistribution updates the duplicated caller token's default owner before moving a VHD. Request TOKEN_ADJUST_DEFAULT for this operation so SetTokenInformation succeeds on release/2.7.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 36bcfb50-8208-46ef-a5a3-21fb9b57b467
Copilot AI review requested due to automatic review settings August 14, 2026 22:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Suppressed comments (2)

test/windows/UnitTests.cpp:2893

  • The cleanup scope_exit lambda uses firstFolder/secondFolder but does not capture them. These are local variables (even though constexpr) and this will not compile without capturing them.
        auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [name]() {
            LxsstuLaunchWsl(std::format(L"--unregister {}", name));
            std::filesystem::remove_all(firstFolder);
            std::filesystem::remove_all(secondFolder);
        });

src/windows/common/WslSecurity.h:103

  • The GetUserToken comment no longer reflects the updated signature: callers can now request extra access rights via additionalAccess. Updating the summary helps prevent misuse and makes the new parameter discoverable.
/// <summary>
/// Returns the user token for the current client.
/// </summary>
wil::unique_handle GetUserToken(_In_ TOKEN_TYPE tokenType, _In_ RPC_BINDING_HANDLE handle = nullptr, _In_ DWORD additionalAccess = 0);

@OneBlue Blue (OneBlue) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@benhillis
Ben Hillis (benhillis) merged commit 68f601b into release/2.7 Aug 17, 2026
8 checks passed
@benhillis
Ben Hillis (benhillis) deleted the backport/2.7-move-distribution-owner branch August 17, 2026 17:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants