Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
23 changes: 23 additions & 0 deletions src/linux/init/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,29 @@ int GenerateSystemdUnits(int Argc, char** Argv)
// When multiple distros are running, the second distro's getty fails because the tty is already held.
THROW_LAST_ERROR_IF(symlink("/dev/null", std::format("{}/console-getty.service", installPath).c_str()) < 0);

if (automountRoot.empty() || automountRoot.back() != '/')
{
automountRoot += '/';
}

const auto sharedMountPath = automountRoot + "wsl";
const auto mountGuardUnitContent = std::format(
R"(# Note: This file is generated by WSL to prevent shutdown unmounts from propagating to other distributions.

[Unit]
Description=WSL Cross-Distribution Mount Guard
After=local-fs.target remote-fs.target
ConditionPathIsMountPoint={}

Comment thread
chemwolf6922 marked this conversation as resolved.
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/true
ExecStop=-/bin/mount --make-rslave {})",
sharedMountPath,
sharedMountPath);
InstallSystemdUnit(installPath, "wsl-mnt-guard", mountGuardUnitContent.c_str());

// Only create the wslg unit if both enabled in wsl.conf, and if the wslg folder actually exists.
if (enableGuiApps && access("/mnt/wslg/runtime-dir", F_OK) == 0)
{
Expand Down
40 changes: 40 additions & 0 deletions test/windows/UnitTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,46 @@ class UnitTests
}
}

WSL2_TEST_METHOD(SharedMountSurvivesDistroTermination)
{
auto validate = [&](LPCWSTR peerDistroName, const std::string& automountRoot) {
const auto extraConfig = automountRoot.empty() ? "" : std::format("[automount]\nroot={}\n", automountRoot);
const auto effectiveAutomountRoot = automountRoot.empty() ? "/mnt" : automountRoot;
const auto mountPoint = std::format(L"{}/wsl/mount-guard-test", wsl::shared::string::MultiByteToWide(effectiveAutomountRoot));

auto cleanupVm = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, []() { WslShutdown(); });
auto cleanupSystemd = EnableSystemd(extraConfig);

VERIFY_ARE_EQUAL(LxsstuLaunchWsl(std::format(L"--import {} . \"{}\" --version 2", peerDistroName, g_testDistroPath)), 0L);
auto cleanupPeer = wil::scope_exit_log(
WI_DIAGNOSTICS_INFO, [&]() { LxsstuLaunchWsl(std::format(L"--unregister {}", peerDistroName)); });

auto cleanupPeerSystemd = EnableSystemd(extraConfig, peerDistroName);

VERIFY_ARE_EQUAL(
LxsstuLaunchWsl(std::format(L"-d {} -- sh -c \"systemctl is-system-running | grep -Eq 'running|degraded'\"", peerDistroName)), 0L);

VERIFY_ARE_EQUAL(
LxsstuLaunchWsl(std::format(
L"sh -c 'mkdir -p {0} && mount -t tmpfs -o size=4M mount-guard-test {0} && echo survived > {0}/marker'", mountPoint)),
0L);
auto cleanupMount = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&]() {
LxsstuLaunchWsl(std::format(L"sh -c 'umount {0} 2>/dev/null || true; rmdir {0} 2>/dev/null || true'", mountPoint));
});

VERIFY_ARE_EQUAL(LxsstuLaunchWsl(std::format(L"-d {} -- findmnt -n {}", peerDistroName, mountPoint)), 0L);
VERIFY_ARE_EQUAL(LxsstuLaunchWsl(std::format(L"-d {} -- grep -qx survived {}/marker", peerDistroName, mountPoint)), 0L);

TerminateDistribution(peerDistroName);

VERIFY_ARE_EQUAL(LxsstuLaunchWsl(std::format(L"findmnt -n {}", mountPoint)), 0L);
VERIFY_ARE_EQUAL(LxsstuLaunchWsl(std::format(L"grep -qx survived {}/marker", mountPoint)), 0L);
};

validate(L"mount-guard-default-root-peer-test", "");
validate(L"mount-guard-custom-root-peer-test", "/wsl-test-mount");
}

WSL2_TEST_METHOD(ConfigUpdateLanguage)
{
// Validates that init populates $LANG from the distro locale configuration file.
Expand Down