Skip to content

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

Open
Ben Hillis (benhillis) wants to merge 5 commits into
release/2.7from
backport/2.7-move-distribution-owner
Open

[release/2.7] Fix VHD ownership during distribution moves#41354
Ben Hillis (benhillis) wants to merge 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);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants