From 9f25d2873ec9a834332f4b714dfb1717d4c2637f Mon Sep 17 00:00:00 2001 From: Sam <30577766+Samasaur1@users.noreply.github.com> Date: Mon, 26 Feb 2024 20:25:40 -0800 Subject: [PATCH 1/7] Potential first version of security.wrappers --- modules/module-list.nix | 1 + modules/security/wrappers/default.nix | 186 ++++++++++++++++++++++++++ modules/system/activation-scripts.nix | 1 + 3 files changed, 188 insertions(+) create mode 100644 modules/security/wrappers/default.nix diff --git a/modules/module-list.nix b/modules/module-list.nix index 043d1ee66..772b936bb 100644 --- a/modules/module-list.nix +++ b/modules/module-list.nix @@ -8,6 +8,7 @@ ./security/pki ./security/sandbox ./security/sudo.nix + ./security/wrappers ./system ./system/base.nix ./system/checks.nix diff --git a/modules/security/wrappers/default.nix b/modules/security/wrappers/default.nix new file mode 100644 index 000000000..3add4de2f --- /dev/null +++ b/modules/security/wrappers/default.nix @@ -0,0 +1,186 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.security; + + parentWrapperDir = dirOf cfg.wrapperDir; + + wrapperType = lib.types.submodule ({ name, config, ... }: { + options = with lib; { + source = mkOption { + type = types.path; + description = mdDoc "The absolute path to the program to be wrapped."; + }; + program = mkOption { + type = with types; nullOr str; + default = name; + description = mdDoc "The name of the wrapper program. Defaults to the attribute name."; + }; + owner = mkOption { + type = types.str; + description = mdDoc "The owner of the wrapper program."; + }; + group = mkOption { + type = types.str; + description = mdDoc "The group of the wrapper program."; + }; + permissions = mkOption { + type = types.str; + default = "u+rx,g+x,o+x"; + description = mdDoc "The permissions to set on the wrapper."; + }; + setuid = mkOption { + type = types.bool; + default = false; + description = mdDoc "Whether to add the setuid bit to the wrapper program."; + }; + setgid = mkOption { + type = types.bool; + default = false; + description = mdDoc "Whether to add the setgid bit to the wrapper program."; + }; + codesign = mkOption { + type = types.bool; + default = false; + description = mdDoc "Whether to codesign the wrapper program."; + }; + }; + }); + + mkWrappedPrograms = + builtins.map + (opts: mkWrapper opts) + (builtins.attrValues cfg.wrappers); + + securityWrapper = sourceProg: pkgs.writers.writeBashBin "security-wrapper" '' + exec ${sourceProg} "$@" + ''; + + mkWrapper = + { program + , source + , owner + , group + , permissions + , setuid + , setgid + , codesign + , ... + }: + let + codesigned = if codesign + then '' + # codesign ${source} to "$wrapperDir/${program}" INSTEAD OF the next line + cp ${securityWrapper source}/bin/security-wrapper "$wrapperDir/${program}" + '' + else '' + cp ${securityWrapper source}/bin/security-wrapper "$wrapperDir/${program}" + ''; + in + '' + ${codesigned} + + # Prevent races + chmod 0000 "$wrapperDir/${program}" + chown ${owner}:${group} "$wrapperDir/${program}" + + chmod "u${if setuid then "+" else "-"}s,g${if setgid then "+" else "-"}s,${permissions}" "$wrapperDir/${program}" + ''; +in +{ + # probably not necessary since these options never existed in nix-darwin? + imports = [ + (lib.mkRemovedOptionModule [ "security" "setuidOwners" ] "Use security.wrappers instead") + (lib.mkRemovedOptionModule [ "security" "setuidPrograms" ] "Use security.wrappers instead") + ]; + + ###### interface + options.security = { + wrappers = lib.mkOption { + type = lib.types.attrsOf wrapperType; + default = {}; + example = lib.literalExpression + '' + { + # a setuid root program + doas = + { setuid = true; + owner = "root"; + group = "root"; + source = "''${pkgs.doas}/bin/doas"; + }; + + + # a setgid program + locate = + { setgid = true; + owner = "root"; + group = "mlocate"; + source = "''${pkgs.locate}/bin/locate"; + }; + + + # a program with the CAP_NET_RAW capability + ping = + { owner = "root"; + group = "root"; + capabilities = "cap_net_raw+ep"; + source = "''${pkgs.iputils.out}/bin/ping"; + }; + } + ''; + description = lib.mdDoc '' + This option effectively allows adding setuid/setgid bits, capabilities, + changing file ownership and permissions of a program without directly + modifying it. This works by creating a wrapper program under the + {option}`security.wrapperDir` directory, which is then added to + the shell `PATH`. + ''; + }; + wrapperDir = lib.mkOption { + type = lib.types.path; + default = "/run/wrappers/bin"; + internal = true; + description = lib.mdDoc '' + This option defines the path to the wrapper programs. It + should not be overridden. + ''; + }; + codesignIdentity = lib.mkOption { + type = lib.types.str; + default = "-"; + description = lib.mdDoc "Identity to use for codesigning."; + }; + }; + + ###### implementation + config = { + environment.extraInit = '' + # Wrappers override other bin directories. + export PATH="${cfg.wrapperDir}:$PATH" + ''; + + system.activationScripts.wrappers.text = '' + echo "setting up wrappers..." >&2 + if ! test -e /run/wrappers; then mkdir /run/wrappers; fi + + # We want to place the tmpdirs for the wrappers to the parent dir. + wrapperDir=$(mktemp --directory --tmpdir="${parentWrapperDir}" wrappers.XXXXXXXXXX) + chmod a+rx $wrapperDir + + ${builtins.concatStringsSep "\n" mkWrappedPrograms} + + if test -L ${cfg.wrapperDir}; then + # Atomically replace the symlink + # See https://axialcorps.com/2013/07/03/atomically-replacing-files-and-directories/ + old=$(readlink -f ${cfg.wrapperDir}) + ln --symbolic --force --no-dereference $wrapperDir ${cfg.wrapperDir}-tmp + mv --no-target-directory ${cfg.wrapperDir}-tmp ${cfg.wrapperDir} + rm --force --recursive $old + else + # For initial setup + ln --symbolic $wrapperDir ${cfg.wrapperDir} + fi + ''; + }; +} diff --git a/modules/system/activation-scripts.nix b/modules/system/activation-scripts.nix index 68e01b592..0d39f7f79 100644 --- a/modules/system/activation-scripts.nix +++ b/modules/system/activation-scripts.nix @@ -70,6 +70,7 @@ in ${cfg.activationScripts.keyboard.text} ${cfg.activationScripts.fonts.text} ${cfg.activationScripts.nvram.text} + ${cfg.activationScripts.wrappers.text} ${cfg.activationScripts.postActivation.text} From ce15e526bf5917c011e77cf40535d4ef014d032b Mon Sep 17 00:00:00 2001 From: Sam <30577766+Samasaur1@users.noreply.github.com> Date: Mon, 26 Feb 2024 20:42:45 -0800 Subject: [PATCH 2/7] Actually wrap with C program --- modules/security/wrappers/default.nix | 32 +++++++- modules/security/wrappers/wrapper.c | 102 ++++++++++++++++++++++++++ modules/security/wrappers/wrapper.nix | 20 +++++ 3 files changed, 151 insertions(+), 3 deletions(-) create mode 100644 modules/security/wrappers/wrapper.c create mode 100644 modules/security/wrappers/wrapper.nix diff --git a/modules/security/wrappers/default.nix b/modules/security/wrappers/default.nix index 3add4de2f..b923105c7 100644 --- a/modules/security/wrappers/default.nix +++ b/modules/security/wrappers/default.nix @@ -52,9 +52,35 @@ let (opts: mkWrapper opts) (builtins.attrValues cfg.wrappers); - securityWrapper = sourceProg: pkgs.writers.writeBashBin "security-wrapper" '' - exec ${sourceProg} "$@" - ''; + # securityWrapper = sourceProg: pkgs.writers.writeBashBin "security-wrapper" '' + # exec ${sourceProg} "$@" + # ''; + # securityWrapper = sourceProg: pkgs.runCommand "security-wrapper" {} '' + # mkdir -p $out/bin + # cp ${sourceProg} $out/bin/security-wrapper + # # ln -s ${sourceProg} $out/bin/security-wrapper + # ''; + + securityWrapper = sourceProg : pkgs.pkgsStatic.callPackage ./wrapper.nix { + inherit sourceProg; + + # glibc definitions of insecure environment variables + # + # We extract the single header file we need into its own derivation, + # so that we don't have to pull full glibc sources to build wrappers. + # + # They're taken from pkgs.glibc so that we don't have to keep as close + # an eye on glibc changes. Not every relevant variable is in this header, + # so we maintain a slightly stricter list in wrapper.c itself as well. + unsecvars = lib.overrideDerivation (pkgs.srcOnly pkgs.glibc) + ({ name, ... }: { + name = "${name}-unsecvars"; + installPhase = '' + mkdir $out + cp sysdeps/generic/unsecvars.h $out + ''; + }); + }; mkWrapper = { program diff --git a/modules/security/wrappers/wrapper.c b/modules/security/wrappers/wrapper.c new file mode 100644 index 000000000..2075b9489 --- /dev/null +++ b/modules/security/wrappers/wrapper.c @@ -0,0 +1,102 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// imported from glibc +#include "unsecvars.h" + +#ifndef SOURCE_PROG +#error SOURCE_PROG should be defined via preprocessor commandline +#endif + +// aborts when false, printing the failed expression +#define ASSERT(expr) ((expr) ? (void) 0 : assert_failure(#expr)) + +extern char **environ; + +// Wrapper debug variable name +static char *wrapper_debug = "WRAPPER_DEBUG"; + +static noreturn void assert_failure(const char *assertion) { + fprintf(stderr, "Assertion `%s` in NixOS's wrapper.c failed.\n", assertion); + fflush(stderr); + abort(); +} + +// These are environment variable aliases for glibc tunables. +// This list shouldn't grow further, since this is a legacy mechanism. +// Any future tunables are expected to only be accessible through GLIBC_TUNABLES. +// +// They are not included in the glibc-provided UNSECURE_ENVVARS list, +// since any SUID executable ignores them. This wrapper also serves +// executables that are merely granted ambient capabilities, rather than +// being SUID, and hence don't run in secure mode. We'd like them to +// defend those in depth as well, so we clear these explicitly. +// +// Except for MALLOC_CHECK_ (which is marked SXID_ERASE), these are all +// marked SXID_IGNORE (ignored in secure mode), so even the glibc version +// of this wrapper would leave them intact. +#define UNSECURE_ENVVARS_TUNABLES \ + "MALLOC_CHECK_\0" \ + "MALLOC_TOP_PAD_\0" \ + "MALLOC_PERTURB_\0" \ + "MALLOC_MMAP_THRESHOLD_\0" \ + "MALLOC_TRIM_THRESHOLD_\0" \ + "MALLOC_MMAP_MAX_\0" \ + "MALLOC_ARENA_MAX\0" \ + "MALLOC_ARENA_TEST\0" + +int main(int argc, char **argv) { + ASSERT(argc >= 1); + + // argv[0] goes into a lot of places, to a far greater degree than other elements + // of argv. glibc has had buffer overflows relating to argv[0], eg CVE-2023-6246. + // Since we expect the wrappers to be invoked from either $PATH or /run/wrappers/bin, + // there should be no reason to pass any particularly large values here, so we can + // be strict for strictness' sake. + ASSERT(strlen(argv[0]) < 512); + + int debug = getenv(wrapper_debug) != NULL; + + // Drop insecure environment variables explicitly + // + // glibc does this automatically in SUID binaries, but we'd like to cover this: + // + // a) before it gets to glibc + // b) in binaries that are only granted ambient capabilities by the wrapper, + // but don't run with an altered effective UID/GID, nor directly gain + // capabilities themselves, and thus don't run in secure mode. + // + // We're using musl, which doesn't drop environment variables in secure mode, + // and we'd also like glibc-specific variables to be covered. + // + // If we don't explicitly unset them, it's quite easy to just set LD_PRELOAD, + // have it passed through to the wrapped program, and gain privileges. + for (char *unsec = UNSECURE_ENVVARS_TUNABLES UNSECURE_ENVVARS; *unsec; unsec = strchr(unsec, 0) + 1) { + if (debug) { + fprintf(stderr, "unsetting %s\n", unsec); + } + unsetenv(unsec); + } + + execve(SOURCE_PROG, argv, environ); + + fprintf(stderr, "%s: cannot run `%s': %s\n", + argv[0], SOURCE_PROG, strerror(errno)); + + return 1; +} diff --git a/modules/security/wrappers/wrapper.nix b/modules/security/wrappers/wrapper.nix new file mode 100644 index 000000000..ca4b27bff --- /dev/null +++ b/modules/security/wrappers/wrapper.nix @@ -0,0 +1,20 @@ +{ stdenv, unsecvars, linuxHeaders, sourceProg, debug ? false }: +# For testing: +# $ nix-build -E 'with import {}; pkgs.callPackage ./wrapper.nix { sourceProg = "${pkgs.hello}/bin/hello"; debug = true; }' +stdenv.mkDerivation { + name = "security-wrapper-${baseNameOf sourceProg}"; + buildInputs = [ linuxHeaders ]; + dontUnpack = true; + CFLAGS = [ + ''-DSOURCE_PROG="${sourceProg}"'' + ] ++ (if debug then [ + "-Werror" "-Og" "-g" + ] else [ + "-Wall" "-O2" + ]); + dontStrip = debug; + installPhase = '' + mkdir -p $out/bin + $CC $CFLAGS ${./wrapper.c} -I${unsecvars} -o $out/bin/security-wrapper + ''; +} From 5ddf368f4fea2743546ecaf6e28b91325b33587a Mon Sep 17 00:00:00 2001 From: Sam <30577766+Samasaur1@users.noreply.github.com> Date: Mon, 26 Feb 2024 21:20:32 -0800 Subject: [PATCH 3/7] Trim C wrapper to work on Darwin --- modules/security/wrappers/default.nix | 16 +++++------ modules/security/wrappers/wrapper.c | 38 +++++++++++++-------------- modules/security/wrappers/wrapper.nix | 5 ++-- 3 files changed, 29 insertions(+), 30 deletions(-) diff --git a/modules/security/wrappers/default.nix b/modules/security/wrappers/default.nix index b923105c7..9fc3b74dc 100644 --- a/modules/security/wrappers/default.nix +++ b/modules/security/wrappers/default.nix @@ -72,14 +72,14 @@ let # They're taken from pkgs.glibc so that we don't have to keep as close # an eye on glibc changes. Not every relevant variable is in this header, # so we maintain a slightly stricter list in wrapper.c itself as well. - unsecvars = lib.overrideDerivation (pkgs.srcOnly pkgs.glibc) - ({ name, ... }: { - name = "${name}-unsecvars"; - installPhase = '' - mkdir $out - cp sysdeps/generic/unsecvars.h $out - ''; - }); + # unsecvars = lib.overrideDerivation (pkgs.srcOnly pkgs.glibc) + # ({ name, ... }: { + # name = "${name}-unsecvars"; + # installPhase = '' + # mkdir $out + # cp sysdeps/generic/unsecvars.h $out + # ''; + # }); }; mkWrapper = diff --git a/modules/security/wrappers/wrapper.c b/modules/security/wrappers/wrapper.c index 2075b9489..5700cf10f 100644 --- a/modules/security/wrappers/wrapper.c +++ b/modules/security/wrappers/wrapper.c @@ -3,21 +3,21 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include // imported from glibc -#include "unsecvars.h" +// #include "unsecvars.h" #ifndef SOURCE_PROG #error SOURCE_PROG should be defined via preprocessor commandline @@ -86,12 +86,12 @@ int main(int argc, char **argv) { // // If we don't explicitly unset them, it's quite easy to just set LD_PRELOAD, // have it passed through to the wrapped program, and gain privileges. - for (char *unsec = UNSECURE_ENVVARS_TUNABLES UNSECURE_ENVVARS; *unsec; unsec = strchr(unsec, 0) + 1) { - if (debug) { - fprintf(stderr, "unsetting %s\n", unsec); - } - unsetenv(unsec); - } + // for (char *unsec = UNSECURE_ENVVARS_TUNABLES UNSECURE_ENVVARS; *unsec; unsec = strchr(unsec, 0) + 1) { + // if (debug) { + // fprintf(stderr, "unsetting %s\n", unsec); + // } + // unsetenv(unsec); + // } execve(SOURCE_PROG, argv, environ); diff --git a/modules/security/wrappers/wrapper.nix b/modules/security/wrappers/wrapper.nix index ca4b27bff..8c795e74f 100644 --- a/modules/security/wrappers/wrapper.nix +++ b/modules/security/wrappers/wrapper.nix @@ -1,9 +1,8 @@ -{ stdenv, unsecvars, linuxHeaders, sourceProg, debug ? false }: +{ stdenv, sourceProg, debug ? false }: # For testing: # $ nix-build -E 'with import {}; pkgs.callPackage ./wrapper.nix { sourceProg = "${pkgs.hello}/bin/hello"; debug = true; }' stdenv.mkDerivation { name = "security-wrapper-${baseNameOf sourceProg}"; - buildInputs = [ linuxHeaders ]; dontUnpack = true; CFLAGS = [ ''-DSOURCE_PROG="${sourceProg}"'' @@ -15,6 +14,6 @@ stdenv.mkDerivation { dontStrip = debug; installPhase = '' mkdir -p $out/bin - $CC $CFLAGS ${./wrapper.c} -I${unsecvars} -o $out/bin/security-wrapper + $CC $CFLAGS ${./wrapper.c} -o $out/bin/security-wrapper ''; } From bddf30d4897f72bb1fa5f2e1c0cae54faef9054f Mon Sep 17 00:00:00 2001 From: Sam <30577766+Samasaur1@users.noreply.github.com> Date: Mon, 26 Feb 2024 21:23:27 -0800 Subject: [PATCH 4/7] include libs --- modules/security/wrappers/wrapper.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/security/wrappers/wrapper.c b/modules/security/wrappers/wrapper.c index 5700cf10f..af06e85a0 100644 --- a/modules/security/wrappers/wrapper.c +++ b/modules/security/wrappers/wrapper.c @@ -3,7 +3,8 @@ #include #include #include -// #include +#include +#include // #include // #include // #include From a5b0b057aac6f2ae11b61ad439b4b95cba728550 Mon Sep 17 00:00:00 2001 From: Sam <30577766+Samasaur1@users.noreply.github.com> Date: Mon, 26 Feb 2024 21:30:50 -0800 Subject: [PATCH 5/7] unset env vars --- modules/security/wrappers/wrapper.c | 37 ++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/modules/security/wrappers/wrapper.c b/modules/security/wrappers/wrapper.c index af06e85a0..b6e4a8b38 100644 --- a/modules/security/wrappers/wrapper.c +++ b/modules/security/wrappers/wrapper.c @@ -61,6 +61,31 @@ static noreturn void assert_failure(const char *assertion) { "MALLOC_ARENA_MAX\0" \ "MALLOC_ARENA_TEST\0" +#define UNSECURE_ENVVARS \ + "GCONV_PATH\0" \ + "GETCONF_DIR\0" \ + "HOSTALIASES\0" \ + "LD_AUDIT\0" \ + "LD_DEBUG\0" \ + "LD_DEBUG_OUTPUT\0" \ + "LD_DYNAMIC_WEAK\0" \ + "LD_HWCAP_MASK\0" \ + "LD_LIBRARY_PATH\0" \ + "LD_ORIGIN_PATH\0" \ + "LD_PRELOAD\0" \ + "LD_PROFILE\0" \ + "LD_SHOW_AUXV\0" \ + "LD_USE_LOAD_BIAS\0" \ + "LOCALDOMAIN\0" \ + "LOCPATH\0" \ + "MALLOC_TRACE\0" \ + "NIS_PATH\0" \ + "NLSPATH\0" \ + "RESOLV_HOST_CONF\0" \ + "RES_OPTIONS\0" \ + "TMPDIR\0" \ + // GLIBC_TUNABLES_ENVVAR \ + int main(int argc, char **argv) { ASSERT(argc >= 1); @@ -87,12 +112,12 @@ int main(int argc, char **argv) { // // If we don't explicitly unset them, it's quite easy to just set LD_PRELOAD, // have it passed through to the wrapped program, and gain privileges. - // for (char *unsec = UNSECURE_ENVVARS_TUNABLES UNSECURE_ENVVARS; *unsec; unsec = strchr(unsec, 0) + 1) { - // if (debug) { - // fprintf(stderr, "unsetting %s\n", unsec); - // } - // unsetenv(unsec); - // } + for (char *unsec = UNSECURE_ENVVARS_TUNABLES UNSECURE_ENVVARS; *unsec; unsec = strchr(unsec, 0) + 1) { + if (debug) { + fprintf(stderr, "unsetting %s\n", unsec); + } + unsetenv(unsec); + } execve(SOURCE_PROG, argv, environ); From 5c5fed09d4938aa39e9838abd3c4785e807ecc5d Mon Sep 17 00:00:00 2001 From: Sam <30577766+Samasaur1@users.noreply.github.com> Date: Mon, 26 Feb 2024 22:14:11 -0800 Subject: [PATCH 6/7] Update examples --- modules/security/wrappers/default.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/security/wrappers/default.nix b/modules/security/wrappers/default.nix index 9fc3b74dc..ec0640a21 100644 --- a/modules/security/wrappers/default.nix +++ b/modules/security/wrappers/default.nix @@ -132,7 +132,7 @@ in doas = { setuid = true; owner = "root"; - group = "root"; + group = "wheel"; source = "''${pkgs.doas}/bin/doas"; }; @@ -146,11 +146,11 @@ in }; - # a program with the CAP_NET_RAW capability + # a codesigned program ping = { owner = "root"; - group = "root"; - capabilities = "cap_net_raw+ep"; + group = "wheel"; + codesign = true; source = "''${pkgs.iputils.out}/bin/ping"; }; } From 520fc2a497174d61f121d45a91f227ff531875df Mon Sep 17 00:00:00 2001 From: Sam <30577766+Samasaur1@users.noreply.github.com> Date: Wed, 28 Feb 2024 15:05:42 -0800 Subject: [PATCH 7/7] Remove codesigning support; leave stubs in place --- modules/security/wrappers/default.nix | 49 ++++++++------------------- 1 file changed, 15 insertions(+), 34 deletions(-) diff --git a/modules/security/wrappers/default.nix b/modules/security/wrappers/default.nix index ec0640a21..a80a4aca6 100644 --- a/modules/security/wrappers/default.nix +++ b/modules/security/wrappers/default.nix @@ -39,11 +39,11 @@ let default = false; description = mdDoc "Whether to add the setgid bit to the wrapper program."; }; - codesign = mkOption { - type = types.bool; - default = false; - description = mdDoc "Whether to codesign the wrapper program."; - }; + # codesign = mkOption { + # type = types.bool; + # default = false; + # description = mdDoc "Whether to codesign the wrapper program."; + # }; }; }); @@ -52,15 +52,6 @@ let (opts: mkWrapper opts) (builtins.attrValues cfg.wrappers); - # securityWrapper = sourceProg: pkgs.writers.writeBashBin "security-wrapper" '' - # exec ${sourceProg} "$@" - # ''; - # securityWrapper = sourceProg: pkgs.runCommand "security-wrapper" {} '' - # mkdir -p $out/bin - # cp ${sourceProg} $out/bin/security-wrapper - # # ln -s ${sourceProg} $out/bin/security-wrapper - # ''; - securityWrapper = sourceProg : pkgs.pkgsStatic.callPackage ./wrapper.nix { inherit sourceProg; @@ -90,7 +81,7 @@ let , permissions , setuid , setgid - , codesign + , codesign ? false , ... }: let @@ -144,23 +135,13 @@ in group = "mlocate"; source = "''${pkgs.locate}/bin/locate"; }; - - - # a codesigned program - ping = - { owner = "root"; - group = "wheel"; - codesign = true; - source = "''${pkgs.iputils.out}/bin/ping"; - }; } ''; description = lib.mdDoc '' - This option effectively allows adding setuid/setgid bits, capabilities, - changing file ownership and permissions of a program without directly - modifying it. This works by creating a wrapper program under the - {option}`security.wrapperDir` directory, which is then added to - the shell `PATH`. + This option effectively allows adding setuid/setgid bits and/or changing + file ownership and permissions without directly modifying it. This works + by creating a wrapper program under the {option}`security.wrapperDir` + directory, which is then added to the shell `PATH`. ''; }; wrapperDir = lib.mkOption { @@ -172,11 +153,11 @@ in should not be overridden. ''; }; - codesignIdentity = lib.mkOption { - type = lib.types.str; - default = "-"; - description = lib.mdDoc "Identity to use for codesigning."; - }; + # codesignIdentity = lib.mkOption { + # type = lib.types.str; + # default = "-"; + # description = lib.mdDoc "Identity to use for codesigning."; + # }; }; ###### implementation