2801
}
2802
}
2803
2804
+ TEST_METHOD(MoveVhdOwnership)
2805
+ {
2806
+ constexpr auto name = L"move-owner-test-distro";
2807
+ constexpr auto moveElevatedFolder = L"move-owner-elevated";
2808
+ constexpr auto moveNonElevatedFolder = L"move-owner-non-elevated";
2809
+
2810
+ // Import a WSL2 distro.
2811
+ VERIFY_ARE_EQUAL(LxsstuLaunchWsl(std::format(L"--import {} . \"{}\" --version 2", name, g_testDistroPath)), 0L);
2812
+
2813
+ auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [name]() {
2814
+ LxsstuLaunchWsl(std::format(L"--unregister {}", name));
2815
+ std::filesystem::remove_all(moveElevatedFolder);
2816
+ std::filesystem::remove_all(moveNonElevatedFolder);
2817
+ });
2818
+
2819
+ auto verifyVhdOwner = [](const std::wstring& path) {
2820
+ PSID ownerSid = nullptr;
2821
+ wil::unique_hlocal descriptor;
2822
+ THROW_IF_WIN32_ERROR(GetNamedSecurityInfoW(
2823
+ path.c_str(), SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, &ownerSid, nullptr, nullptr, nullptr, &descriptor));
2824
+
2825
+ auto userToken = wil::open_current_access_token(TOKEN_QUERY);
2826
+ auto tokenUser = wil::get_token_information<TOKEN_USER>(userToken.get());
2827
+
2828
+ VERIFY_IS_TRUE(EqualSid(ownerSid, tokenUser->User.Sid));
2829
+ };
2830
+
2831
+ const auto nonElevatedToken = GetNonElevatedToken();
2832
+
2833
+ // Move as elevated, launch as non-elevated.
2834
+ // This is the primary bug scenario: MoveFileEx sets owner to BUILTIN\Administrators,
2835
+ // then HcsGrantVmAccess fails with E_ACCESSDENIED when impersonating the non-elevated user.
2836
+ {
2837
+ WslShutdown();
2838
+ VERIFY_ARE_EQUAL(LxsstuLaunchWsl(std::format(L"--manage {} --move {}", name, moveElevatedFolder)), 0L);
2839
+
2840
+ auto vhdPath = std::format(L"{}\\ext4.vhdx", moveElevatedFolder);
2841
+ VERIFY_IS_TRUE(std::filesystem::exists(vhdPath));
2842
+ verifyVhdOwner(vhdPath);
2843
+
2844
+ WslShutdown();
2845
+ auto [out, err] = LxsstuLaunchWslAndCaptureOutput(std::format(L"-d {} echo ok", name), 0, nullptr, nonElevatedToken.get());
2846
+ VERIFY_ARE_EQUAL(out, L"ok\n");
2847
+ }
2848
+
2849
+ // Move as non-elevated, launch as elevated.
2850
+ {
2851
+ WslShutdown();
2852
+ VERIFY_ARE_EQUAL(
2853
+ LxsstuLaunchWsl(
2854
+ std::format(L"--manage {} --move {}", name, moveNonElevatedFolder),
2855
+ nullptr,
2856
+ nullptr,
2857
+ nullptr,
2858
+ nonElevatedToken.get()),
2859
+ 0L);
2860
+
2861
+ auto vhdPath = std::format(L"{}\\ext4.vhdx", moveNonElevatedFolder);
2862
+ VERIFY_IS_TRUE(std::filesystem::exists(vhdPath));
2863
+ verifyVhdOwner(vhdPath);
2864
+
2865
+ WslShutdown();
2866
+ auto [out, err] = LxsstuLaunchWslAndCaptureOutput(std::format(L"-d {} echo ok", name));
2867
+ VERIFY_ARE_EQUAL(out, L"ok\n");
2868
+ }
2869
+
2870
+ // Also launch as non-elevated after the non-elevated move.
2871
+ {
2872
+ WslShutdown();
2873
+ auto [out, err] = LxsstuLaunchWslAndCaptureOutput(std::format(L"-d {} echo ok", name), 0, nullptr, nonElevatedToken.get());
2874
+ VERIFY_ARE_EQUAL(out, L"ok\n");
2875
+ }
2876
+ }
2877
+
2878
WSL2_TEST_METHOD(Resize)
2879
{
2880
constexpr auto name = L"resize-test-distro";