Skip to content

Fix VHD ownership after cross-volume move to prevent E_ACCESSDENIED#40159

Open
benhillis wants to merge 1 commit intomasterfrom
user/benhill/fix-move-vhd-ownership
Open

Fix VHD ownership after cross-volume move to prevent E_ACCESSDENIED#40159
benhillis wants to merge 1 commit intomasterfrom
user/benhill/fix-move-vhd-ownership

Conversation

@benhillis
Copy link
Copy Markdown
Member

When MoveDistribution moves a VHD across volumes, MoveFileEx copies the file and the new file's owner may not be the user's SID. This causes HcsGrantVmAccess to fail with E_ACCESSDENIED when later launching the distro, because the impersonated user lacks WRITE_DAC on the file (only implicitly granted to the owner).

Fix by explicitly setting the VHD owner to the user's SID after the move, matching what CreateVhd already does at creation time. Uses handle-based SetSecurityInfo with FILE_FLAG_OPEN_REPARSE_POINT to avoid TOCTOU races and symlink following.

Also fixes a pre-existing build break in MountTests.cpp from the test refactor (WSL2_TEST_ONLY -> WSL2_TEST_METHOD).

When MoveDistribution moves a VHD across volumes, MoveFileEx copies the
file and the new file's owner may not be the user's SID. This causes
HcsGrantVmAccess to fail with E_ACCESSDENIED when later launching the
distro, because the impersonated user lacks WRITE_DAC on the file
(only implicitly granted to the owner).

Fix by explicitly setting the VHD owner to the user's SID after the
move, matching what CreateVhd already does at creation time. Uses
handle-based SetSecurityInfo with FILE_FLAG_OPEN_REPARSE_POINT to
avoid TOCTOU races and symlink following.

Also fixes a pre-existing build break in MountTests.cpp from the test
refactor (WSL2_TEST_ONLY -> WSL2_TEST_METHOD).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@benhillis benhillis requested a review from a team as a code owner April 10, 2026 19:02
Copilot AI review requested due to automatic review settings April 10, 2026 19:02
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Fixes a WSL2 distro launch failure after cross-volume moves by ensuring the moved VHD retains the user as owner (so HcsGrantVmAccess can succeed), and updates unit tests to cover the scenario plus a build-fix in mount tests.

Changes:

  • Explicitly resets VHD owner to the user SID after MoveFileEx in MoveDistribution (and on revert) to prevent E_ACCESSDENIED.
  • Adds a unit test validating ownership and launch behavior across elevated/non-elevated move/launch combinations.
  • Fixes a mount test macro usage regression (TEST_METHOD/WSL2_TEST_ONLY -> WSL2_TEST_METHOD).

Reviewed changes

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

File Description
test/windows/UnitTests.cpp Adds coverage for VHD ownership correctness after distro moves and validates launch under different elevation contexts.
test/windows/MountTests.cpp Updates a test macro to match the refactored test infrastructure and fix build issues.
src/windows/service/exe/LxssUserSession.cpp Sets VHD owner post-move (and on rollback) using handle-based SetSecurityInfo with reparse-point protection.

auto runAsSelf = wil::run_as_self();
auto privileges = wsl::windows::common::security::AcquirePrivilege(SE_RESTORE_NAME);
THROW_IF_WIN32_ERROR(
::SetSecurityInfo(vhdHandle.get(), SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, GetUserSid(), nullptr, nullptr, nullptr));
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.

This works, but I'm a bit worried that this could be used to change the owner of a file that the caller doesn't actually own.

Instead of using GetUserSid(), could we look up the owner of the original VHD, and apply it to the newly created VHD ? At least that way the owner will be the same either way

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