security: update /proc restriction mechanism

NixOS option `security.hideProcessInformation` for globally restricting
access to /proc has been removed.
Use per-service restrictions via 'ProtectProc' instead.

Rename
`nix-bitcoin.security.hideProcessInformation` to
`nix-bitcoin.security.dbusHideProcessInformation`
because this option now only implements the dbus restriction.
This commit is contained in:
Erik Arvstedt 2021-08-05 00:49:01 +02:00
parent 178a0dcf8f
commit 35fe939cf8
No known key found for this signature in database
GPG Key ID: 33312B944DD97846
4 changed files with 23 additions and 19 deletions

View File

@ -18,7 +18,7 @@ in {
networking.firewall.enable = true; networking.firewall.enable = true;
nix-bitcoin.security.hideProcessInformation = true; nix-bitcoin.security.dbusHideProcessInformation = true;
# Use doas instead of sudo # Use doas instead of sudo
security.doas.enable = true; security.doas.enable = true;

View File

@ -1,20 +1,29 @@
{ config, lib, pkgs, options, ... }: { config, lib, pkgs, ... }:
with lib;
{ {
options = { 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 { config = mkIf config.nix-bitcoin.security.dbusHideProcessInformation {
# Only show the current user's processes in /proc. users.groups.proc = {};
# Users with group 'proc' can still access all processes. nix-bitcoin.operator.groups = [ "proc" ]; # Enable operator access to systemd-status
security.hideProcessInformation = true;
# 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 services.dbus.packages = lib.mkAfter [ # Apply at the end to override the default policy
(pkgs.writeTextDir "etc/dbus-1/system.d/dbus.conf" '' (pkgs.writeTextDir "etc/dbus-1/system.d/dbus.conf" ''
<busconfig> <busconfig>

View File

@ -17,9 +17,8 @@ let self = {
ProtectKernelModules = "true"; ProtectKernelModules = "true";
ProtectKernelLogs = "true"; ProtectKernelLogs = "true";
ProtectClock = "true"; ProtectClock = "true";
# Test and enable these when systemd v247 is available ProtectProc = "invisible";
# ProtectProc = "invisible"; ProcSubset = "pid";
# ProcSubset = "pid";
ProtectControlGroups = "true"; ProtectControlGroups = "true";
RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6"; RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
RestrictNamespaces = "true"; RestrictNamespaces = "true";

View File

@ -85,9 +85,6 @@ def _():
succeed('[[ $(stat -c "%U:%G %a" /secrets/dummy) = "root:root 440" ]]') succeed('[[ $(stat -c "%U:%G %a" /secrets/dummy) = "root:root 440" ]]')
if "secure-node" in enabled_tests: 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") machine.wait_for_unit("bitcoind")
# `systemctl status` run by unprivileged users shouldn't leak cgroup info # `systemctl status` run by unprivileged users shouldn't leak cgroup info
assert_matches( assert_matches(
@ -97,7 +94,6 @@ def _():
# The 'operator' with group 'proc' has full access # The 'operator' with group 'proc' has full access
assert_full_match("runuser -u operator -- systemctl status bitcoind 2>&1 >/dev/null", "") assert_full_match("runuser -u operator -- systemctl status bitcoind 2>&1 >/dev/null", "")
@test("bitcoind") @test("bitcoind")
def _(): def _():
assert_running("bitcoind") assert_running("bitcoind")