@samitouri / QOSAMI-WSL / commits / 19f06f9f

virtiofs: fix an issue where if the VM is launched by an elevated user, non-elevated shells will have elevated virtiofs access. (#13877)

* virtiofs: fix an issue where if the VM is launched by an elevated user, non-elevated shells will have elevated virtiofs access. * rename keelAlive -> keepAlive --------- Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>

Ben Hillis committed Dec 11, 2025 at 15:21 UTC 19f06f9f51c6e65e93e689c680adf1f1f6924cf4
2 files changed +71 -6
src/windows/service/exe/WslCoreVm.cpp
+4 -2
@@ -1793,8 +1793,10 @@ void WslCoreVm::InitializeGuest()
1793 {
1794 try
1795 {
1796 - m_guestDeviceManager->AddSharedMemoryDevice(
1797 - VIRTIO_FS_CLASS_ID, L"wslg", L"wslg", WSLG_SHARED_MEMORY_SIZE_MB, m_userToken.get());
1796 + // Use the appropriate virtiofs class ID based on m_userToken elevation.
1797 + const bool admin = wsl::windows::common::security::IsTokenElevated(m_userToken.get());
1798 + const GUID classId = admin ? VIRTIO_FS_ADMIN_CLASS_ID : VIRTIO_FS_CLASS_ID;
1799 + m_guestDeviceManager->AddSharedMemoryDevice(classId, L"wslg", L"wslg", WSLG_SHARED_MEMORY_SIZE_MB, m_userToken.get());
1800 m_sharedMemoryRoot = std::format(L"WSL\\{}\\wslg", m_machineId);
1801 }
1802 CATCH_LOG()
test/windows/DrvFsTests.cpp
+67 -4
@@ -276,7 +276,7 @@ public:
276 SKIP_TEST_ARM64();
277
278 TerminateDistribution();
279 - WslKeepAlive keelAlive;
279 + WslKeepAlive keepAlive;
280
281 ValidateDrvfsMounts(CREATE_UNICODE_ENVIRONMENT | EXTENDED_STARTUPINFO_PRESENT, Mode);
282 }
@@ -288,7 +288,7 @@ public:
288 SKIP_TEST_ARM64();
289
290 TerminateDistribution();
291 - WslKeepAlive keelAlive;
291 + WslKeepAlive keepAlive;
292
293 ValidateDrvfsMounts(CREATE_UNICODE_ENVIRONMENT | EXTENDED_STARTUPINFO_PRESENT | CREATE_NEW_CONSOLE, Mode);
294 }
@@ -302,7 +302,7 @@ public:
302 TerminateDistribution();
303
304 const auto nonElevatedToken = GetNonElevatedToken();
305 - WslKeepAlive keelAlive(nonElevatedToken.get());
305 + WslKeepAlive keepAlive(nonElevatedToken.get());
306
307 ValidateDrvfsMounts(CREATE_UNICODE_ENVIRONMENT | EXTENDED_STARTUPINFO_PRESENT, Mode);
308 }
@@ -316,11 +316,37 @@ public:
316 TerminateDistribution();
317
318 const auto nonElevatedToken = GetNonElevatedToken();
319 - WslKeepAlive keelAlive(nonElevatedToken.get());
319 + WslKeepAlive keepAlive(nonElevatedToken.get());
320
321 ValidateDrvfsMounts(CREATE_UNICODE_ENVIRONMENT | EXTENDED_STARTUPINFO_PRESENT | CREATE_NEW_CONSOLE, Mode);
322 }
323
324 + void DrvfsMountElevatedSystemDistroEnabled(DrvFsMode Mode)
325 + {
326 + WSL2_TEST_ONLY();
327 + WINDOWS_11_TEST_ONLY(); // TODO: Enable on Windows 10 when virtio support is added
328 + SKIP_TEST_ARM64();
329 +
330 + WslConfigChange config(LxssGenerateTestConfig({.guiApplications = true, .drvFsMode = Mode}));
331 + WslKeepAlive keepAlive;
332 +
333 + ValidateDrvfsMounts(CREATE_UNICODE_ENVIRONMENT | EXTENDED_STARTUPINFO_PRESENT, Mode);
334 + }
335 +
336 + void DrvfsMountNonElevatedSystemDistroEnabled(DrvFsMode Mode)
337 + {
338 + WSL2_TEST_ONLY();
339 + WINDOWS_11_TEST_ONLY(); // TODO: Enable on Windows 10 when virtio support is added
340 + SKIP_TEST_ARM64();
341 +
342 + WslConfigChange config(LxssGenerateTestConfig({.guiApplications = true, .drvFsMode = Mode}));
343 +
344 + const auto nonElevatedToken = GetNonElevatedToken();
345 + WslKeepAlive keepAlive(nonElevatedToken.get());
346 +
347 + ValidateDrvfsMounts(CREATE_UNICODE_ENVIRONMENT | EXTENDED_STARTUPINFO_PRESENT, Mode);
348 + }
349 +
350 static void XattrDrvFs(DrvFsMode Mode)
351 {
352 SKIP_TEST_ARM64();
@@ -946,6 +972,31 @@ private:
972
973 const auto nonElevatedToken = GetNonElevatedToken();
974 validate(nonElevatedType, nonElevatedToken.get());
975 +
976 + // Elevated token should be able to create files at the root of the drive (/mnt/c)
977 + {
978 + const auto commandLine =
979 + LxssGenerateWslCommandLine(L"touch /mnt/c/elevated_test_file.tmp && rm /mnt/c/elevated_test_file.tmp");
980 +
981 + wsl::windows::common::SubProcess process(nullptr, commandLine.c_str(), CreateProcessFlags);
982 + process.SetToken(nullptr);
983 + process.SetShowWindow(SW_HIDE);
984 +
985 + const auto output = process.RunAndCaptureOutput();
986 + VERIFY_ARE_EQUAL(0, output.ExitCode, L"Elevated token should be able to create files at /mnt/c");
987 + }
988 +
989 + // Non-elevated token should NOT be able to create files at the root of the drive (/mnt/c)
990 + {
991 + const auto commandLine = LxssGenerateWslCommandLine(L"touch /mnt/c/nonelevated_test_file.tmp");
992 +
993 + wsl::windows::common::SubProcess process(nullptr, commandLine.c_str(), CreateProcessFlags);
994 + process.SetToken(nonElevatedToken.get());
995 + process.SetShowWindow(SW_HIDE);
996 +
997 + const auto output = process.RunAndCaptureOutput();
998 + VERIFY_ARE_NOT_EQUAL(0, output.ExitCode, L"Non-elevated token should NOT be able to create files at /mnt/c (C:\\)");
999 + }
1000 }
1001
1002 static VOID VerifyDrvFsSymlink(const std::wstring& Path, const std::wstring& ExpectedTarget, bool Directory)
@@ -1198,6 +1249,18 @@ class WSL1 : public DrvFsTests
1249 WSL2_TEST_ONLY(); \
1250 DrvFsTests::DrvfsMountNonElevatedDifferentConsole(DrvFsMode::##_mode##); \
1251 } \
1252 +\
1253 + TEST_METHOD(DrvfsMountElevatedSystemDistroEnabled) \
1254 + { \
1255 + WSL2_TEST_ONLY(); \
1256 + DrvFsTests::DrvfsMountElevatedSystemDistroEnabled(DrvFsMode::##_mode##); \
1257 + } \
1258 +\
1259 + TEST_METHOD(DrvfsMountNonElevatedSystemDistroEnabled) \
1260 + { \
1261 + WSL2_TEST_ONLY(); \
1262 + DrvFsTests::DrvfsMountNonElevatedSystemDistroEnabled(DrvFsMode::##_mode##); \
1263 + } \
1264 \
1265 TEST_METHOD(XattrDrvFs) \
1266 { \