@samitouri / QOSAMI-WSL / commits / 0b6391bf

Use explicit tokens for user registry access (#41245)

* Preserve caller impersonation in SetSparse Capture the caller token before accessing distribution state and use an explicit token impersonation scope for the operation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 50f7fded-45e9-4427-aedb-39a3fce37ec3 * Use explicit tokens for user registry access Require callers to provide the captured user token when opening the per-user WSL registry key. Reuse captured tokens where subsequent operations require the same identity. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 50f7fded-45e9-4427-aedb-39a3fce37ec3 * Use userToken for captured caller tokens Reuse the captured user token where later operations need the same caller identity. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 50f7fded-45e9-4427-aedb-39a3fce37ec3 --------- Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com> Copilot-Session: 50f7fded-45e9-4427-aedb-39a3fce37ec3

Ben Hillis committed Aug 4, 2026 at 19:06 UTC 0b6391bf51030926620806150961e91af5eba427
2 files changed +42 -30
src/windows/service/exe/LxssUserSession.cpp
+40 -28
@@ -565,9 +565,8 @@ LxssUserSessionImpl::LxssUserSessionImpl(_In_ PSID userSid, _In_ DWORD sessionId
565 wil::unique_hkey lxssKey;
566 wil::unique_handle userToken;
567 {
568 - auto runAsUser = wil::CoImpersonateClient();
568 userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
570 - lxssKey = wsl::windows::common::registry::OpenLxssUserKey();
569 + lxssKey = s_OpenLxssUserKey(userToken.get());
570 }
571
572 static std::atomic<DWORD> sessionCookie;
@@ -683,7 +682,8 @@ HRESULT LxssUserSessionImpl::AttachDisk(_In_ LPCWSTR Disk, _In_ ULONG Flags)
682 ExecutionContext context(Context::AttachDisk);
683
684 std::lock_guard lock(m_instanceLock);
686 - const wil::unique_hkey lxssKey = s_OpenLxssUserKey();
685 + const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
686 + const wil::unique_hkey lxssKey = s_OpenLxssUserKey(userToken.get());
687
688 // Validate that at least one WSL2 distro is installed
689 auto pred = [&](const auto& e) { return WI_IsFlagSet(e.Read(Property::Flags), LXSS_DISTRO_FLAGS_VM_MODE); };
@@ -706,7 +706,8 @@ try
706
707 WSL_LOG("ConfigureDistribution", TraceLoggingValue(DefaultUid, "DefaultUid"), TraceLoggingValue(Flags, "Flags"));
708
709 - const wil::unique_hkey lxssKey = s_OpenLxssUserKey();
709 + const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
710 + const wil::unique_hkey lxssKey = s_OpenLxssUserKey(userToken.get());
711 std::lock_guard lock(m_instanceLock);
712
713 // Ensure the distribution exists.
@@ -920,7 +921,8 @@ HRESULT LxssUserSessionImpl::MoveDistribution(_In_ LPCGUID DistroGuid, _In_ LPCW
921 _EnsureNotLocked(DistroGuid);
922
923 // Lookup the distribution configuration
923 - const auto lxssKey = s_OpenLxssUserKey();
924 + const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
925 + const auto lxssKey = s_OpenLxssUserKey(userToken.get());
926 _ValidateDistributionNameAndPathNotInUse(lxssKey.get(), Location, nullptr);
927
928 auto registration = DistributionRegistration::Open(lxssKey.get(), *DistroGuid);
@@ -1005,7 +1007,8 @@ HRESULT LxssUserSessionImpl::MoveDistribution(_In_ LPCGUID DistroGuid, _In_ LPCW
1007 HRESULT LxssUserSessionImpl::EnumerateDistributions(_Out_ PULONG DistributionCount, _Out_ LXSS_ENUMERATE_INFO** Distributions)
1008 {
1009 // Get a list of all registered distributions.
1008 - const wil::unique_hkey lxssKey = s_OpenLxssUserKey();
1010 + const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
1011 + const wil::unique_hkey lxssKey = s_OpenLxssUserKey(userToken.get());
1012 std::lock_guard lock(m_instanceLock);
1013 const auto distributions = _EnumerateDistributions(lxssKey.get(), true);
1014
@@ -1072,7 +1075,8 @@ HRESULT LxssUserSessionImpl::ExportDistribution(_In_opt_ LPCGUID DistroGuid, _In
1075 wil::unique_hkey distroKey;
1076 try
1077 {
1075 - const wil::unique_hkey lxssKey = s_OpenLxssUserKey();
1078 + const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
1079 + const wil::unique_hkey lxssKey = s_OpenLxssUserKey(userToken.get());
1080 std::lock_guard lock(m_instanceLock);
1081
1082 const auto registration = DistributionRegistration::OpenOrDefault(lxssKey.get(), DistroGuid);
@@ -1217,7 +1221,8 @@ HRESULT LxssUserSessionImpl::ExportDistribution(_In_opt_ LPCGUID DistroGuid, _In
1221 HRESULT LxssUserSessionImpl::GetDefaultDistribution(_Out_ LPGUID DefaultDistribution)
1222 try
1223 {
1220 - const wil::unique_hkey lxssKey = s_OpenLxssUserKey();
1224 + const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
1225 + const wil::unique_hkey lxssKey = s_OpenLxssUserKey(userToken.get());
1226 std::lock_guard lock(m_instanceLock);
1227 *DefaultDistribution = _GetDefaultDistro(lxssKey.get());
1228 return S_OK;
@@ -1234,7 +1239,8 @@ HRESULT LxssUserSessionImpl::GetDistributionConfiguration(
1239 _Out_ ULONG* Flags)
1240 try
1241 {
1237 - const wil::unique_hkey lxssKey = s_OpenLxssUserKey();
1242 + const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
1243 + const wil::unique_hkey lxssKey = s_OpenLxssUserKey(userToken.get());
1244 std::lock_guard lock(m_instanceLock);
1245
1246 const auto registration = DistributionRegistration::OpenOrDefault(lxssKey.get(), DistroGuid);
@@ -1271,7 +1277,8 @@ try
1277 RETURN_HR_IF(E_INVALIDARG, (WI_IsAnyFlagSet(Flags, ~LXSS_GET_DISTRO_ID_LIST_ALL)));
1278
1279 // Open the user's lxss registry key.
1274 - const wil::unique_hkey lxssKey = s_OpenLxssUserKey();
1280 + const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
1281 + const wil::unique_hkey lxssKey = s_OpenLxssUserKey(userToken.get());
1282 const bool listAll = WI_IsFlagSet(Flags, LXSS_GET_DISTRO_ID_LIST_ALL);
1283 bool distroFound = false;
1284
@@ -1321,7 +1328,8 @@ LxssUserSessionImpl::ImportDistributionInplace(_In_ LPCWSTR DistributionName, _I
1328 const std::filesystem::path path{VhdPath};
1329 RETURN_HR_IF(E_INVALIDARG, !path.is_absolute() || !wsl::windows::common::wslutil::IsVhdFile(path));
1330
1324 - const wil::unique_hkey lxssKey = s_OpenLxssUserKey();
1331 + const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
1332 + const wil::unique_hkey lxssKey = s_OpenLxssUserKey(userToken.get());
1333 std::lock_guard lock(m_instanceLock);
1334
1335 // Create a registration for the distribution.
@@ -1345,7 +1353,6 @@ LxssUserSessionImpl::ImportDistributionInplace(_In_ LPCWSTR DistributionName, _I
1353 auto configuration = s_GetDistributionConfiguration(registration);
1354
1355 // Declare a scope exit variable to clean up on failure.
1348 - const wil::unique_handle userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
1356 auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&] {
1357 {
1358 auto runAsUser = wil::impersonate_token(userToken.get());
@@ -1430,7 +1437,8 @@ HRESULT LxssUserSessionImpl::RegisterDistribution(
1437 }
1438
1439 // Impersonate the user and open their lxss registry key.
1433 - wil::unique_hkey lxssKey = s_OpenLxssUserKey();
1440 + const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
1441 + wil::unique_hkey lxssKey = s_OpenLxssUserKey(userToken.get());
1442
1443 // Determine the filesystem version. If WslFs is not enabled, downgrade
1444 // the version.
@@ -1471,7 +1479,6 @@ HRESULT LxssUserSessionImpl::RegisterDistribution(
1479 DistributionRegistration registration;
1480 LXSS_DISTRO_CONFIGURATION configuration;
1481 std::filesystem::path distributionPath;
1474 - wil::unique_handle userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
1482 auto config = _GetResultantConfig(userToken.get());
1483
1484 {
@@ -1737,7 +1744,8 @@ HRESULT LxssUserSessionImpl::RegisterDistribution(
1744 HRESULT LxssUserSessionImpl::SetDefaultDistribution(_In_ LPCGUID DistroGuid)
1745 try
1746 {
1740 - const wil::unique_hkey lxssKey = s_OpenLxssUserKey();
1747 + const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
1748 + const wil::unique_hkey lxssKey = s_OpenLxssUserKey(userToken.get());
1749
1750 // Ensure the distribution is in the installed state.
1751 std::lock_guard lock(m_instanceLock);
@@ -1757,8 +1765,9 @@ CATCH_RETURN()
1765 HRESULT LxssUserSessionImpl::SetSparse(_In_ LPCGUID DistroGuid, _In_ BOOLEAN Sparse, _In_ BOOLEAN AllowUnsafe)
1766 try
1767 {
1760 - auto runAsUser = wil::CoImpersonateClient();
1761 - const wil::unique_hkey lxssKey = s_OpenLxssUserKey();
1768 + const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
1769 + const wil::unique_hkey lxssKey = s_OpenLxssUserKey(userToken.get());
1770 + auto runAsUser = wil::impersonate_token(userToken.get());
1771 std::lock_guard lock(m_instanceLock);
1772
1773 const auto registration = DistributionRegistration::Open(lxssKey.get(), *DistroGuid);
@@ -1807,7 +1816,8 @@ HRESULT LxssUserSessionImpl::ResizeDistribution(_In_ LPCGUID DistroGuid, _In_ HA
1816 try
1817 {
1818 std::lock_guard lock(m_instanceLock);
1810 - const wil::unique_hkey lxssKey = s_OpenLxssUserKey();
1819 + const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
1820 + const wil::unique_hkey lxssKey = s_OpenLxssUserKey(userToken.get());
1821 const auto registration = DistributionRegistration::Open(lxssKey.get(), *DistroGuid);
1822 const auto configuration = s_GetDistributionConfiguration(registration);
1823 RETURN_HR_IF(WSL_E_WSL2_NEEDED, WI_IsFlagClear(configuration.Flags, LXSS_DISTRO_FLAGS_VM_MODE));
@@ -1838,7 +1848,6 @@ try
1848
1849 // Ensure VM exists and attach the VHD.
1850 _CreateVm();
1841 - const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
1851 const auto lun = m_utilityVm->AttachDisk(vhdPath.c_str(), WslCoreVm::DiskType::VHD, {}, true, userToken.get());
1852
1853 // Resize the underlying filesystem.
@@ -1869,7 +1878,8 @@ HRESULT LxssUserSessionImpl::SetVersion(_In_ LPCGUID DistroGuid, _In_ ULONG Vers
1878
1879 DistributionRegistration registration;
1880 LXSS_DISTRO_CONFIGURATION configuration;
1872 - wil::unique_hkey lxssKey = s_OpenLxssUserKey();
1881 + const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
1882 + wil::unique_hkey lxssKey = s_OpenLxssUserKey(userToken.get());
1883 try
1884 {
1885 // Ensure the distribution exists.
@@ -2332,7 +2342,8 @@ void LxssUserSessionImpl::TerminateByClientIdLockHeld(_In_ ULONG ClientId)
2342 HRESULT LxssUserSessionImpl::TerminateDistribution(_In_opt_ LPCGUID DistroGuid)
2343 try
2344 {
2335 - const wil::unique_hkey lxssKey = s_OpenLxssUserKey();
2345 + const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
2346 + const wil::unique_hkey lxssKey = s_OpenLxssUserKey(userToken.get());
2347 GUID defaultDistro;
2348 {
2349 std::lock_guard lock(m_instanceLock);
@@ -2372,7 +2383,8 @@ HRESULT LxssUserSessionImpl::UnregisterDistribution(_In_ LPCGUID DistroGuid)
2383
2384 try
2385 {
2375 - wil::unique_hkey lxssKey = s_OpenLxssUserKey();
2386 + const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
2387 + wil::unique_hkey lxssKey = s_OpenLxssUserKey(userToken.get());
2388
2389 // Set up a scope exit lambda to delete the distribution registry key
2390 // when the function exits.
@@ -2526,9 +2538,9 @@ std::shared_ptr<LxssRunningInstance> LxssUserSessionImpl::_CreateInstance(_In_op
2538 m_terminatedInstances.clear();
2539 }
2540
2529 - wil::unique_hkey lxssKey = s_OpenLxssUserKey();
2530 - DistributionRegistration registration;
2541 wil::unique_handle userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
2542 + wil::unique_hkey lxssKey = s_OpenLxssUserKey(userToken.get());
2543 + DistributionRegistration registration;
2544
2545 std::shared_ptr<LxssRunningInstance> instance;
2546 {
@@ -4034,7 +4046,8 @@ void LxssUserSessionImpl::_LaunchOOBEIfNeeded() noexcept
4046 try
4047 {
4048 // Impersonate the user and open their lxss registry key.
4037 - const wil::unique_hkey lxssKey = s_OpenLxssUserKey();
4049 + const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
4050 + const wil::unique_hkey lxssKey = s_OpenLxssUserKey(userToken.get());
4051
4052 // OOBE hasn't run if the value is not present or set to 0.
4053 if (wsl::windows::common::registry::ReadDword(lxssKey.get(), nullptr, LXSS_OOBE_COMPLETE_NAME, false) != false)
@@ -4051,7 +4064,6 @@ try
4064 return;
4065 }
4066
4054 - const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
4067 // This is needed to launch the OOBE process as the user.
4068 wil::unique_handle userTokenCreateProcess;
4069 THROW_IF_WIN32_BOOL_FALSE(::DuplicateTokenEx(
@@ -4156,9 +4168,9 @@ try
4168 }
4169 CATCH_LOG()
4170
4159 -wil::unique_hkey LxssUserSessionImpl::s_OpenLxssUserKey()
4171 +wil::unique_hkey LxssUserSessionImpl::s_OpenLxssUserKey(_In_ HANDLE UserToken)
4172 {
4161 - auto runAsUser = wil::CoImpersonateClient();
4173 + auto runAsUser = wil::impersonate_token(UserToken);
4174 return wsl::windows::common::registry::OpenLxssUserKey();
4175 }
4176
src/windows/service/exe/LxssUserSession.h
+2 -2
@@ -757,9 +757,9 @@ private:
757 static LXSS_DISTRO_CONFIGURATION s_GetDistributionConfiguration(const wsl::windows::service::DistributionRegistration& Distro, bool skipName = false);
758
759 /// <summary>
760 - /// Impersonate the user and open the lxss registry key
760 + /// Impersonate the specified user and open the lxss registry key.
761 /// </summary>
762 - static wil::unique_hkey s_OpenLxssUserKey();
762 + static wil::unique_hkey s_OpenLxssUserKey(_In_ HANDLE UserToken);
763
764 /// <summary>
765 /// Ensures the distribution name is valid.