diff --git a/nixos/modules/security/permissions-wrappers/setcap-wrappers.nix b/nixos/modules/security/permissions-wrappers/setcap-wrappers.nix deleted file mode 100644 index ead3cb219f1..00000000000 --- a/nixos/modules/security/permissions-wrappers/setcap-wrappers.nix +++ /dev/null @@ -1,162 +0,0 @@ -{ config, lib, pkgs, ... }: - -with lib; with pkgs; - -let - - inherit (config.security) setcapWrapperDir; - - cfg = config.security.setcapCapabilities; - - # Produce a shell-code splice intended to be stitched into one of - # the build or install phases within the `setcapWrapper` derivation. - mkSetcapWrapper = { program, source ? null, ...}: - '' - if ! source=${if source != null then source else "$(readlink -f $(PATH=$SETCAP_PATH type -tP ${program}))"}; then - # If we can't find the program, fall back to the - # system profile. - source=/nix/var/nix/profiles/default/bin/${program} - fi - - gcc -Wall -O2 -DSOURCE_PROG=\"$source\" -DWRAPPER_DIR=\"${setcapWrapperDir}\" \ - -lcap-ng -lcap ${./setcap-wrapper.c} -o $out/bin/${program}.wrapper - ''; - - setcapWrappers = - - # This is only useful for Linux platforms and a kernel version of - # 4.3 or greater - assert pkgs.stdenv.isLinux; - assert versionAtLeast (getVersion config.boot.kernelPackages.kernel) "4.3"; - - pkgs.stdenv.mkDerivation { - name = "setcap-wrapper"; - unpackPhase = "true"; - buildInputs = [ linuxHeaders libcap libcap_ng ]; - installPhase = '' - mkdir -p $out/bin - - # Concat together all of our shell splices to compile - # binary wrapper programs for all configured setcap programs. - ${concatMapStrings mkSetcapWrapper cfg} - ''; - }; -in -{ - options = { - security.setcapCapabilities = mkOption { - type = types.listOf types.attrs; - default = []; - example = - [ { program = "ping"; - owner = "nobody"; - group = "nogroup"; - setcap = true; - capabilities = "cap_net_raw+ep"; - } - ]; - description = '' - This option sets capabilities on a wrapper program that - propagates those capabilities down to the wrapped, real - program. - - The `program` attribute is the name of the program to be - wrapped. If no `source` attribute is provided, specifying the - absolute path to the program, then the program will be - searched for in the path environment variable. - - NOTE: cap_setpcap, which is required for the wrapper program - to be able to raise caps into the Ambient set is NOT raised to - the Ambient set so that the real program cannot modify its own - capabilities!! This may be too restrictive for cases in which - the real program needs cap_setpcap but it at least leans on - the side security paranoid vs. too relaxed. - - The attribute `setcap` defaults to false and it will create a - wrapper program but never set the capability set on it. This - is done so that you can remove a capability sent entirely from - a wrapper program without also needing to go change any - absolute paths that may be directly referencing the wrapper - program. - ''; - }; - - security.setcapWrapperDir = mkOption { - type = types.path; - default = "/var/setcap-wrappers"; - internal = true; - description = '' - This option defines the path to the setcap wrappers. It - should generally not be overriden. - ''; - }; - - }; - - config = { - - # Make sure our setcap-wrapper dir exports to the PATH env - # variable when initializing the shell - environment.extraInit = '' - # The setcap wrappers override other bin directories. - export PATH="${config.security.setcapWrapperDir}:$PATH" - ''; - - system.activationScripts.setcap = - let - setcapPrograms = cfg; - configureSetcapWrapper = - { program - , capabilities - , source ? null - , owner ? "nobody" - , group ? "nogroup" - , setcap ? false - }: - '' - mkdir -p ${setcapWrapperDir} - - cp ${setcapWrappers}/bin/${program}.wrapper ${setcapWrapperDir}/${program} - - # Prevent races - chmod 0000 ${setcapWrapperDir}/${program} - chown ${owner}.${group} ${setcapWrapperDir}/${program} - - # Set desired capabilities on the file plus cap_setpcap so - # the wrapper program can elevate the capabilities set on - # its file into the Ambient set. - # - # Only set the capabilities though if we're being told to - # do so. - ${ - if setcap then - '' - ${libcap.out}/bin/setcap "cap_setpcap,${capabilities}" ${setcapWrapperDir}/${program} - '' - else "" - } - - # Set the executable bit - chmod u+rx,g+x,o+x ${setcapWrapperDir}/${program} - ''; - - in stringAfter [ "users" ] - '' - # Look in the system path and in the default profile for - # programs to be wrapped. - SETCAP_PATH=${config.system.path}/bin:${config.system.path}/sbin - - # When a program is removed from the security.setcapCapabilities - # list we have to remove all of the previous program wrappers - # and re-build them minus the wrapper for the program removed, - # hence the rm here in the activation script. - - rm -f ${setcapWrapperDir}/* - - # Concatenate the generated shell slices to configure - # wrappers for each program needing specialized capabilities. - - ${concatMapStrings configureSetcapWrapper setcapPrograms} - ''; - }; -} diff --git a/nixos/modules/security/permissions-wrappers/setuid-wrappers.nix b/nixos/modules/security/permissions-wrappers/setuid-wrappers.nix deleted file mode 100644 index fe220c94313..00000000000 --- a/nixos/modules/security/permissions-wrappers/setuid-wrappers.nix +++ /dev/null @@ -1,146 +0,0 @@ -{ config, lib, pkgs, ... }: - -with lib; - -let - - inherit (config.security) wrapperDir; - - setuidWrapper = pkgs.stdenv.mkDerivation { - name = "setuid-wrapper"; - unpackPhase = "true"; - installPhase = '' - mkdir -p $out/bin - cp ${./setuid-wrapper.c} setuid-wrapper.c - gcc -Wall -O2 -DWRAPPER_DIR=\"/run/setuid-wrapper-dirs\" \ - setuid-wrapper.c -o $out/bin/setuid-wrapper - ''; - }; - -in - -{ - - ###### interface - - options = { - - security.setuidPrograms = mkOption { - type = types.listOf types.str; - default = []; - example = ["passwd"]; - description = '' - The Nix store cannot contain setuid/setgid programs directly. - For this reason, NixOS can automatically generate wrapper - programs that have the necessary privileges. This option - lists the names of programs in the system environment for - which setuid root wrappers should be created. - ''; - }; - - security.setuidOwners = mkOption { - type = types.listOf types.attrs; - default = []; - example = - [ { program = "sendmail"; - owner = "nobody"; - group = "postdrop"; - setuid = false; - setgid = true; - permissions = "u+rx,g+x,o+x"; - } - ]; - description = '' - This option allows the ownership and permissions on the setuid - wrappers for specific programs to be overridden from the - default (setuid root, but not setgid root). - ''; - }; - - security.wrapperDir = mkOption { - internal = true; - type = types.path; - default = "/var/setuid-wrappers"; - description = '' - This option defines the path to the setuid wrappers. It - should generally not be overriden. Some packages in Nixpkgs - expect that is - /var/setuid-wrappers. - ''; - }; - - }; - - - ###### implementation - - config = { - - security.setuidPrograms = [ "fusermount" ]; - - system.activationScripts.setuid = - let - setuidPrograms = - (map (x: { program = x; owner = "root"; group = "root"; setuid = true; }) - config.security.setuidPrograms) - ++ config.security.setuidOwners; - - makeSetuidWrapper = - { program - , source ? "" - , owner ? "nobody" - , group ? "nogroup" - , setuid ? false - , setgid ? false - , permissions ? "u+rx,g+x,o+x" - }: - - '' - if ! source=${if source != "" then source else "$(readlink -f $(PATH=$SETUID_PATH type -tP ${program}))"}; then - # If we can't find the program, fall back to the - # system profile. - source=/nix/var/nix/profiles/default/bin/${program} - fi - - cp ${setuidWrapper}/bin/setuid-wrapper $wrapperDir/${program} - echo -n "$source" > $wrapperDir/${program}.real - chmod 0000 $wrapperDir/${program} # to prevent races - chown ${owner}.${group} $wrapperDir/${program} - chmod "u${if setuid then "+" else "-"}s,g${if setgid then "+" else "-"}s,${permissions}" $wrapperDir/${program} - ''; - - in stringAfter [ "users" ] - '' - # Look in the system path and in the default profile for - # programs to be wrapped. - SETUID_PATH=${config.system.path}/bin:${config.system.path}/sbin - - mkdir -p /run/setuid-wrapper-dirs - wrapperDir=$(mktemp --directory --tmpdir=/run/setuid-wrapper-dirs setuid-wrappers.XXXXXXXXXX) - chmod a+rx $wrapperDir - - ${concatMapStrings makeSetuidWrapper setuidPrograms} - - if [ -L ${wrapperDir} ]; then - # Atomically replace the symlink - # See https://axialcorps.com/2013/07/03/atomically-replacing-files-and-directories/ - old=$(readlink ${wrapperDir}) - ln --symbolic --force --no-dereference $wrapperDir ${wrapperDir}-tmp - mv --no-target-directory ${wrapperDir}-tmp ${wrapperDir} - rm --force --recursive $old - elif [ -d ${wrapperDir} ]; then - # Compatibility with old state, just remove the folder and symlink - rm -f ${wrapperDir}/* - # if it happens to be a tmpfs - ${pkgs.utillinux}/bin/umount ${wrapperDir} || true - rm -d ${wrapperDir} - ln -d --symbolic $wrapperDir ${wrapperDir} - else - # For initial setup - ln --symbolic $wrapperDir ${wrapperDir} - fi - ''; - - }; - -}