microsoft / WSL

Issues found on WSL
https://docs.microsoft.com/windows/wsl
MIT License
17.25k stars 811 forks source link

WSLg's runtime-dir has always owner 1000 resulting in inaccessable runtime dir for default user #9689

Closed martin-rueegg closed 4 months ago

martin-rueegg commented 1 year ago

Versions

Windows Version

10.0.19045.2604

WSL Version

Kernel Version

5.15.90.1

Distro Version

Ubuntu 22.04 (with systemd enabled)

Other Software

WSL version: 1.1.3.0 Kernel version: 5.15.90.1 WSLg version: 1.0.49 MSRDC version: 1.2.3770 Direct3D version: 1.608.2-61064218 DXCore version: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp Windows version: 10.0.19045.2604

Repro Steps

[^1]: Login as root: wsl.exe -u root and then run:

    NEW_USER=new_user
    NEW_UID=1234
    sudo addgroup --gid $NEW_UID $NEW_USER
    sudo adduser --uid $NEW_UID --gid $NEW_UID --disabled-password $NEW_USER

[^2]: Still as root, run editor /etc/wsl.conf and add or adjust the following section, making sure that the default property under user section is set to new_user:

    [user]
    default=new_user

[^3]: In the same root session, run the following command:

    $(wslupath 'C:\')Windows/System32/WindowsPowerShell/v1.0/powershell.exe \
     "Get-ItemProperty 'Registry::HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Lxss\\{*}\' DistributionName" \
     "| Where-Object -Property DistributionName -eq $WSL_DISTRO_NAME" \
     "| Set-ItemProperty -Name DefaultUid -Value $(id -u $NEW_USER)"

Expected Behavior

The user's run directory ("$XDG_RUNTIME_DIR", i.e. /run/user/$UID) is read-writable and has the required sockets set up, e.g.:

$ ls -la "$XDG_RUNTIME_DIR"
total 0
drwx------ 9 new_user  new_user  280 Feb 24 15:36 .
drwxr-xr-x 3 root root  60 Feb 24 15:36 ..
srw-rw-rw- 1 new_user  new_user    0 Feb 24 15:36 bus
drwx------ 3 new_user  new_user   60 Feb 24 15:36 dbus-1
drwx------ 2 new_user  new_user   60 Feb 24 15:36 dconf
drwx------ 2 new_user  new_user  140 Feb 24 15:36 gnupg
dr-x------ 2 new_user  new_user    0 Feb 24 15:36 gvfs
drwx------ 2 new_user  new_user   40 Feb 24 15:36 gvfsd
srw-rw-rw- 1 new_user  new_user    0 Feb 24 15:36 pipewire-0
-rw-rw---- 1 new_user  new_user    0 Feb 24 15:36 pipewire-0.lock
srw-rw-rw- 1 new_user  new_user    0 Feb 24 15:36 pk-debconf-socket
drwx------ 2 new_user  new_user   80 Feb 24 15:36 pulse
srw-rw-rw- 1 new_user  new_user    0 Feb 24 15:36 snapd-session-agent.socket
drwxr-xr-x 5 new_user  new_user  140 Feb 24 15:36 systemd

It can be either

It can easily be tested with the following command, which should only return 1 entry:

findmnt "$XDG_RUNTIME_DIR"

Actual Behavior

The directory /mnt/wslg/runtime-dir is always owned UID 1000, whether or not this UID is assigned to a user in /etc/passwd.

The runtime directory is not accessible:

$ ls -la "$XDG_RUNTIME_DIR"
ls: cannot open directory '/run/user/1234/': Permission denied

In fact, runtime directory ("$XDG_RUNTIME_DIR", /run/user/$UID seems to be mounted twice[^4], at least when logging in as a user with an UID other than 1000:

user@host:~$ findmnt "$XDG_RUNTIME_DIR"
TARGET         SOURCE             FSTYPE OPTIONS
/run/user/1234 tmpfs              tmpfs  rw,nosuid,nodev,relatime,size=6565592k,nr_inodes=1641398,mode=700,uid=1234,gid=1234
/run/user/1234 none[/runtime-dir] tmpfs  rw,relatime

[^4]: I had one occasion, where there was actually only the bind mount, but not the tempfs mount. However, I was not able to reproduce that case. Might be related to the following issue: #9690.

The first would be the regular mount for that user. However, it's "shadowed" by the bind mount to /mnt/wslg/runtime-dir, despite the later being owned by another user. As such, the current user's run directory becomes inaccessible:

$ ls -ldn /mnt/wslg/runtime-dir "$XDG_RUNTIME_DIR"
drwx------ 4 1000 1000 120 Feb 24 01:03 /mnt/wslg/runtime-dir
drwx------ 4 1000 1000 120 Feb 24 01:03 /run/user/1234

If, however, the later mount is removed with sudo umount "$XDG_RUNTIME_DIR", then the "real" directory becomes "visible" and accessible and apps that require access to e.g. d-bus other sockets can now succeed:

$ ls -ldn /mnt/wslg/runtime-dir "$XDG_RUNTIME_DIR"
drwx------ 4 1000 1000 120 Feb 24 01:03 /mnt/wslg/runtime-dir
drwx------ 9 1234 1234 280 Feb 24 01:03 /run/user/1234

Further observations/remarks

Workaround

I've been able do make things work by adding the following snippet to the login script:

# make sure, XDG_RUNTIME_DIR is set
declare -i MyUID=$(id -u)
XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR:-/run/user/$MyUID}
export XDG_RUNTIME_DIR

while findmnt --shadow -n -o SOURCE "$XDG_RUNTIME_DIR" >/dev/null; do
    echo "Unmounting '$XDG_RUNTIME_DIR'" >&2
    sudo umount "$XDG_RUNTIME_DIR"
done

Diagnostic Logs

WslLogs-2023-02-24_16-35-04.zip

martin-rueegg commented 1 year ago

If this issue should actually be filed against microsoft/wslg, happy to create it there again.

cerebrate commented 1 year ago

This and related runtime dir issues have, unfortunately, been something of a long-running issue (see #8918 and #9025, primarily).

I think the best (most functionality-preserving) current solution is the one I espouse here, in which overlayfs is used to give every user/uid access to their own user runtime directory as in native Linux, but in which the WSLg sockets are effectively made to appear in all of them.

cforce commented 1 year ago

Same here ..really annoying

microsoft-github-policy-service[bot] commented 4 months ago

This issue has been automatically closed since it has not had any activity for the past year. If you're still experiencing this issue please re-file this as a new issue or feature request.

Thank you!