Merge pull request #126289 from rnhmjoj/wrappers

nixos/security/wrappers: make well-typed
This commit is contained in:
Guillaume Girol 2021-09-18 15:28:49 +00:00 committed by GitHub
commit ceb2e6667b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
50 changed files with 462 additions and 155 deletions

View file

@ -278,6 +278,16 @@
<section xml:id="sec-release-21.11-incompatibilities">
<title>Backward Incompatibilities</title>
<itemizedlist>
<listitem>
<para>
The <literal>security.wrappers</literal> option now requires
to always specify an owner, group and whether the
setuid/setgid bit should be set. This is motivated by the fact
that before NixOS 21.11, specifying either setuid or setgid
but not owner/group resulted in wrappers owned by
nobody/nogroup, which is unsafe.
</para>
</listitem>
<listitem>
<para>
The <literal>paperless</literal> module and package have been

View file

@ -88,6 +88,8 @@ subsonic-compatible api. Available as [navidrome](#opt-services.navidrome.enable
## Backward Incompatibilities {#sec-release-21.11-incompatibilities}
- The `security.wrappers` option now requires to always specify an owner, group and whether the setuid/setgid bit should be set.
This is motivated by the fact that before NixOS 21.11, specifying either setuid or setgid but not owner/group resulted in wrappers owned by nobody/nogroup, which is unsafe.
- The `paperless` module and package have been removed. All users should migrate to the
successor `paperless-ng` instead. The Paperless project [has been

View file

@ -22,8 +22,10 @@ in {
config = mkIf cfg.enable {
environment.systemPackages = with pkgs; [ bandwhich ];
security.wrappers.bandwhich = {
source = "${pkgs.bandwhich}/bin/bandwhich";
owner = "root";
group = "root";
capabilities = "cap_net_raw,cap_net_admin+ep";
source = "${pkgs.bandwhich}/bin/bandwhich";
};
};
}

View file

@ -105,11 +105,15 @@ in
);
security.wrappers.udhcpc = {
owner = "root";
group = "root";
capabilities = "cap_net_raw+p";
source = "${pkgs.busybox}/bin/udhcpc";
};
security.wrappers.captive-browser = {
owner = "root";
group = "root";
capabilities = "cap_net_raw+p";
source = pkgs.writeShellScript "captive-browser" ''
export PREV_CONFIG_HOME="$XDG_CONFIG_HOME"

View file

@ -28,7 +28,9 @@ in {
# "nix-ccache --show-stats" and "nix-ccache --clear"
security.wrappers.nix-ccache = {
owner = "nobody";
group = "nixbld";
setuid = false;
setgid = true;
source = pkgs.writeScript "nix-ccache.pl" ''
#!${pkgs.perl}/bin/perl

View file

@ -81,7 +81,12 @@ in {
};
config = mkIf cfg.enable {
security.wrappers.firejail.source = "${lib.getBin pkgs.firejail}/bin/firejail";
security.wrappers.firejail =
{ setuid = true;
owner = "root";
group = "root";
source = "${lib.getBin pkgs.firejail}/bin/firejail";
};
environment.systemPackages = [ pkgs.firejail ] ++ [ wrappedBins ];
};

View file

@ -56,6 +56,8 @@ in
polkit.enable = true;
wrappers = mkIf cfg.enableRenice {
gamemoded = {
owner = "root";
group = "root";
source = "${pkgs.gamemode}/bin/gamemoded";
capabilities = "cap_sys_nice+ep";
};

View file

@ -11,8 +11,10 @@ in {
config = mkIf cfg.enable {
environment.systemPackages = [ pkgs.iftop ];
security.wrappers.iftop = {
source = "${pkgs.iftop}/bin/iftop";
owner = "root";
group = "root";
capabilities = "cap_net_raw+p";
source = "${pkgs.iftop}/bin/iftop";
};
};
}

View file

@ -10,8 +10,10 @@ in {
};
config = mkIf cfg.enable {
security.wrappers.iotop = {
source = "${pkgs.iotop}/bin/iotop";
owner = "root";
group = "root";
capabilities = "cap_net_admin+p";
source = "${pkgs.iotop}/bin/iotop";
};
};
}

View file

@ -11,6 +11,11 @@ in
config = mkIf cfg.enable {
environment.systemPackages = [ pkgs.kbdlight ];
security.wrappers.kbdlight.source = "${pkgs.kbdlight.out}/bin/kbdlight";
security.wrappers.kbdlight =
{ setuid = true;
owner = "root";
group = "root";
source = "${pkgs.kbdlight.out}/bin/kbdlight";
};
};
}

View file

@ -13,8 +13,10 @@ in {
security.wrappers = mkMerge (map (
exec: {
"${exec}" = {
source = "${pkgs.liboping}/bin/${exec}";
owner = "root";
group = "root";
capabilities = "cap_net_raw+p";
source = "${pkgs.liboping}/bin/${exec}";
};
}
) [ "oping" "noping" ]);

View file

@ -78,6 +78,8 @@ in {
source = "${pkgs.msmtp}/bin/sendmail";
setuid = false;
setgid = false;
owner = "root";
group = "root";
};
environment.etc."msmtprc".text = let

View file

@ -31,8 +31,10 @@ in {
environment.systemPackages = with pkgs; [ cfg.package ];
security.wrappers.mtr-packet = {
source = "${cfg.package}/bin/mtr-packet";
owner = "root";
group = "root";
capabilities = "cap_net_raw+p";
source = "${cfg.package}/bin/mtr-packet";
};
};
}

View file

@ -18,8 +18,10 @@ in {
config = mkIf cfg.enable {
security.wrappers.noisetorch = {
source = "${cfg.package}/bin/noisetorch";
owner = "root";
group = "root";
capabilities = "cap_sys_resource=+ep";
source = "${cfg.package}/bin/noisetorch";
};
};
}

View file

@ -43,6 +43,13 @@ let
'';
mkSetuidRoot = source:
{ setuid = true;
owner = "root";
group = "root";
inherit source;
};
in
{
@ -109,14 +116,14 @@ in
};
security.wrappers = {
su.source = "${pkgs.shadow.su}/bin/su";
sg.source = "${pkgs.shadow.out}/bin/sg";
newgrp.source = "${pkgs.shadow.out}/bin/newgrp";
newuidmap.source = "${pkgs.shadow.out}/bin/newuidmap";
newgidmap.source = "${pkgs.shadow.out}/bin/newgidmap";
su = mkSetuidRoot "${pkgs.shadow.su}/bin/su";
sg = mkSetuidRoot "${pkgs.shadow.out}/bin/sg";
newgrp = mkSetuidRoot "${pkgs.shadow.out}/bin/newgrp";
newuidmap = mkSetuidRoot "${pkgs.shadow.out}/bin/newuidmap";
newgidmap = mkSetuidRoot "${pkgs.shadow.out}/bin/newgidmap";
} // lib.optionalAttrs config.users.mutableUsers {
chsh.source = "${pkgs.shadow.out}/bin/chsh";
passwd.source = "${pkgs.shadow.out}/bin/passwd";
chsh = mkSetuidRoot "${pkgs.shadow.out}/bin/chsh";
passwd = mkSetuidRoot "${pkgs.shadow.out}/bin/passwd";
};
};
}

View file

@ -16,7 +16,12 @@ in {
config = mkIf cfg.enable {
environment.systemPackages = [ singularity ];
security.wrappers.singularity-suid.source = "${singularity}/libexec/singularity/bin/starter-suid.orig";
security.wrappers.singularity-suid =
{ setuid = true;
owner = "root";
group = "root";
source = "${singularity}/libexec/singularity/bin/starter-suid.orig";
};
systemd.tmpfiles.rules = [
"d /var/singularity/mnt/session 0770 root root -"
"d /var/singularity/mnt/final 0770 root root -"

View file

@ -21,6 +21,11 @@ in
config = mkIf cfg.enable {
environment.systemPackages = [ pkgs.slock ];
security.wrappers.slock.source = "${pkgs.slock.out}/bin/slock";
security.wrappers.slock =
{ setuid = true;
owner = "root";
group = "root";
source = "${pkgs.slock.out}/bin/slock";
};
};
}

View file

@ -181,6 +181,8 @@ in
source = "${pkgs.ssmtp}/bin/sendmail";
setuid = false;
setgid = false;
owner = "root";
group = "root";
};
};

View file

@ -19,8 +19,10 @@ in {
config = mkIf cfg.enable {
security.wrappers.traceroute = {
source = "${pkgs.traceroute}/bin/traceroute";
owner = "root";
group = "root";
capabilities = "cap_net_raw+p";
source = "${pkgs.traceroute}/bin/traceroute";
};
};
}

View file

@ -9,6 +9,11 @@ in {
options.programs.udevil.enable = mkEnableOption "udevil";
config = mkIf cfg.enable {
security.wrappers.udevil.source = "${lib.getBin pkgs.udevil}/bin/udevil";
security.wrappers.udevil =
{ setuid = true;
owner = "root";
group = "root";
source = "${lib.getBin pkgs.udevil}/bin/udevil";
};
};
}

View file

@ -21,8 +21,10 @@ in {
config = mkIf cfg.enable {
environment.systemPackages = with pkgs; [ wavemon ];
security.wrappers.wavemon = {
source = "${pkgs.wavemon}/bin/wavemon";
owner = "root";
group = "root";
capabilities = "cap_net_admin+ep";
source = "${pkgs.wavemon}/bin/wavemon";
};
};
}

View file

@ -17,6 +17,11 @@ in {
};
config = mkIf cfg.enable {
security.wrappers.wshowkeys.source = "${pkgs.wshowkeys}/bin/wshowkeys";
security.wrappers.wshowkeys =
{ setuid = true;
owner = "root";
group = "root";
source = "${pkgs.wshowkeys}/bin/wshowkeys";
};
};
}

View file

@ -28,6 +28,11 @@ in
config = mkIf cfg.enable {
environment.systemPackages = [ sandbox ];
security.wrappers.${sandbox.passthru.sandboxExecutableName}.source = "${sandbox}/bin/${sandbox.passthru.sandboxExecutableName}";
security.wrappers.${sandbox.passthru.sandboxExecutableName} =
{ setuid = true;
owner = "root";
group = "root";
source = "${sandbox}/bin/${sandbox.passthru.sandboxExecutableName}";
};
};
}

View file

@ -241,8 +241,11 @@ in
}
];
security.wrappers = {
doas.source = "${doas}/bin/doas";
security.wrappers.doas =
{ setuid = true;
owner = "root";
group = "root";
source = "${doas}/bin/doas";
};
environment.systemPackages = [

View file

@ -186,7 +186,12 @@ in
config = mkIf (cfg.ssh.enable || cfg.pam.enable) {
environment.systemPackages = [ pkgs.duo-unix ];
security.wrappers.login_duo.source = "${pkgs.duo-unix.out}/bin/login_duo";
security.wrappers.login_duo =
{ setuid = true;
owner = "root";
group = "root";
source = "${pkgs.duo-unix.out}/bin/login_duo";
};
system.activationScripts = {
login_duo = mkIf cfg.ssh.enable ''

View file

@ -869,9 +869,10 @@ in
security.wrappers = {
unix_chkpwd = {
source = "${pkgs.pam}/sbin/unix_chkpwd.orig";
owner = "root";
setuid = true;
owner = "root";
group = "root";
source = "${pkgs.pam}/sbin/unix_chkpwd.orig";
};
};

View file

@ -32,8 +32,18 @@ in
# Make sure pmount and pumount are setuid wrapped.
security.wrappers = {
pmount.source = "${pkgs.pmount.out}/bin/pmount";
pumount.source = "${pkgs.pmount.out}/bin/pumount";
pmount =
{ setuid = true;
owner = "root";
group = "root";
source = "${pkgs.pmount.out}/bin/pmount";
};
pumount =
{ setuid = true;
owner = "root";
group = "root";
source = "${pkgs.pmount.out}/bin/pumount";
};
};
environment.systemPackages = [ pkgs.pmount ];

View file

@ -83,8 +83,18 @@ in
security.pam.services.polkit-1 = {};
security.wrappers = {
pkexec.source = "${pkgs.polkit.bin}/bin/pkexec";
polkit-agent-helper-1.source = "${pkgs.polkit.out}/lib/polkit-1/polkit-agent-helper-1";
pkexec =
{ setuid = true;
owner = "root";
group = "root";
source = "${pkgs.polkit.bin}/bin/pkexec";
};
polkit-agent-helper-1 =
{ setuid = true;
owner = "root";
group = "root";
source = "${pkgs.polkit.out}/lib/polkit-1/polkit-agent-helper-1";
};
};
systemd.tmpfiles.rules = [

View file

@ -5,85 +5,140 @@ let
parentWrapperDir = dirOf wrapperDir;
programs =
(lib.mapAttrsToList
(n: v: (if v ? program then v else v // {program=n;}))
wrappers);
securityWrapper = pkgs.callPackage ./wrapper.nix {
inherit parentWrapperDir;
};
fileModeType =
let
# taken from the chmod(1) man page
symbolic = "[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=][0-7]+";
numeric = "[-+=]?[0-7]{0,4}";
mode = "((${symbolic})(,${symbolic})*)|(${numeric})";
in
lib.types.strMatching mode
// { description = "file mode string"; };
wrapperType = lib.types.submodule ({ name, config, ... }: {
options.source = lib.mkOption
{ type = lib.types.path;
description = "The absolute path to the program to be wrapped.";
};
options.program = lib.mkOption
{ type = with lib.types; nullOr str;
default = name;
description = ''
The name of the wrapper program. Defaults to the attribute name.
'';
};
options.owner = lib.mkOption
{ type = lib.types.str;
description = "The owner of the wrapper program.";
};
options.group = lib.mkOption
{ type = lib.types.str;
description = "The group of the wrapper program.";
};
options.permissions = lib.mkOption
{ type = fileModeType;
default = "u+rx,g+x,o+x";
example = "a+rx";
description = ''
The permissions of the wrapper program. The format is that of a
symbolic or numeric file mode understood by <command>chmod</command>.
'';
};
options.capabilities = lib.mkOption
{ type = lib.types.commas;
default = "";
description = ''
A comma-separated list of capabilities to be given to the wrapper
program. For capabilities supported by the system check the
<citerefentry>
<refentrytitle>capabilities</refentrytitle>
<manvolnum>7</manvolnum>
</citerefentry>
manual page.
<note><para>
<literal>cap_setpcap</literal>, 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.
</para></note>
'';
};
options.setuid = lib.mkOption
{ type = lib.types.bool;
default = false;
description = "Whether to add the setuid bit the wrapper program.";
};
options.setgid = lib.mkOption
{ type = lib.types.bool;
default = false;
description = "Whether to add the setgid bit the wrapper program.";
};
});
###### Activation script for the setcap wrappers
mkSetcapProgram =
{ program
, capabilities
, source
, owner ? "nobody"
, group ? "nogroup"
, permissions ? "u+rx,g+x,o+x"
, owner
, group
, permissions
, ...
}:
assert (lib.versionAtLeast (lib.getVersion config.boot.kernelPackages.kernel) "4.3");
''
cp ${securityWrapper}/bin/security-wrapper $wrapperDir/${program}
echo -n "${source}" > $wrapperDir/${program}.real
cp ${securityWrapper}/bin/security-wrapper "$wrapperDir/${program}"
echo -n "${source}" > "$wrapperDir/${program}.real"
# Prevent races
chmod 0000 $wrapperDir/${program}
chown ${owner}.${group} $wrapperDir/${program}
chmod 0000 "$wrapperDir/${program}"
chown ${owner}.${group} "$wrapperDir/${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.
${pkgs.libcap.out}/bin/setcap "cap_setpcap,${capabilities}" $wrapperDir/${program}
${pkgs.libcap.out}/bin/setcap "cap_setpcap,${capabilities}" "$wrapperDir/${program}"
# Set the executable bit
chmod ${permissions} $wrapperDir/${program}
chmod ${permissions} "$wrapperDir/${program}"
'';
###### Activation script for the setuid wrappers
mkSetuidProgram =
{ program
, source
, owner ? "nobody"
, group ? "nogroup"
, setuid ? false
, setgid ? false
, permissions ? "u+rx,g+x,o+x"
, owner
, group
, setuid
, setgid
, permissions
, ...
}:
''
cp ${securityWrapper}/bin/security-wrapper $wrapperDir/${program}
echo -n "${source}" > $wrapperDir/${program}.real
cp ${securityWrapper}/bin/security-wrapper "$wrapperDir/${program}"
echo -n "${source}" > "$wrapperDir/${program}.real"
# Prevent races
chmod 0000 $wrapperDir/${program}
chown ${owner}.${group} $wrapperDir/${program}
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}
chmod "u${if setuid then "+" else "-"}s,g${if setgid then "+" else "-"}s,${permissions}" "$wrapperDir/${program}"
'';
mkWrappedPrograms =
builtins.map
(s: if (s ? capabilities)
then mkSetcapProgram
({ owner = "root";
group = "root";
} // s)
else if
(s ? setuid && s.setuid) ||
(s ? setgid && s.setgid) ||
(s ? permissions)
then mkSetuidProgram s
else mkSetuidProgram
({ owner = "root";
group = "root";
setuid = true;
setgid = false;
permissions = "u+rx,g+x,o+x";
} // s)
) programs;
(opts:
if opts.capabilities != ""
then mkSetcapProgram opts
else mkSetuidProgram opts
) (lib.attrValues wrappers);
in
{
imports = [
@ -95,45 +150,42 @@ in
options = {
security.wrappers = lib.mkOption {
type = lib.types.attrs;
type = lib.types.attrsOf wrapperType;
default = {};
example = lib.literalExample
''
{ sendmail.source = "/nix/store/.../bin/sendmail";
ping = {
source = "${pkgs.iputils.out}/bin/ping";
owner = "nobody";
group = "nogroup";
{
# 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 = ''
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).
<note>
<para>The sub-attribute <literal>source</literal> is mandatory,
it must be the absolute path to the program to be wrapped.
</para>
<para>The sub-attribute <literal>program</literal> is optional and
can give the wrapper program a new name. The default name is the same
as the attribute name itself.</para>
<para>Additionally, this option can set capabilities on a
wrapper program that propagates those capabilities down to the
wrapped, real program.</para>
<para>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.</para>
</note>
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</option> directory, which is then added to
the shell <literal>PATH</literal>.
'';
};
@ -151,12 +203,30 @@ in
###### implementation
config = {
security.wrappers = {
# These are mount related wrappers that require the +s permission.
fusermount.source = "${pkgs.fuse}/bin/fusermount";
fusermount3.source = "${pkgs.fuse3}/bin/fusermount3";
mount.source = "${lib.getBin pkgs.util-linux}/bin/mount";
umount.source = "${lib.getBin pkgs.util-linux}/bin/umount";
assertions = lib.mapAttrsToList
(name: opts:
{ assertion = opts.setuid || opts.setgid -> opts.capabilities == "";
message = ''
The security.wrappers.${name} wrapper is not valid:
setuid/setgid and capabilities are mutually exclusive.
'';
}
) wrappers;
security.wrappers =
let
mkSetuidRoot = source:
{ setuid = true;
owner = "root";
group = "root";
inherit source;
};
in
{ # These are mount related wrappers that require the +s permission.
fusermount = mkSetuidRoot "${pkgs.fuse}/bin/fusermount";
fusermount3 = mkSetuidRoot "${pkgs.fuse3}/bin/fusermount3";
mount = mkSetuidRoot "${lib.getBin pkgs.util-linux}/bin/mount";
umount = mkSetuidRoot "${lib.getBin pkgs.util-linux}/bin/umount";
};
boot.specialFileSystems.${parentWrapperDir} = {
@ -179,19 +249,15 @@ in
]}"
'';
###### setcap activation script
###### wrappers activation script
system.activationScripts.wrappers =
lib.stringAfter [ "specialfs" "users" ]
''
# Look in the system path and in the default profile for
# programs to be wrapped.
WRAPPER_PATH=${config.system.path}/bin:${config.system.path}/sbin
chmod 755 "${parentWrapperDir}"
# We want to place the tmpdirs for the wrappers to the parent dir.
wrapperDir=$(mktemp --directory --tmpdir="${parentWrapperDir}" wrappers.XXXXXXXXXX)
chmod a+rx $wrapperDir
chmod a+rx "$wrapperDir"
${lib.concatStringsSep "\n" mkWrappedPrograms}
@ -199,16 +265,44 @@ in
# Atomically replace the symlink
# See https://axialcorps.com/2013/07/03/atomically-replacing-files-and-directories/
old=$(readlink -f ${wrapperDir})
if [ -e ${wrapperDir}-tmp ]; then
rm --force --recursive ${wrapperDir}-tmp
if [ -e "${wrapperDir}-tmp" ]; then
rm --force --recursive "${wrapperDir}-tmp"
fi
ln --symbolic --force --no-dereference $wrapperDir ${wrapperDir}-tmp
mv --no-target-directory ${wrapperDir}-tmp ${wrapperDir}
rm --force --recursive $old
ln --symbolic --force --no-dereference "$wrapperDir" "${wrapperDir}-tmp"
mv --no-target-directory "${wrapperDir}-tmp" "${wrapperDir}"
rm --force --recursive "$old"
else
# For initial setup
ln --symbolic $wrapperDir ${wrapperDir}
ln --symbolic "$wrapperDir" "${wrapperDir}"
fi
'';
###### wrappers consistency checks
system.extraDependencies = lib.singleton (pkgs.runCommandLocal
"ensure-all-wrappers-paths-exist" { }
''
# make sure we produce output
mkdir -p $out
echo -n "Checking that Nix store paths of all wrapped programs exist... "
declare -A wrappers
${lib.concatStringsSep "\n" (lib.mapAttrsToList (n: v:
"wrappers['${n}']='${v.source}'") wrappers)}
for name in "''${!wrappers[@]}"; do
path="''${wrappers[$name]}"
if [[ "$path" =~ /nix/store ]] && [ ! -e "$path" ]; then
test -t 1 && echo -ne '\033[1;31m'
echo "FAIL"
echo "The path $path does not exist!"
echo 'Please, check the value of `security.wrappers."'$name'".source`.'
test -t 1 && echo -ne '\033[0m'
exit 1
fi
done
echo "OK"
'');
};
}

View file

@ -52,8 +52,10 @@ with lib;
security.pam.services.login.enableGnomeKeyring = true;
security.wrappers.gnome-keyring-daemon = {
source = "${pkgs.gnome.gnome-keyring}/bin/gnome-keyring-daemon";
owner = "root";
group = "root";
capabilities = "cap_ipc_lock=ep";
source = "${pkgs.gnome.gnome-keyring}/bin/gnome-keyring-daemon";
};
};

View file

@ -104,7 +104,12 @@ in
gid = config.ids.gids.exim;
};
security.wrappers.exim.source = "${cfg.package}/bin/exim";
security.wrappers.exim =
{ setuid = true;
owner = "root";
group = "root";
source = "${cfg.package}/bin/exim";
};
systemd.services.exim = {
description = "Exim Mail Daemon";

View file

@ -1,4 +1,4 @@
{ config, lib, ... }:
{ config, options, lib, ... }:
with lib;
@ -11,6 +11,7 @@ with lib;
services.mail = {
sendmailSetuidWrapper = mkOption {
type = types.nullOr options.security.wrappers.type.nestedTypes.elemType;
default = null;
internal = true;
description = ''

View file

@ -103,12 +103,15 @@ in {
};
security.wrappers.smtpctl = {
owner = "nobody";
group = "smtpq";
setuid = false;
setgid = true;
source = "${cfg.package}/bin/smtpctl";
};
services.mail.sendmailSetuidWrapper = mkIf cfg.setSendmail security.wrappers.smtpctl;
services.mail.sendmailSetuidWrapper = mkIf cfg.setSendmail
security.wrappers.smtpctl // { program = "sendmail"; };
systemd.tmpfiles.rules = [
"d /var/spool/smtpd 711 root - - -"

View file

@ -673,6 +673,7 @@ in
services.mail.sendmailSetuidWrapper = mkIf config.services.postfix.setSendmail {
program = "sendmail";
source = "${pkgs.postfix}/bin/sendmail";
owner = "nobody";
group = setgidGroup;
setuid = false;
setgid = true;
@ -681,6 +682,7 @@ in
security.wrappers.mailq = {
program = "mailq";
source = "${pkgs.postfix}/bin/mailq";
owner = "nobody";
group = setgidGroup;
setuid = false;
setgid = true;
@ -689,6 +691,7 @@ in
security.wrappers.postqueue = {
program = "postqueue";
source = "${pkgs.postfix}/bin/postqueue";
owner = "nobody";
group = setgidGroup;
setuid = false;
setgid = true;
@ -697,6 +700,7 @@ in
security.wrappers.postdrop = {
program = "postdrop";
source = "${pkgs.postfix}/bin/postdrop";
owner = "nobody";
group = setgidGroup;
setuid = false;
setgid = true;

View file

@ -45,8 +45,10 @@ in
environment.systemPackages = [ pkgs.mame ];
security.wrappers."${mame}" = {
source = "${pkgs.mame}/bin/${mame}";
owner = "root";
group = "root";
capabilities = "cap_net_admin,cap_net_raw+eip";
source = "${pkgs.mame}/bin/${mame}";
};
systemd.services.mame = {

View file

@ -52,7 +52,12 @@ in
wants = [ "network.target" ];
};
security.wrappers.screen.source = "${pkgs.screen}/bin/screen";
security.wrappers.screen =
{ setuid = true;
owner = "root";
group = "root";
source = "${pkgs.screen}/bin/screen";
};
};
meta.doc = ./weechat.xml;

View file

@ -71,7 +71,12 @@ in
environment.systemPackages = [ pkgs.incron ];
security.wrappers.incrontab.source = "${pkgs.incron}/bin/incrontab";
security.wrappers.incrontab =
{ setuid = true;
owner = "root";
group = "root";
source = "${pkgs.incron}/bin/incrontab";
};
# incron won't read symlinks
environment.etc."incron.d/system" = {

View file

@ -262,7 +262,12 @@ in
};
security.wrappers = {
fping.source = "${pkgs.fping}/bin/fping";
fping =
{ setuid = true;
owner = "root";
group = "root";
source = "${pkgs.fping}/bin/fping";
};
};
systemd.services.zabbix-proxy = {

View file

@ -278,8 +278,18 @@ in
}
];
security.wrappers = {
fping.source = "${pkgs.fping}/bin/fping";
fping6.source = "${pkgs.fping}/bin/fping6";
fping =
{ setuid = true;
owner = "root";
group = "root";
source = "${pkgs.fping}/bin/fping";
};
fping6 =
{ setuid = true;
owner = "root";
group = "root";
source = "${pkgs.fping}/bin/fping6";
};
};
environment.systemPackages = [ pkgs.fping ];
users.users.${cfg.user} = {

View file

@ -88,12 +88,14 @@ in {
source = "${pkgs.x2goserver}/lib/x2go/libx2go-server-db-sqlite3-wrapper.pl";
owner = "x2go";
group = "x2go";
setuid = false;
setgid = true;
};
security.wrappers.x2goprintWrapper = {
source = "${pkgs.x2goserver}/bin/x2goprint";
owner = "x2go";
group = "x2go";
setuid = false;
setgid = true;
};

View file

@ -93,7 +93,12 @@ in
{ services.cron.enable = mkDefault (allFiles != []); }
(mkIf (config.services.cron.enable) {
security.wrappers.crontab.source = "${cronNixosPkg}/bin/crontab";
security.wrappers.crontab =
{ setuid = true;
owner = "root";
group = "root";
source = "${cronNixosPkg}/bin/crontab";
};
environment.systemPackages = [ cronNixosPkg ];
environment.etc.crontab =
{ source = pkgs.runCommand "crontabs" { inherit allFiles; preferLocalBuild = true; }

View file

@ -136,10 +136,13 @@ in
owner = "fcron";
group = "fcron";
setgid = true;
setuid = false;
};
fcronsighup = {
source = "${pkgs.fcron}/bin/fcronsighup";
owner = "root";
group = "fcron";
setuid = true;
};
};
systemd.services.fcron = {

View file

@ -44,8 +44,10 @@ in
security.wrappers = mkIf cfg.enableSysAdminCapability {
replay-sorcery = {
source = "${pkgs.replay-sorcery}/bin/replay-sorcery";
owner = "root";
group = "root";
capabilities = "cap_sys_admin+ep";
source = "${pkgs.replay-sorcery}/bin/replay-sorcery";
};
};

View file

@ -49,9 +49,10 @@ in {
users.groups.mail = {};
security.wrappers = {
dtmail = {
source = "${pkgs.cdesktopenv}/bin/dtmail";
group = "mail";
setgid = true;
owner = "nobody";
group = "mail";
source = "${pkgs.cdesktopenv}/bin/dtmail";
};
};

View file

@ -65,9 +65,24 @@ in
# Wrappers for programs installed by enlightenment that should be setuid
security.wrappers = {
enlightenment_ckpasswd.source = "${pkgs.enlightenment.enlightenment}/lib/enlightenment/utils/enlightenment_ckpasswd";
enlightenment_sys.source = "${pkgs.enlightenment.enlightenment}/lib/enlightenment/utils/enlightenment_sys";
enlightenment_system.source = "${pkgs.enlightenment.enlightenment}/lib/enlightenment/utils/enlightenment_system";
enlightenment_ckpasswd =
{ setuid = true;
owner = "root";
group = "root";
source = "${pkgs.enlightenment.enlightenment}/lib/enlightenment/utils/enlightenment_ckpasswd";
};
enlightenment_sys =
{ setuid = true;
owner = "root";
group = "root";
source = "${pkgs.enlightenment.enlightenment}/lib/enlightenment/utils/enlightenment_sys";
};
enlightenment_system =
{ setuid = true;
owner = "root";
group = "root";
source = "${pkgs.enlightenment.enlightenment}/lib/enlightenment/utils/enlightenment_system";
};
};
environment.etc."X11/xkb".source = xcfg.xkbDir;

View file

@ -197,11 +197,23 @@ in
};
security.wrappers = {
kcheckpass.source = "${lib.getBin libsForQt5.kscreenlocker}/libexec/kcheckpass";
start_kdeinit.source = "${lib.getBin libsForQt5.kinit}/libexec/kf5/start_kdeinit";
kwin_wayland = {
source = "${lib.getBin plasma5.kwin}/bin/kwin_wayland";
kcheckpass =
{ setuid = true;
owner = "root";
group = "root";
source = "${lib.getBin libsForQt5.kscreenlocker}/libexec/kcheckpass";
};
start_kdeinit =
{ setuid = true;
owner = "root";
group = "root";
source = "${lib.getBin libsForQt5.kinit}/libexec/kf5/start_kdeinit";
};
kwin_wayland =
{ owner = "root";
group = "root";
capabilities = "cap_sys_nice+ep";
source = "${lib.getBin plasma5.kwin}/bin/kwin_wayland";
};
};

View file

@ -7,8 +7,18 @@ with lib;
config = mkIf (any (fs: fs == "ecryptfs") config.boot.supportedFilesystems) {
system.fsPackages = [ pkgs.ecryptfs ];
security.wrappers = {
"mount.ecryptfs_private".source = "${pkgs.ecryptfs.out}/bin/mount.ecryptfs_private";
"umount.ecryptfs_private".source = "${pkgs.ecryptfs.out}/bin/umount.ecryptfs_private";
"mount.ecryptfs_private" =
{ setuid = true;
owner = "root";
group = "root";
source = "${pkgs.ecryptfs.out}/bin/mount.ecryptfs_private";
};
"umount.ecryptfs_private" =
{ setuid = true;
owner = "root";
group = "root";
source = "${pkgs.ecryptfs.out}/bin/umount.ecryptfs_private";
};
};
};
}

View file

@ -1133,11 +1133,16 @@ in
# kernel because we need the ambient capability
security.wrappers = if (versionAtLeast (getVersion config.boot.kernelPackages.kernel) "4.3") then {
ping = {
source = "${pkgs.iputils.out}/bin/ping";
owner = "root";
group = "root";
capabilities = "cap_net_raw+p";
source = "${pkgs.iputils.out}/bin/ping";
};
} else {
ping.source = "${pkgs.iputils.out}/bin/ping";
setuid = true;
owner = "root";
group = "root";
source = "${pkgs.iputils.out}/bin/ping";
};
security.apparmor.policies."bin.ping".profile = lib.mkIf config.security.apparmor.policies."bin.ping".enable (lib.mkAfter ''
/run/wrappers/bin/ping {

View file

@ -183,6 +183,9 @@ in {
};
security.wrappers.qemu-bridge-helper = {
setuid = true;
owner = "root";
group = "root";
source = "/run/${dirName}/nix-helpers/qemu-bridge-helper";
};

View file

@ -14,9 +14,11 @@
config = lib.mkIf config.virtualisation.spiceUSBRedirection.enable {
environment.systemPackages = [ pkgs.spice-gtk ]; # For polkit actions
security.wrappers.spice-client-glib-usb-acl-helper ={
source = "${pkgs.spice-gtk}/bin/spice-client-glib-usb-acl-helper";
security.wrappers.spice-client-glib-usb-acl-helper = {
owner = "root";
group = "root";
capabilities = "cap_fowner+ep";
source = "${pkgs.spice-gtk}/bin/spice-client-glib-usb-acl-helper";
};
};