Impersonate caller in ResizeDistribution VHD operations (#40253)
Add scoped wil::CoImpersonateClient() around VHD file operations in ResizeDistribution so that file access is checked against the calling user's permissions rather than running as SYSTEM. Both the grow and shrink paths are covered. VM operations remain as SYSTEM. Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Ben Hillis committed
Apr 21, 2026 at 21:58 UTC
3a675eb48c30f20e6eca4e883ac761fd84afbaa4
1 file changed
+18
-17
src/windows/service/exe/LxssUserSession.cpp
+18
-17
@@ -1788,47 +1788,48 @@ try
1788
std::lock_guard lock(m_instanceLock);
1789
const wil::unique_hkey lxssKey = s_OpenLxssUserKey();
1790
const auto registration = DistributionRegistration::Open(lxssKey.get(), *DistroGuid);
1791
- LXSS_DISTRO_CONFIGURATION configuration = s_GetDistributionConfiguration(registration);
1791
+ const auto configuration = s_GetDistributionConfiguration(registration);
1792
RETURN_HR_IF(WSL_E_WSL2_NEEDED, WI_IsFlagClear(configuration.Flags, LXSS_DISTRO_FLAGS_VM_MODE));
1793
1794
- const auto vhdFilePath = configuration.VhdFilePath;
1795
- if (m_utilityVm && m_utilityVm->IsVhdAttached(vhdFilePath.c_str()))
1794
+ const auto& vhdPath = configuration.VhdFilePath;
1795
+ if (m_utilityVm && m_utilityVm->IsVhdAttached(vhdPath.c_str()))
1796
{
1797
THROW_HR_WITH_USER_ERROR(WSL_E_DISTRO_NOT_STOPPED, wsl::shared::Localization::MessageVhdInUse());
1798
}
1799
1800
- auto diskHandle = wsl::core::filesystem::OpenVhd(vhdFilePath.c_str(), VIRTUAL_DISK_ACCESS_GET_INFO | VIRTUAL_DISK_ACCESS_METAOPS);
1801
- const auto diskSize = wsl::core::filesystem::GetDiskSize(diskHandle.get());
1802
-
1803
- const auto resizingLarger = NewSize > diskSize;
1804
- if (resizingLarger)
1800
+ // If growing the VHD, resize the underlying VHD file before resizing the filesystem.
1801
+ bool resizingLarger;
1802
{
1806
- wsl::core::filesystem::ResizeExistingVhd(diskHandle.get(), NewSize, RESIZE_VIRTUAL_DISK_FLAG_NONE);
1807
- }
1803
+ auto runAsUser = wil::CoImpersonateClient();
1804
+ auto diskHandle = wsl::core::filesystem::OpenVhd(vhdPath.c_str(), VIRTUAL_DISK_ACCESS_GET_INFO | VIRTUAL_DISK_ACCESS_METAOPS);
1805
+ resizingLarger = NewSize > wsl::core::filesystem::GetDiskSize(diskHandle.get());
1806
1809
- diskHandle.reset();
1807
+ if (resizingLarger)
1808
+ {
1809
+ wsl::core::filesystem::ResizeExistingVhd(diskHandle.get(), NewSize, RESIZE_VIRTUAL_DISK_FLAG_NONE);
1810
+ }
1811
+ }
1812
1813
// Ensure VM exists and attach the VHD.
1814
_CreateVm();
1815
const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
1814
- const auto lun = m_utilityVm->AttachDisk(vhdFilePath.c_str(), WslCoreVm::DiskType::VHD, {}, true, userToken.get());
1816
+ const auto lun = m_utilityVm->AttachDisk(vhdPath.c_str(), WslCoreVm::DiskType::VHD, {}, true, userToken.get());
1817
1818
// Resize the underlying filesystem.
1819
//
1820
// N.B. Passing zero as the size causes the resize to consume all available space on the block device.
1821
{
1820
- auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&] { m_utilityVm->EjectVhd(vhdFilePath.c_str()); });
1822
+ auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&] { m_utilityVm->EjectVhd(vhdPath.c_str()); });
1823
m_utilityVm->ResizeDistribution(lun, OutputHandle, resizingLarger ? 0 : NewSize);
1824
}
1825
1826
// If shrinking the VHD, resize the underlying VHD file. This is only supported for .vhdx files.
1827
//
1828
// N.B. RESIZE_VIRTUAL_DISK_FLAG_ALLOW_UNSAFE_VIRTUAL_SIZE is required because vhdmp can't validate that the minimum safe ext4 size.
1827
- if (!resizingLarger &&
1828
- wsl::shared::string::IsEqual(vhdFilePath.extension().c_str(), wsl::windows::common::wslutil::c_vhdxFileExtension, true))
1829
+ if (!resizingLarger && wsl::shared::string::IsEqual(vhdPath.extension().c_str(), wsl::windows::common::wslutil::c_vhdxFileExtension, true))
1830
{
1830
- const auto diskHandle =
1831
- wsl::core::filesystem::OpenVhd(vhdFilePath.c_str(), VIRTUAL_DISK_ACCESS_GET_INFO | VIRTUAL_DISK_ACCESS_METAOPS);
1831
+ auto runAsUser = wil::CoImpersonateClient();
1832
+ const auto diskHandle = wsl::core::filesystem::OpenVhd(vhdPath.c_str(), VIRTUAL_DISK_ACCESS_GET_INFO | VIRTUAL_DISK_ACCESS_METAOPS);
1833
wsl::core::filesystem::ResizeExistingVhd(diskHandle.get(), NewSize, RESIZE_VIRTUAL_DISK_FLAG_ALLOW_UNSAFE_VIRTUAL_SIZE);
1834
}
1835