[release/2.7] Fix VHD ownership during distribution moves - #41354
[release/2.7] Fix VHD ownership during distribution moves#41354Ben Hillis (benhillis) wants to merge 5 commits into
Conversation
There was a problem hiding this comment.
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
MoveDistributionto 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
MoveVhdWithAdminOwnerregression 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.
|
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>
ddffe1c to
abf2715
Compare
There was a problem hiding this comment.
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
userTokenis used here but is not declared inMoveDistribution, which will not compile. Also, the token returned bywsl::windows::common::security::GetUserToken()is duplicated withoutTOKEN_ADJUST_DEFAULT, soSetTokenInformation(TokenOwner, ...)can fail with access denied even afteruserTokenis 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)));
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>
There was a problem hiding this comment.
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 withoutTOKEN_ADJUST_DEFAULT(seesrc/windows/common/WslSecurity.cpp:159-161). This meansSetTokenInformation(..., 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)));
There was a problem hiding this comment.
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 haveTOKEN_ADJUST_DEFAULT, butwsl::windows::common::security::GetUserToken()currently duplicates the client token without requestingTOKEN_ADJUST_DEFAULT(seesrc/windows/common/WslSecurity.cpp:159-162). As a result, this call will reliably fail withERROR_ACCESS_DENIED, breakingMoveDistribution. Please either updateGetUserToken()to includeTOKEN_ADJUST_DEFAULTin theDuplicateTokenExdesired access mask, or re-duplicate the token locally withTOKEN_ADJUST_DEFAULTbefore callingSetTokenInformation.
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
There was a problem hiding this comment.
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);
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
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
cmake --build . -- -mwas 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.master, including x64/ARM64 builds and WSL1/WSL2/WSLC tests.