Commit graph

88 commits

Author SHA1 Message Date
Robert Obryk c64bbd4466 nixos/security/wrappers: remove all the assertions about readlink(/proc/self/exe)
Given that we are no longer inspecting the target of the /proc/self/exe
symlink, stop asserting that it has any properties. Remove the plumbing
for wrappersDir, which is no longer used.

Asserting that the binary is located in the specific place is no longer
necessary, because we don't rely on that location being writable only by
privileged entities (we used to rely on that when assuming that
readlink(/proc/self/exe) will continue to point at us and when assuming
that the `.real` file can be trusted).

Assertions about lack of write bits on the file were
IMO meaningless since inception: ignoring the Linux's refusal to honor
S[UG]ID bits on files-writeable-by-others, if someone could have
modified the wrapper in a way that preserved the capability or S?ID
bits, they could just remove this check.

Assertions about effective UID were IMO just harmful: if we were
executed without elevation, the caller would expect the result that
would cause in a wrapperless distro: the targets gets executed without
elevation. Due to lack of elevation, that cannot be used to abuse
privileges that the elevation would give.

This change partially fixes #98863 for S[UG]ID wrappers. The issue for
capability wrappers remains.
2023-08-27 14:10:38 +02:00
Robert Obryk e3550208de nixos/security/wrappers: read capabilities off /proc/self/exe directly
/proc/self/exe is a "fake" symlink. When it's opened, it always opens
the actual file that was execve()d in this process, even if the file was
deleted or renamed; if the file is no longer accessible from the current
chroot/mount namespace it will at the very worst fail and never open the
wrong file. Thus, we can make a much simpler argument that we're reading
capabilities off the correct file after this change (and that argument
doesn't rely on things such as protected_hardlinks being enabled, or no
users being able to write to /run/wrappers, or the verification that the
path readlink returns starts with /run/wrappers/).
2023-08-27 14:10:38 +02:00
Robert Obryk 1bdbc0b0fe nixos/security/wrappers: stop using .real files
Before this change it was crucial that nonprivileged users are unable to
create hardlinks to SUID wrappers, lest they be able to provide a
different `.real` file alongside. That was ensured by not providing a
location writable to them in the /run/wrappers tmpfs, (unless
disabled) by the fs.protected_hardlinks=1 sysctl, and by the explicit
own-path check in the wrapper. After this change, ensuring
that property is no longer important, and the check is most likely
redundant.

The simplification of expectations of the wrapper will make it
easier to remove some of the assertions in the wrapper (which currently
cause the wrapper to fail in no_new_privs environments, instead of
executing the target with non-elevated privileges).

Note that wrappers had to be copied (not symlinked) into /run/wrappers
due to the SUID/capability bits, and they couldn't be hard/softlinks of
each other due to those bits potentially differing. Thus, this change
doesn't increase the amount of memory used by /run/wrappers.

This change removes part of the test that is obsoleted by the removal of
`.real` files.
2023-08-27 14:10:36 +02:00
Robert Obryk 44fde723be nixos/security/wrappers: generate a separate and more complete apparmor policy fragment for each wrapper
This change includes some stuff (e.g. reading of the `.real` file,
execution of the wrapper's target) that belongs to the apparmor policy
of the wrapper. This necessitates making them distinct for each wrapper.
The main reason for this change is as a preparation for making each
wrapper be a distinct binary.
2023-08-27 14:10:07 +02:00
Pierre Bourdon 4428f3a79a
Revert "nixos/security/wrappers: simplifications and a fix for #98863" 2023-08-24 08:35:11 +02:00
Robert Obryk ff204ca32b nixos/security/wrappers: remove all the assertions about readlink(/proc/self/exe)
Given that we are no longer inspecting the target of the /proc/self/exe
symlink, stop asserting that it has any properties. Remove the plumbing
for wrappersDir, which is no longer used.

Asserting that the binary is located in the specific place is no longer
necessary, because we don't rely on that location being writable only by
privileged entities (we used to rely on that when assuming that
readlink(/proc/self/exe) will continue to point at us and when assuming
that the `.real` file can be trusted).

Assertions about lack of write bits on the file were
IMO meaningless since inception: ignoring the Linux's refusal to honor
S[UG]ID bits on files-writeable-by-others, if someone could have
modified the wrapper in a way that preserved the capability or S?ID
bits, they could just remove this check.

Assertions about effective UID were IMO just harmful: if we were
executed without elevation, the caller would expect the result that
would cause in a wrapperless distro: the targets gets executed without
elevation. Due to lack of elevation, that cannot be used to abuse
privileges that the elevation would give.

This change partially fixes #98863 for S[UG]ID wrappers. The issue for
capability wrappers remains.
2023-08-16 11:33:22 +02:00
Robert Obryk 11ca4dcbb8 nixos/security/wrappers: read capabilities off /proc/self/exe directly
/proc/self/exe is a "fake" symlink. When it's opened, it always opens
the actual file that was execve()d in this process, even if the file was
deleted or renamed; if the file is no longer accessible from the current
chroot/mount namespace it will at the very worst fail and never open the
wrong file. Thus, we can make a much simpler argument that we're reading
capabilities off the correct file after this change (and that argument
doesn't rely on things such as protected_hardlinks being enabled, or no
users being able to write to /run/wrappers, or the verification that the
path readlink returns starts with /run/wrappers/).
2023-08-16 11:33:22 +02:00
Robert Obryk ec36e0218f nixos/security/wrappers: stop using .real files
Before this change it was crucial that nonprivileged users are unable to
create hardlinks to SUID wrappers, lest they be able to provide a
different `.real` file alongside. That was ensured by not providing a
location writable to them in the /run/wrappers tmpfs, (unless
disabled) by the fs.protected_hardlinks=1 sysctl, and by the explicit
own-path check in the wrapper. After this change, ensuring
that property is no longer important, and the check is most likely
redundant.

The simplification of expectations of the wrapper will make it
easier to remove some of the assertions in the wrapper (which currently
cause the wrapper to fail in no_new_privs environments, instead of
executing the target with non-elevated privileges).

Note that wrappers had to be copied (not symlinked) into /run/wrappers
due to the SUID/capability bits, and they couldn't be hard/softlinks of
each other due to those bits potentially differing. Thus, this change
doesn't increase the amount of memory used by /run/wrappers.
2023-08-16 11:33:22 +02:00
Guillaume Girol 0e4b8a05b2 nixos/wrappers: allow setuid and setgid wrappers to run in user namespaces
In user namespaces where an unprivileged user is mapped as root and root
is unmapped, setuid bits have no effect. However setuid root
executables like mount are still usable *in the namespace* as the user
already has the required privileges. This commit detects the situation
where the wrapper gained no privileges that the parent process did not
already have and in this case does less sanity checking. In short there
is no need to be picky since the parent already can execute the foo.real
executable themselves.

Details:
man 7 user_namespaces:
   Set-user-ID and set-group-ID programs
       When a process inside a user namespace executes a set-user-ID
       (set-group-ID) program, the process's effective user (group) ID
       inside the namespace is changed to whatever value is mapped for
       the user (group) ID of the file.  However, if either the user or
       the group ID of the file has no mapping inside the namespace, the
       set-user-ID (set-group-ID) bit is silently ignored: the new
       program is executed, but the process's effective user (group) ID
       is left unchanged.  (This mirrors the semantics of executing a
       set-user-ID or set-group-ID program that resides on a filesystem
       that was mounted with the MS_NOSUID flag, as described in
       mount(2).)

The effect of the setuid bit is that the real user id is preserved and
the effective and set user ids are changed to the owner of the wrapper.
We detect that no privilege was gained by checking that euid == suid
== ruid. In this case we stop checking that euid == owner of the
wrapper file.

As a reminder here are the values of euid, ruid, suid, stat.st_uid and
stat.st_mode & S_ISUID in various cases when running a setuid 42 executable as user 1000:

Normal case:
ruid=1000 euid=42 suid=42
setuid=2048, st_uid=42

nosuid mount:
ruid=1000 euid=1000 suid=1000
setuid=2048, st_uid=42

inside unshare -rm:
ruid=0 euid=0 suid=0
setuid=2048, st_uid=65534

inside unshare -rm, on a suid mount:
ruid=0 euid=0 suid=0
setuid=2048, st_uid=65534
2023-08-09 12:00:00 +00:00
Robert Hensing 2e2f0d28ea nixos: Use checks instead of extraDependencies
... as appropriate.

This drops a few unnecessary store paths from the system closure.
2023-05-11 21:18:38 +02:00
figsoda 6bb0dbf91f nixos: fix typos 2022-12-17 19:31:14 -05:00
Jason Yundt 17352e8995 nixos/security/wrappers: clarify required format for capabilities
Before this change, the description for
security.wrappers.<name>.capabilities made it seem like you could just
string together the names of capabilities like this:

  capabilities = "CAP_SETUID,CAP_SETGID";

In reality, each item in the list must be a full-on capability clause:

  capabilities = "CAP_SETUID=ep,CAP_SETGID+i";
2022-09-11 16:36:58 +02:00
pennae 722b99bc0e nixos/*: convert options with admonitions to MD
rendering changes only slightly, most changes are in spacing.
2022-08-31 16:36:16 +02:00
pennae 9547123258 nixos/*: convert internal option descriptions to MD
we'll have to do it eventually, may as well be now.
2022-08-31 16:32:54 +02:00
pennae ef176dcf7e nixos/*: automatically convert option descriptions
conversions were done using https://github.com/pennae/nix-doc-munge
using (probably) rev f34e145 running

    nix-doc-munge nixos/**/*.nix
    nix-doc-munge --import nixos/**/*.nix

the tool ensures that only changes that could affect the generated
manual *but don't* are committed, other changes require manual review
and are discarded.
2022-08-31 16:32:53 +02:00
Robert Hensing d00583540b
Merge pull request #184368 from DieracDelta/jr/wrappers-run-size-option
nixos/security: add size option to /run/wrappers
2022-08-14 19:13:17 +02:00
Justin Restivo 82640adbf0 nixos/security: add size option to /run/wrappers 2022-08-14 07:31:37 -07:00
pennae 423545fe48 nixos/*: normalize manpage references to single-line form
now nix-doc-munge will not introduce whitespace changes when it replaces
manpage references with the MD equivalent.

no change to the manpage, changes to the HTML manual are whitespace only.
2022-08-05 18:34:50 +02:00
pennae 2e751c0772 treewide: automatically md-convert option descriptions
the conversion procedure is simple:

 - find all things that look like options, ie calls to either `mkOption`
   or `lib.mkOption` that take an attrset. remember the attrset as the
   option
 - for all options, find a `description` attribute who's value is not a
   call to `mdDoc` or `lib.mdDoc`
 - textually convert the entire value of the attribute to MD with a few
   simple regexes (the set from mdize-module.sh)
 - if the change produced a change in the manual output, discard
 - if the change kept the manual unchanged, add some text to the
   description to make sure we've actually found an option. if the
   manual changes this time, keep the converted description

this procedure converts 80% of nixos options to markdown. around 2000
options remain to be inspected, but most of those fail the "does not
change the manual output check": currently the MD conversion process
does not faithfully convert docbook tags like <code> and <package>, so
any option using such tags will not be converted at all.
2022-07-30 15:16:34 +02:00
Mario Rodas cc73dc83b3
Revert "nixos/security/wrappers: use an assertion for the existence check" 2022-06-12 15:38:05 -05:00
Naïm Favier 39a56c7696
nixos/security/wrappers: use an assertion for the existence check
A simpler implementation of 7d8b303e3f
that uses an assertion instead of a derivation.

`pathHasContext` seems a bit better than `hasPrefix storeDir` because it
avoids a string comparison, and catches nonsense like
`"foo${pkgs.hello}bar"`.
2022-06-11 23:22:03 +02:00
Linus Heckemann 7c035dbb75
Merge pull request #156822 from xfix/wrapper-assert-argc-at-least-one
nixos/wrappers: require argc to be at least one
2022-05-16 18:52:51 +02:00
Ivan Kozik f18cc2cf02 nixos/security/wrappers: chown user:group instead of user.group to fix warnings from coreutils 9.1
activating the configuration...
setting up /etc...
chown: warning: '.' should be ':': ‘root.root’
chown: warning: '.' should be ':': ‘root.messagebus’
chown: warning: '.' should be ':': ‘root.root’
chown: warning: '.' should be ':': ‘root.root’
chown: warning: '.' should be ':': ‘root.root’
chown: warning: '.' should be ':': ‘root.root’
chown: warning: '.' should be ':': ‘root.root’
chown: warning: '.' should be ':': ‘root.root’
chown: warning: '.' should be ':': ‘root.root’
chown: warning: '.' should be ':': ‘root.root’
chown: warning: '.' should be ':': ‘root.root’
chown: warning: '.' should be ':': ‘root.root’
chown: warning: '.' should be ':': ‘root.root’
chown: warning: '.' should be ':': ‘root.root’
chown: warning: '.' should be ':': ‘root.root’
chown: warning: '.' should be ':': ‘root.root’
reloading user units for root...
2022-05-05 22:05:18 +00:00
Alyssa Ross 1176525f87 treewide: remove obsolete kernel version checks
We don't support Linux kernels older than 4.4 in Nixpkgs.
2022-02-19 21:09:19 +00:00
Konrad Borowski 2a6a3d2c47 nixos/wrappers: require argc to be at least one
setuid applications were exploited in the past with an empty
argv, such as pkexec using CVE-2021-4034.
2022-01-28 12:26:20 +01:00
Konrad Borowski 1009d6e79e nixos/wrappers: create a new assert macro that always asserts
C's assert macro only works when NDEBUG is undefined. Previously
NDEBUG was undefined incorrectly which meant that the assert
macros in wrapper.c did not work.
2022-01-28 12:26:19 +01:00
Julien Moutinho 0e5611e0be security/wrappers: remove C compiler from the nixos/security.wrappers AppArmor profile 2021-12-29 16:26:57 +01:00
Naïm Favier 2ddc335e6f
nixos/doc: clean up defaults and examples 2021-10-04 12:47:20 +02:00
rnhmjoj fedd7cd690
nixos: explicitely set security.wrappers ownership
This is slightly more verbose and inconvenient, but it forces you
to think about what the wrapper ownership and permissions will be.
2021-09-13 13:48:13 +02:00
rnhmjoj 27dcb04cde
nixos/security/wrappers: remove WRAPPER_PATH
This appears to be a leftover from 628e6a83.
2021-09-13 13:48:13 +02:00
rnhmjoj 936e8eaf41
nixos/security/wrappers: fix shell quoting 2021-09-13 13:48:12 +02:00
rnhmjoj 7d8b303e3f
nixos/security/wrappers: check that sources exist
Add a shell script that checks if the paths of all wrapped programs
actually exist to catch mistakes. This only checks for Nix store paths,
which are always expected to exist at build time.
2021-09-13 10:38:04 +02:00
rnhmjoj 22004f7e8f
nixos/security/wrappers: use fixed defaults
To keep backward compatibility and have a typing would require making
all options null by default, adding a defaultText containing the actual
value, write the default value logic based on `!= null` and replacing
the nulls laters. This pretty much defeats the point of having used
a submodule type.
2021-09-12 21:43:25 +02:00
rnhmjoj 904f68fb0f
nixos/security/wrappers: make well-typed
The security.wrappers option is morally a set of submodules but it's
actually (un)typed as a generic attribute set. This is bad for several
reasons:

1. Some of the "submodule" option are not document;
2. the default values are not documented and are chosen based on
   somewhat bizarre rules (issue #23217);
3. It's not possible to override an existing wrapper due to the
   dumb types.attrs.merge strategy;
4. It's easy to make mistakes that will go unnoticed, which is
   really bad given the sensitivity of this module (issue #47839).

This makes the option a proper set of submodule and add strict types and
descriptions to every sub-option. Considering it's not yet clear if the
way the default values are picked is intended, this reproduces the current
behavior, but it's now documented explicitly.
2021-09-12 21:43:03 +02:00
Julien Moutinho 05d334cfe2 Revert "Revert "apparmor: fix and improve the service""
This reverts commit 420f89ceb2.
2021-04-23 07:17:55 +02:00
Jörg Thalheim dbd05a5289
Update nixos/modules/security/wrappers/wrapper.nix
Co-authored-by: Cole Helbling <cole.e.helbling@outlook.com>
2021-01-14 09:00:34 +00:00
Jörg Thalheim eadffd9154
nixos/wrappers: fix applying capabilities
With libcap 2.41 the output of cap_to_text changed, also the original
author of code hoped that this would never happen.
To counter this now the security-wrapper only relies on the syscall
ABI, which is more stable and robust than string parsing. If new
breakages occur this will be more obvious because version numbers will
be incremented.
Furthermore all errors no make execution explicitly fail instead of
hiding errors behind debug environment variables and the code style was
more consistent with no goto fail; goto fail; vulnerabilities (https://gotofail.com/)
2021-01-14 08:46:57 +01:00
Graham Christensen bc49a0815a
utillinux: rename to util-linux 2020-11-24 12:42:06 -05:00
Vladimír Čunát 420f89ceb2
Revert "apparmor: fix and improve the service"
This reverts commit fb6d63f3fd.

I really hope this finally fixes #99236: evaluation on Hydra.
This time I really did check basically the same commit on Hydra:
https://hydra.nixos.org/eval/1618011

Right now I don't have energy to find what exactly is wrong in the
commit, and it doesn't seem important in comparison to nixos-unstable
channel being stuck on a commit over one week old.
2020-10-07 12:22:18 +02:00
Andreas Rammhold 9630d5c07f
nixos/security/wrapper: ensure the tmpfs is not world writeable
The /run/wrapper directory is a tmpfs. Unfortunately, it's mounted with
its root directory has the standard (for tmpfs) mode: 1777 (world writeable,
sticky -- the standard mode of shared temporary directories). This means that
every user can create new files and subdirectories there, but can't
move/delete/rename files that belong to other users.
2020-09-28 22:55:20 +02:00
Julien Moutinho fb6d63f3fd apparmor: fix and improve the service 2020-09-06 07:43:03 +02:00
Doron Behar a854b77b08 nixos/wrappers: make (u)mount have the +s bit.
See
https://discourse.nixos.org/t/how-to-make-a-derivations-executables-have-the-s-permission/8555
and:
https://www.linuxquestions.org/questions/slackware-14/must-be-superuser-to-use-mount-fstab-is-correct-however-144932/
2020-08-15 21:57:16 +03:00
Silvan Mosberger 4ee3e8b21d
nixos/treewide: Move rename.nix imports to their respective modules
A centralized list for these renames is not good because:
- It breaks disabledModules for modules that have a rename defined
- Adding/removing renames for a module means having to find them in the
central file
- Merge conflicts due to multiple people editing the central file
2019-12-10 02:51:19 +01:00
volth 35d68ef143 treewide: remove redundant quotes 2019-08-26 21:40:19 +00:00
Linus Heckemann 45981145ad nixos/wrappers: remove outdated upgrade code
As mentioned in the code comments themselves, this was only necessary
for 16.09 -> 17.03 and as such is obsolete.
2018-10-21 15:12:36 +02:00
Will Dietz cb30a1b425 wrapper.c: fixup includes to work w/musl 2018-03-25 18:06:02 -05:00
Ben Gamari b2cbffae64 nixos/security-wrapper: Fix cross-compilation 2018-01-09 11:25:19 -05:00
Michael Weiss 351f5fc585 fuse3: init at 3.1.1
This includes fuse-common (fusePackages.fuse_3.common) as recommended by
upstream. But while fuse(2) and fuse3 would normally depend on
fuse-common we can't do that in nixpkgs while fuse-common is just
another output from the fuse3 multiple-output derivation (i.e. this
would result in a circular dependency). To avoid building fuse3 twice I
decided it would be best to copy the shared files (i.e. the ones
provided by fuse(2) and fuse3) from fuse-common to fuse (version 2) and
avoid collision warnings by defining priorities. Now it should be
possible to install an arbitrary combination of "fuse", "fuse3", and
"fuse-common" without getting any collision warnings. The end result
should be the same and all changes should be backwards compatible
(assuming that mount.fuse from fuse3 is backwards compatible as stated
by upstream [0] - if not this might break some /etc/fstab definitions
but that should be very unlikely).

My tests with sshfs (version 2 and 3) didn't show any problems.

See #28409 for some additional information.

[0]: https://github.com/libfuse/libfuse/releases/tag/fuse-3.0.0
2017-09-21 23:59:46 +02:00
tv ea44ca47f3 security-wrapper: run activation script after specialfs
Ensures that parentWrapperDir exists before it is used.

Closes #26851
2017-06-26 09:26:16 +02:00
Parnell Springmeyer 5ca644c228
Fixing attribute name mistake: setguid => setgid 2017-06-15 19:25:43 -07:00