mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-06-05 21:03:40 +00:00
nixos/shadow: use file capabilities for newuidmap/newgidmap
Writing a multi-line /proc/<pid>/[ug]id_map only requires
CAP_SETUID/CAP_SETGID over the parent user namespace, not full root.
shadow's own --with-fcaps install mode (70971457b761) sets exactly
cap_setuid+ep / cap_setgid+ep, and Arch, Fedora and Debian have shipped
these binaries with file capabilities instead of setuid for years.
The setuid variant already drops to the same single capability before
the uid_map write (see lib/idmapping.c), so the privilege at the point
attacker-controlled data reaches the kernel is unchanged. The reduction
is in the startup window: with file capabilities the process never has
euid 0 and never holds the full capability set during NSS lookups,
/etc/subuid parsing and /proc/<pid> opening.
The only functional difference is that mapping host uid 0 into a child
namespace additionally needs CAP_SETFCAP, which the setuid path got
implicitly. NixOS never puts uid 0 into auto-allocated subuid ranges,
and granting it manually is a deliberate root-equivalent configuration;
the release notes document the override for that case.
nixosTests.{shadow,podman,docker-rootless} pass; the latter two
exercise newuidmap/newgidmap via rootless containers.
Supersedes #461172.
Co-authored-by: Rasheeq Azad <rasheeqhere@gmail.com>
This commit is contained in:
@@ -24,4 +24,4 @@
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
||||
- Create the first release note entry in this section!
|
||||
- The `newuidmap` and `newgidmap` security wrappers are now installed with `cap_setuid`/`cap_setgid` file capabilities instead of the setuid-root bit, matching shadow's `--with-fcaps` install mode and other major distributions. Rootless containers (podman, docker-rootless, unprivileged user namespaces) are unaffected. The only behavioural change is that mapping host uid 0 via `/etc/subuid` (which NixOS never configures by default) additionally requires `cap_setfcap`; users who explicitly grant uid 0 in a subuid range can restore the previous behaviour with `security.wrappers.newuidmap.capabilities = lib.mkForce "cap_setuid,cap_setfcap+ep";`.
|
||||
|
||||
@@ -267,13 +267,22 @@ in
|
||||
group = "root";
|
||||
inherit source;
|
||||
};
|
||||
mkCapRoot = capabilities: source: {
|
||||
inherit capabilities source;
|
||||
owner = "root";
|
||||
group = "root";
|
||||
};
|
||||
in
|
||||
{
|
||||
su = mkSetuidRoot "${config.security.shadow.su.package}/bin/su";
|
||||
sg = mkSetuidRoot "${cfg.package.out}/bin/sg";
|
||||
newgrp = mkSetuidRoot "${cfg.package.out}/bin/newgrp";
|
||||
newuidmap = mkSetuidRoot "${cfg.package.out}/bin/newuidmap";
|
||||
newgidmap = mkSetuidRoot "${cfg.package.out}/bin/newgidmap";
|
||||
# File capabilities instead of setuid root, mirroring shadow's
|
||||
# own --with-fcaps install mode and what Arch/Fedora/Debian ship.
|
||||
# The kernel only requires CAP_SETUID/CAP_SETGID over the parent
|
||||
# userns to write a multi-line /proc/<pid>/[ug]id_map.
|
||||
newuidmap = mkCapRoot "cap_setuid+ep" "${cfg.package.out}/bin/newuidmap";
|
||||
newgidmap = mkCapRoot "cap_setgid+ep" "${cfg.package.out}/bin/newgidmap";
|
||||
}
|
||||
// lib.optionalAttrs config.users.mutableUsers {
|
||||
chsh = mkSetuidRoot "${cfg.package.out}/bin/chsh";
|
||||
|
||||
Reference in New Issue
Block a user