Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/windows/service/exe/HcsVirtualMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,9 @@ try
}
else
{
std::wstring options = ReadOnly ? L"ro" : L"";
// N.B. The 'metadata' option is required so the virtiofs device host persists per-file
// uid/gid in NTFS extended attributes. Without it, all files appear as root-owned.
std::wstring options = ReadOnly ? L"ro;metadata" : L"metadata";
Comment thread
halter73 marked this conversation as resolved.
Comment thread
halter73 marked this conversation as resolved.
if (!m_swiotlbOption.empty())
{
if (!options.empty())
Expand Down
37 changes: 37 additions & 0 deletions test/windows/WSLCTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3388,6 +3388,43 @@ class WSLCTests
ValidateWindowsMounts(true);
}

// Validates that virtiofs mounts preserve file ownership for non-root users (regression test for #40719).
WSLC_TEST_METHOD(WindowsMountsVirtioFsFileOwnership)
{
auto settings = GetDefaultSessionSettings(L"virtiofs-ownership-test");
WI_SetFlag(settings.FeatureFlags, WslcFeatureFlagsVirtioFs);

auto createNewSession = !WI_IsFlagSet(m_defaultSessionSettings.FeatureFlags, WslcFeatureFlagsVirtioFs);
auto session = createNewSession ? CreateSession(settings) : m_defaultSession;
Comment thread
halter73 marked this conversation as resolved.

auto testFolder = std::filesystem::current_path() / "test-folder-virtiofs-ownership";
std::filesystem::create_directories(testFolder);
auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&]() { std::filesystem::remove_all(testFolder); });

static constexpr auto mountPoint = "/virtiofs-ownership-test";

VERIFY_SUCCEEDED(session->MountWindowsFolder(testFolder.c_str(), mountPoint, false));
Comment thread
halter73 marked this conversation as resolved.
auto unmount = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&]() { session->UnmountWindowsFolder(mountPoint); });

// Create a file and chown to uid 1000:100, then verify ownership is preserved.
// Without the 'metadata' option on the virtiofs share, chown appears to succeed but
// subsequent stat reports uid=0/gid=0 because ownership is not persisted.
auto result = ExpectCommandResult(
session.get(),
{"/bin/sh", "-c", "touch /virtiofs-ownership-test/owned.txt && chown 1000:100 /virtiofs-ownership-test/owned.txt && stat -c '%u %g' /virtiofs-ownership-test/owned.txt"},
0);

VERIFY_ARE_EQUAL(result.Output[1], std::string("1000 100\n"));
Comment thread
halter73 marked this conversation as resolved.

// Verify that a file created by a non-root user retains the creator's ownership.
result = ExpectCommandResult(
session.get(),
{"/bin/sh", "-c", "rm -f /virtiofs-ownership-test/nonroot.txt && su -s /bin/sh nobody -c 'touch /virtiofs-ownership-test/nonroot.txt' && stat -c '%u' /virtiofs-ownership-test/nonroot.txt"},
0);
Comment thread
halter73 marked this conversation as resolved.
Comment thread
halter73 marked this conversation as resolved.

VERIFY_ARE_EQUAL(result.Output[1], std::string("65534\n"));
}

// Validates that VirtioFs shares are reused across mount/unmount cycles for the same Windows folder.
WSLC_TEST_METHOD(WindowsMountsVirtioFsShareReuse)
{
Expand Down