summary refs log tree commit diff
path: root/nixos/modules/security/setuid-wrappers.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/security/setuid-wrappers.nix')
-rw-r--r--nixos/modules/security/setuid-wrappers.nix121
1 files changed, 121 insertions, 0 deletions
diff --git a/nixos/modules/security/setuid-wrappers.nix b/nixos/modules/security/setuid-wrappers.nix
new file mode 100644
index 00000000000..e75679e5ff6
--- /dev/null
+++ b/nixos/modules/security/setuid-wrappers.nix
@@ -0,0 +1,121 @@
+{pkgs, config, ...}:
+
+with pkgs.lib;
+
+let
+
+  inherit (config.security) wrapperDir;
+
+  setuidWrapper = pkgs.stdenv.mkDerivation {
+    name = "setuid-wrapper";
+    buildCommand = ''
+      ensureDir $out/bin
+      gcc -Wall -O2 -DWRAPPER_DIR=\"${wrapperDir}\" \
+          ${./setuid-wrapper.c} -o $out/bin/setuid-wrapper
+      strip -s $out/bin/setuid-wrapper
+    '';
+  };
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    security.setuidPrograms = mkOption {
+      default = [];
+      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 {
+      default = [];
+      example =
+        [ { program = "sendmail";
+            owner = "nobody";
+            group = "postdrop";
+            setuid = false;
+            setgid = true;
+          }
+        ];
+      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 {
+      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 <option>wrapperDir</option> is
+        <filename>/var/setuid-wrappers</filename>.
+      '';
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = {
+
+    security.setuidPrograms =
+      [ "fusermount" "wodim" "cdrdao" "growisofs" ];
+
+    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"
+          }:
+
+          ''
+            source=${if source != "" then source else "$(PATH=$SETUID_PATH type -tP ${program})"}
+            if test -z "$source"; 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
+
+          if test -d ${wrapperDir}; then rm -f ${wrapperDir}/*; fi # */
+          mkdir -p ${wrapperDir}
+
+          ${concatMapStrings makeSetuidWrapper setuidPrograms}
+        '';
+
+  };
+
+}