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
{ \