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

NixOS setuid wrapper prevent running sudo in user namespace #42117

Closed
nh2 opened this issue Jun 17, 2018 · 28 comments · Fixed by #231673
Closed

NixOS setuid wrapper prevent running sudo in user namespace #42117

nh2 opened this issue Jun 17, 2018 · 28 comments · Fixed by #231673

Comments

@nh2
Copy link
Contributor

nh2 commented Jun 17, 2018

On NixOS 18.03:

$ sudo -u nobody echo hi
hi

$ /run/current-system/sw/bin/unshare -Upf --map-root-user -- sudo -u nobody echo hello
sudo: /nix/store/3xsjm8rfpy0ysfjs1pcybj33fsigszgp-wrapper.c:203: main: Assertion `!(st.st_mode & S_ISUID) || (st.st_uid == geteuid())' failed.
Segmentation fault

The assertion in question is this:

assert(!(st.st_mode & S_ISUID) || (st.st_uid == geteuid()));

If I'm able to to run sudo -u nobody outside the user namespace, why should I lose this capability inside a user namespace where I am root?

Could the assertion be safely relaxed so that I can still drop privileges to nobody inside my faked root environment (using sudo, after executing some commands as that fake root user)?

CC @ixmatus

@Ekleog
Copy link
Member

Ekleog commented Oct 28, 2018

Note: this breaks with all security wrappers, not just sudo (just duped with su in #49100)

@Chiiruno
Copy link
Contributor

I get the same problem with steam-run.
(also did this with sudo, same thing)

steam-run su
su: /nix/store/v6l2sacryfr88yqq0pq7sia8wfgm9q31-wrapper.c:203: main: Assertion `!(st.st_mode & S_ISUID) || (st.st_uid == geteuid())' failed.

Is there any way around this?

@ixmatus
Copy link
Contributor

ixmatus commented Dec 24, 2018

Sorry for the very late reply, the original Github issue email message must have got lost in my inbox :-/

It has been a while since I've looked at the wrapper code so I will need to familiarize myself first before I can provide an answer to the question asking if it is safe to relax the assertion. I'll see if I can spend some time doing that later today.

@nyarly
Copy link
Contributor

nyarly commented May 20, 2019

Pinging this: I'm trying to use exim from a Rails app run under systemd, and I trigger this same assertion.

@scintill
Copy link

scintill commented Dec 8, 2019

Running the activation script in a chroot in the namespace creates wrappers with the right ownership (though it also reported other errors.) Unfortunately, in the case of trying to drop to regular user with su or chroot, I then get setgid: Invalid argument or chroot: failed to set supplemental groups: Operation not permitted. I believe it has to do with the kernel checking gid_map, but don't understand more than that yet.

Edit: if you're already root in the namespace, you can also just bypass the wrapper (execute the path in e.g. su.real), but I ran into issues that are probably not strictly NixOS-specific, such as the above, or sudo bailing because it's .so files are not owned by root as viewed from within the namespace.

@bachp bachp mentioned this issue Mar 26, 2020
10 tasks
@stale
Copy link

stale bot commented Jun 15, 2020

Thank you for your contributions.

This has been automatically marked as stale because it has had no activity for 180 days.

If this is still important to you, we ask that you leave a comment below. Your comment can be as simple as "still important to me". This lets people see that at least one person still cares about this. Someone will have to do this at most twice a year if there is no other activity.

Here are suggestions that might help resolve this more quickly:

  1. Search for maintainers and people that previously touched the related code and @ mention them in a comment.
  2. Ask on the NixOS Discourse.
  3. Ask on the #nixos channel on irc.freenode.net.

@stale stale bot added the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Jun 15, 2020
@vs49688
Copy link
Contributor

vs49688 commented Nov 5, 2020

Still a problem, just hit this on 20.03 when trying to use Gitea with nullmailer.

@stale stale bot removed the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Nov 5, 2020
@tobiasBora
Copy link
Contributor

I also get the same error, but when running a normal appImage (appimage runs fuse):

$ nix-shell -p "(steam.override { extraPkgs = pkgs: [pkgs.fuse]; nativeOnly = true;}).run"
$ steam-run bash
bash-4.4$ ./LittleWeeb-0.4.0.303.AppImage 
fusermount: /nix/store/v6l2sacryfr88yqq0pq7sia8wfgm9q31-wrapper.c:203: main: Assertion `!(st.st_mode & S_ISUID) || (st.st_uid == geteuid())' failed.

@nixos-discourse
Copy link

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/help-with-a-derivation-package/8686/6

@legendofmiracles
Copy link
Contributor

The same happens to nixos-enter when run without root.

@jbalme
Copy link
Contributor

jbalme commented May 2, 2021

Bubblewrap breaks setuid inside containers by design which is what causes the check to fail. Unfortunately, this means that even if the check were removed, the functionality that requires setuid in the first place would just fail later down the line.

The only way around this would be passing a message to a setuid binary on the host, as Flatpak does with flatpak-spawn.

@tobiasBora
Copy link
Contributor

tobiasBora commented May 2, 2021 via email

@jbalme
Copy link
Contributor

jbalme commented May 2, 2021

Nix runs on more than just NixOS and many distros do not have user namespaces enabled for security reasons.

@Kreyren
Copy link
Contributor

Kreyren commented Jun 13, 2021

I seem to have this issue in #126744 (set as duplicate of this issue)

@Atemu
Copy link
Member

Atemu commented Jun 24, 2021

Duplicate with some more discussion and repro steps: #69338

@jbalme
Copy link
Contributor

jbalme commented Jun 25, 2021

I did some looking into making a unprivileged userns container with unshare, and setuid is non-trivial to work there too. It will be possible to get setuid to a "fake" root, but getting "real" root inside the container doesn't seem possible, as "real" root no longer has uid 0 inside the container.

This is probably by design - if a user can create an arbitrary container with an arbitrary host setuid binary, they can surely design the container such that they can escalate privileges (eg. by swapping out libc out from under the setuid binary.)

I suppose we could look into a privileged mountns script that drops back to the capabilities of the calling user.

@rnhmjoj
Copy link
Contributor

rnhmjoj commented Jul 1, 2021

Just found this in a different situation:

unshare -mr /run/current-system/sw/bin/mount --bind a b   # WORKS
unshare -mr /run/wrappers/bin/mount --bind a b   # FAILS

Can't we at least change the wrapper to check for an unshared user namespace and call directly the real binary? It's pretty easy to detect by looking at /proc/self/ns/user.

@jbalme
Copy link
Contributor

jbalme commented Jul 2, 2021

Can't we at least change the wrapper to check for an unshared user namespace and call directly the real binary? It's pretty easy to detect by looking at /proc/self/ns/user.

That will only work if we're root in the container, and only for things that a fake root can do (mounts inside the container, but not bind to port 80 or capture packets/trace from host processes, etc...)

Correct me if I'm wrong, but the primary use case for userns on Nix is to emulate a FHS distro, but while preserving the user's environment and Nix functionality, is it not? I do have to wonder if we're simply using the wrong tool for that.

@nixos-discourse
Copy link

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/build-a-yocto-rootfs-inside-nix/2643/28

@jraygauthier
Copy link
Member

@matthewbauer: Might be related:
Was bitten by this when attempting to deploy a script that used sudo alongside with its dependency using nix-bundle. Found no way to make sudo available to the bundled script. Only workaround I found was to adapt my script so that sudo is not required (root access already available) and requiring my client to invoke the bundle using sudo (external to the bundle).

@nixos-discourse
Copy link

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/build-a-yocto-rootfs-inside-nix/2643/29

@futile
Copy link
Contributor

futile commented Nov 19, 2021

Stumbled upon this as well. Thanks @rnhmjoj, your comment lead me to this general workaround:

$ PATH="/run/current-system/sw/bin:$PATH" ./command-that-runs-in-userns.sh

This might be overly generic, or might need to be adapted in combination with other environments etc., but seems like a simple workaround.

Edit:

This version might be a bit cleaner:

$ PATH=${PATH//:\/run\/wrappers\/bin/} ./command-that-runs-in-userns.sh

It simply removes all entries /run/wrappers/bin from PATH (and it assumes that there are entries before and after it in PATH) and thus doesn't otherwise reorder entries.

Edit: Of course this doesn't work for fusermount/fusermount3, because the path is hard-compiled into the executable there...:

export NIX_CFLAGS_COMPILE="-DFUSERMOUNT_DIR=\"/run/wrappers/bin\""

@Atemu
Copy link
Member

Atemu commented Dec 17, 2021

I've had a look into how Flatpak solves this issue and it seems like most apps use Polkit to authenticate. SteamVR (the main reason I'm here) uses it too.

AFAIUI, it's an IPC-based privilege escalation mechanism which enables it to work in containers. It needs a privileged daemon on the host of course though.

Perhaps we could build a sudo substitute on top of polkit?

@CMCDragonkai
Copy link
Member

This is quite annoying, it's not explained anywhere that unshare basically doesn't work on NixOS due to these wrappers. At least this should be documented somewhere and the fix is: #42117 (comment)

j-lgs added a commit to j-lgs/terraform-provider-talos that referenced this issue Jun 6, 2022
The fix is for issue NixOS/nixpkgs#42117
where the unshare in the normal path cannot perform a bind mount
inside a fakeroot user namespace on NixOS. This is required to ensure
that DNS works properly inside the test environment.
@Jayman2000
Copy link
Contributor

Jayman2000 commented Aug 21, 2022

I created an FHS environment so that I could run some #!/bin/bash scripts, and I ran into this bug. The workaround that I came up with is to have the user run

sudo nix-shell

, and then, once the shell starts, run

sudo -u <their-username> bash

I also created an example implementation of this workaround.

jktjkt added a commit to CESNET/velia that referenced this issue Feb 8, 2023
On my NixOS, `mount` is a SUID wrapper which fails in a user NS with our
UID mapping, like this:

 Assertion `!(st.st_mode & S_ISUID) || (st.st_uid == geteuid())` in NixOS's wrapper.c failed.

That's because in the created NS, the `/run/wrappers/bin/mount` appears
to be owned by `nobody:nogroup`. Fortunately, there's also the
`/run/current-system/sw/bin/mount` which does not involve any fancy
wrappers. So just let me pass
`-DMOUNT_EXECUTABLE=/run/current-system/sw/bin/mount` in my local build
script.

Bug: NixOS/nixpkgs#42117 (comment)
Change-Id: If5c601981c69bc179e5e413cc6692a56db65529d
@symphorien
Copy link
Member

see #231673

@nixos-discourse
Copy link

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/cannot-start-rootless-podman-compose-from-dynamic-user-systemd-service/34081/1

@nixos-discourse
Copy link

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/sudo-not-working-inside-a-buildfhsuserenv-no-new-privileges-flag/38971/4

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

Successfully merging a pull request may close this issue.