NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
17.39k stars 13.61k forks source link

SUID wrappers do not work in buildFHSUserenv.env #69338

Open JohnAZoidberg opened 4 years ago

JohnAZoidberg commented 4 years ago

Describe the bug Running sudo inside the environment of buildFHSUserenv.env does not work.

To Reproduce Steps to reproduce the behavior:

  1. Create shell.nix with
    
    { pkgs ? import <nixpkgs> {} }:

(pkgs.buildFHSUserEnv { name = "sudo-env"; targetPkgs = pkgs: with pkgs; [ sudo ]; runScript = "bash"; }).env

2. Run `nix-shell`
3. Run `sudo whoami`

**Expected behavior**
`sudo whoami` should print `root`

**Actual behaviour**

$ sudo whoami sudo: /nix/store/v6l2sacryfr88yqq0pq7sia8wfgm9q31-wrapper.c:203: main: Assertion `!(st.st_mode & S_ISUID) || (st.st_uid == geteuid())' failed. Aborted


**Additional context**
I think this is caused by the owner of `sudo` being `nobody:nogroup`:

Inside FHS env

$ ls -l /run/wrappers/bin/sudo -r-s--x--x 1 nobody nogroup 17704 Sep 22 13:08 /run/wrappers/bin/sudo

Outside FHS env

$ ls -l /run/wrappers/bin/sudo -r-s--x--x 1 root root 17704 Sep 22 15:08 /run/wrappers/bin/sudo


**Metadata**
- system: `"x86_64-linux"`                                           
- host os: `Linux 5.3.0, NixOS, 20.03pre193781.d484f2b7fc0 (Markhor)`
- multi-user?: `yes`                                                 
- sandbox: `no`                                                      
- version: `nix-env (Nix) 2.3`                                       
- nixpkgs: `/nix/store/2p5njn4s0i93s9i8pwg276ibb15ynpyn-foo`         

which is this unstable channel `nixos-20.03pre193781.d484f2b7fc0`

Maintainer information:
```yaml
# a list of nixpkgs attributes affected by the problem
attribute: buildFHSUserEnv

cc @abbradar

matthewbauer commented 4 years ago

This looks like any program with the SUID bit fails?

abbradar commented 4 years ago

Yeah, that's an implication of us using mount namespaces inside buildFHSUserEnv. Unfortunately I don't think much could be done about it: the security check that the wrapper does avoids a scenario when you craft a malicious namespace where say /etc/passwd is mounted to a file you control, and gain user privileges via sudo.

JohnAZoidberg commented 4 years ago

Yes, you're right. All SUID wrapped programs fail.

cawilliamson commented 4 years ago

This is a really major blocker for me because I'm trying to package VMware Workstation 15 for NixOS (nixpkgs) and so far I only see two options:

1.) Use an FHS environment to install VMware in to meaning to need to patch the binaries - blocked by this issue.

2.) Use patchelf to patch the binaries - this then generates a large binary and patchelf complains it cannot patch it due to a max filesize limit so basically I can't win either way!

Any ideas on how I can work around this in a way which can be pushed to nixpkgs? (i.e. not hacking random scripts and things because I obviously can't share that outside of my own system. :))

cc @abbradar - any ideas about how I can address this? Completely blocked at the moment.

stale[bot] commented 4 years ago

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.
Atemu commented 4 years ago

Still important to me.

Atemu commented 4 years ago

Could this be solved by "registering" the FHSUserenvs which are allowed to run SUID wrappers using a mechanism that requires root privileges?
That's how SUID wrappers work outside of chrootenvs, right?

setupminimal commented 4 years ago

This is important to me too - it's necessary to get fuse working inside a FHS User Env. I'll keep this issue open while I look for alternatives, and report back if I find a workaround.

noonien commented 4 years ago

This is also important to me. Some programs don't work without FHS, and, some of those require access to root-only resources.

eglaysher commented 4 years ago

This is important to me since it's in the blocking path for Steam VR stuff.

con-f-use commented 3 years ago

Just ran into this, too. Can we have a workaround or fix, please?

foosinn commented 3 years ago

Also run into this. 2-liner to reproduce:

nix-shell -E '{pkgs ? import <nixpkgs> {} }: (pkgs.buildFHSUserEnv { name = "test"; targetPkgs = pkgs: (with pkgs; [ sudo ]);}).env'
sudo whoami
hmenke commented 3 years ago

@foosinn This is actually not surprising and actually the expected behavior (at least by me), because the version of sudo that you now have in the PATH is the one from the Nix store, which does not have (and cannot have) the SUID bit set.

What is more surprising is this:

user@nixos:~$ nix-shell -E '{pkgs ? import <nixpkgs> {} }: (pkgs.buildFHSUserEnv { name = "test"; targetPkgs = _: [];}).env'
[nix-shell:~]$ which sudo
/run/wrappers/bin/sudo
[nix-shell:~]$ sudo whoami
sudo: /nix/store/yx5zifiwsc7zbd54zs7l8i4a6nrrg6wf-wrapper.c:195: main: Assertion `!(st.st_mode & S_ISUID) || (st.st_uid == geteuid())' failed.
Aborted (core dumped)

So even though the correct SUID wrapper is called it doesn't work.

N.B.: The same happens for pkgs.buildFHSUserEnvBubblewrap

Atemu commented 3 years ago

Would it be possible to hard-code the sudoers rules into tho SUID wrapper? That way there'd be no possibility of overriding them using a namespace.

Atemu commented 3 years ago

On a second thought, that probably won't work. Sudo depends on all kinds of external files which a userns could freely override.

The only viable solution I see is to have a sudo proxy on the host which a fake sudo inside an FHSEnv could communicate with and get its privileges from.

Just saw that this is a duplicate of https://github.com/NixOS/nixpkgs/issues/42117 though, so I'm closing this.

Atemu commented 1 year ago

Just realised that this is, in fact, not a duplicate as the other issue was about dropping privileges when already privileged rather than gaining privileges as is the case here.

Copying my idea from over there here:


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?

nixos-discourse commented 3 months ago

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

Atemu commented 3 months ago

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

This will actually exists soon: Systemd 256 adds support for run0. You should be able to manually create your own "run0" using systemd-run already though if anyone wants to experiment.

nixos-discourse commented 3 months ago

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/5

Atemu commented 3 months ago

Okay, so apparently polkit (via pkexec) still requires SUID and will immediately exit with pkexec must be setuid root if it doesn't have SUID.

But somehow this must be working within flatpak and friends?

Perhaps it's safe to allow SUID in any case on polkit because it does its own internal userns-aware checking using a privileged daemon that cannot be fooled by a malicious userns? Figuring this out feels like the logical next step.

zarelit commented 2 months ago

I'm linking this other issue on documenting suid wrappers because it's actually not clear how to proceed when packaging something that needs to access a suid binary, especially when this is inside any kind of jail