nixos/sudo: add option execWheelOnly

By setting the executable's group to wheel and permissions to 4510, we
make sure that only members of the wheel group can execute sudo.

Changed files
+45 -4
nixos
modules
security
tests
+25 -3
nixos/modules/security/sudo.nix
···
'';
};
+
security.sudo.execWheelOnly = mkOption {
+
type = types.bool;
+
default = false;
+
description = ''
+
Only allow members of the <code>wheel</code> group to execute sudo by
+
setting the executable's permissions accordingly.
+
This prevents users that are not members of <code>wheel</code> from
+
exploiting vulnerabilities in sudo such as CVE-2021-3156.
+
'';
+
};
+
security.sudo.configFile = mkOption {
type = types.lines;
# Note: if syntax errors are detected in this file, the NixOS
···
${cfg.extraConfig}
'';
-
security.wrappers = {
-
sudo.source = "${cfg.package.out}/bin/sudo";
-
sudoedit.source = "${cfg.package.out}/bin/sudoedit";
+
security.wrappers = let
+
owner = "root";
+
group = if cfg.execWheelOnly then "wheel" else "root";
+
setuid = true;
+
permissions = if cfg.execWheelOnly then "u+rx,g+x" else "u+rx,g+x,o+x";
+
in {
+
sudo = {
+
source = "${cfg.package.out}/bin/sudo";
+
inherit owner group setuid permissions;
+
};
+
sudoedit = {
+
source = "${cfg.package.out}/bin/sudoedit";
+
inherit owner group setuid permissions;
+
};
};
environment.systemPackages = [ sudo ];
+20 -1
nixos/tests/sudo.nix
···
maintainers = [ lschuermann ];
};
-
machine =
+
nodes.machine =
{ lib, ... }:
with lib;
{
···
};
};
+
nodes.strict = { ... }: {
+
users.users = {
+
admin = { isNormalUser = true; extraGroups = [ "wheel" ]; };
+
noadmin = { isNormalUser = true; };
+
};
+
+
security.sudo = {
+
enable = true;
+
wheelNeedsPassword = false;
+
execWheelOnly = true;
+
};
+
};
+
testScript =
''
with subtest("users in wheel group should have passwordless sudo"):
···
with subtest("users in group 'barfoo' should not be able to keep their environment"):
machine.fail("sudo -u test3 sudo -n -E -u root true")
+
+
with subtest("users in wheel should be able to run sudo despite execWheelOnly"):
+
strict.succeed('su - admin -c "sudo -u root true"')
+
+
with subtest("non-wheel users should be unable to run sudo thanks to execWheelOnly"):
+
strict.fail('su - noadmin -c "sudo --help"')
'';
})