diff --git a/modules/presets/secure-node.nix b/modules/presets/secure-node.nix index 374dd52..7933487 100644 --- a/modules/presets/secure-node.nix +++ b/modules/presets/secure-node.nix @@ -227,6 +227,7 @@ in { isNormalUser = true; extraGroups = [ "systemd-journal" + "proc" # Enable full /proc access and systemd-status cfg.bitcoind.group ] ++ (optionals cfg.clightning.enable [ "clightning" ]) diff --git a/modules/security.nix b/modules/security.nix index 89efc66..f4d2c78 100644 --- a/modules/security.nix +++ b/modules/security.nix @@ -7,21 +7,27 @@ # This mitigates a systemd security issue leaking (sub)process # command lines. - # Only allow root to retrieve systemd unit information like + # Only allow users with group 'proc' to retrieve systemd unit information like # cgroup paths (i.e. (sub)process command lines) via D-Bus. # This D-Bus call is used by `systemctl status`. - services.dbus.packages = [ (pkgs.writeTextDir "etc/dbus-1/system.d/dbus.conf" '' - - - - - - - - - '') ]; + services.dbus.packages = lib.mkAfter [ # Apply at the end to override the default policy + (pkgs.writeTextDir "etc/dbus-1/system.d/dbus.conf" '' + + + + + + + + + '') + ]; } diff --git a/test/scenarios/lib.py b/test/scenarios/lib.py index 78c28a8..2ebda30 100644 --- a/test/scenarios/lib.py +++ b/test/scenarios/lib.py @@ -103,11 +103,13 @@ def run_tests(extra_tests): machine.wait_until_succeeds(log_has_string("bitcoind-import-banlist", "Importing node banlist")) assert_no_failure("bitcoind-import-banlist") - # test that `systemctl status` can't leak credentials + # `systemctl status` run by unprivileged users shouldn't leak cgroup info assert_matches( "sudo -u electrs systemctl status clightning 2>&1 >/dev/null", "Failed to dump process list for 'clightning.service', ignoring: Access denied", ) + # The 'operator' with group 'proc' has full access + assert_full_match("sudo -u operator systemctl status clightning 2>&1 >/dev/null", "") machine.succeed("grep -Fq hidepid=2 /proc/mounts") ### Additional tests