diff --git a/modules/presets/secure-node.nix b/modules/presets/secure-node.nix index 25a6d47..4036282 100644 --- a/modules/presets/secure-node.nix +++ b/modules/presets/secure-node.nix @@ -18,7 +18,7 @@ in { networking.firewall.enable = true; - nix-bitcoin.security.hideProcessInformation = true; + nix-bitcoin.security.dbusHideProcessInformation = true; # Use doas instead of sudo security.doas.enable = true; diff --git a/modules/security.nix b/modules/security.nix index cd5ad4e..0ea57b7 100644 --- a/modules/security.nix +++ b/modules/security.nix @@ -1,20 +1,29 @@ -{ config, lib, pkgs, options, ... }: +{ config, lib, pkgs, ... }: +with lib; { options = { - nix-bitcoin.security.hideProcessInformation = options.security.hideProcessInformation; + nix-bitcoin.security.dbusHideProcessInformation = mkOption { + type = types.bool; + default = false; + description = '' + Only allow users with group 'proc' to retrieve systemd unit information like + cgroup paths (i.e. (sub)process command lines) via D-Bus. + + This mitigates a systemd security issue where (sub)process command lines can + be retrieved by services even when their access to /proc is restricted + (via ProtectProc). + + This option works by restricting the D-Bus method 'GetUnitProcesses', which + is also used internally by `systemctl status`. + ''; + }; }; - config = lib.mkIf config.nix-bitcoin.security.hideProcessInformation { - # Only show the current user's processes in /proc. - # Users with group 'proc' can still access all processes. - security.hideProcessInformation = true; + config = mkIf config.nix-bitcoin.security.dbusHideProcessInformation { + users.groups.proc = {}; + nix-bitcoin.operator.groups = [ "proc" ]; # Enable operator access to systemd-status - # This mitigates a systemd security issue leaking (sub)process - # command lines. - # 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 = lib.mkAfter [ # Apply at the end to override the default policy (pkgs.writeTextDir "etc/dbus-1/system.d/dbus.conf" '' diff --git a/pkgs/lib.nix b/pkgs/lib.nix index 1d53289..660820b 100644 --- a/pkgs/lib.nix +++ b/pkgs/lib.nix @@ -17,9 +17,8 @@ let self = { ProtectKernelModules = "true"; ProtectKernelLogs = "true"; ProtectClock = "true"; - # Test and enable these when systemd v247 is available - # ProtectProc = "invisible"; - # ProcSubset = "pid"; + ProtectProc = "invisible"; + ProcSubset = "pid"; ProtectControlGroups = "true"; RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6"; RestrictNamespaces = "true"; diff --git a/test/tests.py b/test/tests.py index 724e2d4..1208848 100644 --- a/test/tests.py +++ b/test/tests.py @@ -85,9 +85,6 @@ def _(): succeed('[[ $(stat -c "%U:%G %a" /secrets/dummy) = "root:root 440" ]]') if "secure-node" in enabled_tests: - # Access to '/proc' should be restricted - machine.succeed("grep -Fq hidepid=2 /proc/mounts") - machine.wait_for_unit("bitcoind") # `systemctl status` run by unprivileged users shouldn't leak cgroup info assert_matches( @@ -97,7 +94,6 @@ def _(): # The 'operator' with group 'proc' has full access assert_full_match("runuser -u operator -- systemctl status bitcoind 2>&1 >/dev/null", "") - @test("bitcoind") def _(): assert_running("bitcoind")