Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UAC elevated / basic level of wslhost.exe cause different mount "namespaces" #9690

Closed
martin-rueegg opened this issue Feb 24, 2023 · 1 comment

Comments

@martin-rueegg
Copy link

martin-rueegg commented Feb 24, 2023

Versions

Windows Version

10.0.19045.2604

WSL Version

  • WSL 2

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

Docker Desktop 4.16.3

Repro Steps

Prerequisites

  • make sure, Docker Desktop is not running1
  • make sure your user is not an Administrator on your local machine
  • make sure you do not use a user-defined kernel in .wslconfig
  • optionally, enable the debug console (set debugConsole=true in your .wslconfig)

Preparation

  • open a non-elevated console (i.e. not run as Administrator!)
  • open an elevated console (run as Administrator)

Common steps to test the different scenarios below

  1. shut down WSL completely:
    wsl.exe --shutdown
    
  2. Optionally, verify that there is no running wslhost.exe on your machin (or as your user)
  3. in the elevated console, attach a whole drive (or presumably the same with only a partition) to the WSL VM:
    wsl.exe --mount \\.\PHYSICALDRIVE1 --bare
    
    This will start up the UVM with admin privileges.

Scenario 1: initiate linux session from elevated wsl.exe within 60 seconds

  • Follow the common preparation steps as indicated above
  • Once the UVM has started and there is no more output in the debug console (approx. 3-5 seconds)
    but before 60 seconds have passed, go to the elevated console and start a linux session: wsl.exe "~"
  • once the prompt is ready, start a second login from your non-elevated console: wsl.exe "~"
  • Then, in both linux sessions, run the following command
    ls -ldn /mnt/wslg/runtime-dir "$XDG_RUNTIME_DIR" \
    && echo \
    && ( findmnt "$XDG_RUNTIME_DIR" || echo "no mount found for '$XDG_RUNTIME_DIR'" )
    

Scenario 2: initiate linux session from non-elevated wsl.exe within 60 seconds

  • Follow the common preparation steps as indicated above
  • Once the UVM has started and there is no more output in the debug console (approx. 3-5 seconds)
    but before 60 seconds have passed, go to the non-elevated console and start a linux session: wsl.exe "~"
  • once the prompt is ready, start a second login from your elevated console: wsl.exe "~"
  • Again, in both linux sessions, run the following command
    ls -ldn /mnt/wslg/runtime-dir "$XDG_RUNTIME_DIR" \
    && echo \
    && ( findmnt "$XDG_RUNTIME_DIR" || echo "no mount found for '$XDG_RUNTIME_DIR'" )
    

Scenario 3: initiate linux session from non-elevated wsl.exe after the UVM2 has stopped (60+ seconds)

  • Follow the common preparation steps as indicated above
  • Once the UVM has started and there is no more output in the debug console (approx. 3-5 seconds)
    start counting further 60 seconds3 before going to the non-elevated console and start a linux session: wsl.exe "~"
  • once the prompt is ready, start a second login from your elevated console: wsl.exe "~"
  • Again, in both linux sessions, run the following command
    ls -ldn /mnt/wslg/runtime-dir "$XDG_RUNTIME_DIR" \
    && echo \
    && ( findmnt "$XDG_RUNTIME_DIR" || echo "no mount found for '$XDG_RUNTIME_DIR'" )
    

Expected Behavior

  • In short, I would expect that it makes no difference if I run wsl.exe from a privileged or unprivileged or restricted context
  • And even more so, that this behavior is consistent, whether or not I start the user session within the 60 seconds or not.

Hence,

  • In all different scenarios, the login sessions of the default user should have all mounts available, independent of the trust level the launching wsl.exe
  • Also, there would only be one mount namespace per distro (apart from user-level mounts with e.g. fuse)
  • Hence, changes to dose mounts would be visible/reflected in all sessions, independent of their trust level in windows

Please note: using wsl.exe --mount in privileged mode is required, as otherwise the process would not have the right to access the drive/partition).

Further more I would expect the /mnt/wslg/runtime-dir to be owned by the default user as specified in '/etc/wsl.conf` (or if not existent the one defined in the windows registry for that distribution). But this might be an issue related to #9689.

Actual Behavior

Scenario 1: initiate linux session from elevated wsl.exe within 60 seconds

  • Output from the elevated and the non-elevated sessions are identical:
    $ ls -ldn /mnt/wslg/runtime-dir "$XDG_RUNTIME_DIR" && echo && findmnt "$XDG_RUNTIME_DIR"
    drwx------ 4 1000 1000 120 Feb 24 17:35 /mnt/wslg/runtime-dir
    drwx------ 4 1000 1000 120 Feb 24 17:35 /run/user/1234/
    
    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
    
    However, after fixing the issue with the double mount (see issue #) in one session, the un-mount is only reflected in this session, but not the other:
    $ ls -ldn /mnt/wslg/runtime-dir "$XDG_RUNTIME_DIR" && echo && findmnt "$XDG_RUNTIME_DIR"
    drwx------ 4 1000 1000 120 Feb 24 17:35 /mnt/wslg/runtime-dir
    drwx------ 9 1234 1234 280 Feb 24 17:35 /run/user/1234/
    
    TARGET         SOURCE FSTYPE OPTIONS
    /run/user/1234 tmpfs  tmpfs  rw,nosuid,nodev,relatime,size=6565592k,nr_inodes=1641398,mode=700,uid=1234,gid=1234
    

Scenario 2: initiate linux session from non-elevated wsl.exe within 60 seconds

  • Output from the non-elevated session:
    $ ls -ldn /mnt/wslg/runtime-dir "$XDG_RUNTIME_DIR" && echo && ( findmnt "$XDG_RUNTIME_DIR" || echo "no mount found for '$XDG_RUNTIME_DIR'" )
    drwx------ 4 1000 1000 120 Feb 24 18:05 /mnt/wslg/runtime-dir
    drwx------ 2    0    0  40 Feb 24 18:05 /run/user/1574/
    
    no mount found for '/run/user/1574/'
    
  • Output from the non-elevated session:
    $ ls -ldn /mnt/wslg/runtime-dir "$XDG_RUNTIME_DIR" && echo && findmnt "$XDG_RUNTIME_DIR"
    drwx------ 4 1000 1000 120 Feb 24 17:35 /mnt/wslg/runtime-dir
    drwx------ 4 1000 1000 120 Feb 24 17:35 /run/user/1234/
    
    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
    

Scenario 3: initiate linux session from non-elevated wsl.exe after the UVM2 has stopped (60+ seconds)

  • Output from the two sessions are identical - at first.
  • However, mounts or un-mounts are not reflected in the other session.
  • If you close one session and open another one from the same console, mount-changes persist

Conclusions

  • The UVM2/wslhost.exe is launched with the same user trust level as the wsl.exe that invokes the launch of the UVM.
  • If no distro is started (a user session invoked), the UVM2 turns off after 60 seconds. However, the attached drive remains "attached"
  • Depending on the trust level of a user session, different mount namespaces seem to be created.
  • The initial set of mounts is dependent on whether the initial user session matches the trust level of the UVM:
    • If the trust level of the user session is the same or higher than the one of the currently running UVM, then the mounts are as expected initially.
    • If the trust level of the initial user session is lower than the one of the UVM, no user-mounts are available
    • In both cases, mount changes are not reflected in the other namespace/trust level

Further observations

  • Another thing that I have noticed is, that when the UVM2 is launched with elevated privileges and I have enabled localhostForwarding in .wslconfig then I get the debug console spammed with the following messages:
    SecCompDispatcher: Notified for arch C000003E syscall 49 with id 8705495076337283978 for pid 2363 with args (8, 7FFD5BAAE150, 18, 0, 7FFD5BAAE4D0, 7FFD5BAADFB0)
    SecCompDispatcher: Responding to notification with id 8705495076337283978 for pid 2363, result 0
    SecCompDispatcher: Notified for arch C000003E syscall 49 with id 8705495076337283979 for pid 2363 with args (A, 7FFD5BAAE150, 17, 0, 7FFD5BAAE4D0, 7FFD5BAADFB0)
    SecCompDispatcher: Responding to notification with id 8705495076337283979 for pid 2363, result 0
    SecCompDispatcher: Notified for arch C000003E syscall 49 with id 8705495076337283980 for pid 2363 with args (8, 7FFD5BAAE150, 18, 0, 7FFD5BAAE4D0, 7FFD5BAADFB0)
    SecCompDispatcher: Responding to notification with id 8705495076337283980 for pid 2363, result 0
    
  • When attaching the drive from an elevated console, but dropping to basic user level, then I would be able to start the user session from a non-elevated console immediately with no problem, but above messages would still be shown:
    runas /trustlevel:0x20000 "C:\Windows\system32\wsl.exe --mount \\.\PHYSICALDRIVE1 --bare"
    
  • When launching the initial user session after the UVM has stopped again and doing so from an elevated console, but dropping to the basic user level like so
    runas /trustlevel:0x20000 "C:\Windows\system32\wsl.exe ~"
    
    then the windows auto-mounts are all unavailable (empty directories) and sometimes I also get an error <3>WSL (2382) ERROR: CreateProcessParseCommon:786: Failed to translate C:\Users\{username}

Further remarks

I expect that there are more than one bug involved in my scenario. I try to give as many information as I can in order to identify them.

(I do not observe the same behavior as described in #9508 though, as the connection still works stable)

Diagnostic Logs

Drives:

C:\> wmic diskdrive get Availability,Capabilities,CapabilityDescriptions,DeviceID,InterfaceType,MediaLoaded,MediaType,Model,Name,Partitions
Availability  Capabilities  CapabilityDescriptions                                       DeviceID            InterfaceType  MediaLoaded  MediaType              Model                             Name                Partitions
              {3, 4, 10}    {"Random Access", "Supports Writing", "SMART Notification"}  \\.\PHYSICALDRIVE1  SCSI           TRUE         Fixed hard disk media  KXG50PNV2T04 NVMe TOSHIBA 2048GB  \\.\PHYSICALDRIVE1  5
              {3, 4, 10}    {"Random Access", "Supports Writing", "SMART Notification"}  \\.\PHYSICALDRIVE0  SCSI           TRUE         Fixed hard disk media  PM981a NVMe SAMSUNG 2048GB        \\.\PHYSICALDRIVE0  4

Footnotes

Footnotes

  1. The only reason why I have mentioned Docker Desktop is, that while it is running it will always automatically (re)start its helper distributions (at least docker-desktop) as soon as the UVM2 is terminated (e.g. through wsl.exe --shutdown). Since Docker Desktop is unprivileged, the UVM is run in unprivileged mode. So running the wsl.exe --mount command would only attach the drive, but not elevate the priviledge of the UVM.

  2. WSL's lightweight utility virtual machine (UVM) 2 3 4 5 6

  3. Optionally, verify that there is no running wslhost.exe on your machine (or as your user) or check that the debug console shows the following message: The connection with the virtual machine or container was closed.

Copy link
Contributor

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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant