nixos: add optional process information hiding

This module adds an option `security.hideProcessInformation` that, when
enabled, restricts access to process information such as command-line
arguments to the process owner.  The module adds a static group "proc"
whose members are exempt from process information hiding.

Ideally, this feature would be implemented by simply adding the
appropriate mount options to `fileSystems."/proc".fsOptions`, but this
was found to not work in vmtests. To ensure that process information
hiding is enforced, we use a systemd service unit that remounts `/proc`
after `systemd-remount-fs.service` has completed.

To verify the correctness of the feature, simple tests were added to
nixos/tests/misc: the test ensures that unprivileged users cannot see
process information owned by another user, while members of "proc" CAN.

Thanks to @abbradar for feedback and suggestions.
This commit is contained in:
Joachim Fasting 2016-04-09 20:22:16 +02:00
parent 496a369805
commit cef2814a4f
4 changed files with 54 additions and 0 deletions

View File

@ -47,6 +47,7 @@
#floppy = 18; # unused
#uucp = 19; # unused
#lp = 20; # unused
#proc = 21; # unused
pulseaudio = 22; # must match `pulseaudio' GID
gpsd = 23;
#cdrom = 24; # unused
@ -288,6 +289,7 @@
floppy = 18;
uucp = 19;
lp = 20;
proc = 21;
pulseaudio = 22; # must match `pulseaudio' UID
gpsd = 23;
cdrom = 24;

View File

@ -90,6 +90,7 @@
./security/ca.nix
./security/duosec.nix
./security/grsecurity.nix
./security/hidepid.nix
./security/oath.nix
./security/pam.nix
./security/pam_usb.nix

View File

@ -0,0 +1,42 @@
{ config, pkgs, lib, ... }:
with lib;
{
options = {
security.hideProcessInformation = mkEnableOption "" // { description = ''
Restrict access to process information to the owning user. Enabling
this option implies, among other things, that command-line arguments
remain private. This option is recommended for most systems, unless
there's a legitimate reason for allowing unprivileged users to inspect
the process information of other users.
Members of the group "proc" are exempt from process information hiding.
To allow a service to run without process information hiding, add "proc"
to its supplementary groups via
<option>systemd.services.&lt;name?&gt;.serviceConfig.SupplementaryGroups</option>.
''; };
};
config = mkIf config.security.hideProcessInformation {
users.groups.proc.gid = config.ids.gids.proc;
systemd.services.hidepid = {
wantedBy = [ "local-fs.target" ];
after = [ "systemd-remount-fs.service" ];
before = [ "local-fs-pre.target" "local-fs.target" "shutdown.target" ];
wants = [ "local-fs-pre.target" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = ''${pkgs.utillinux}/bin/mount -o remount,hidepid=2,gid=${toString config.ids.gids.proc} /proc'';
ExecStop = ''${pkgs.utillinux}/bin/mount -o remount,hidepid=0,gid=0 /proc'';
};
unitConfig = {
DefaultDependencies = false;
Conflicts = "shutdown.target";
};
};
};
}

View File

@ -25,6 +25,8 @@ import ./make-test.nix ({ pkgs, ...} : {
};
users.users.sybil = { isNormalUser = true; group = "wheel"; };
security.sudo = { enable = true; wheelNeedsPassword = false; };
security.hideProcessInformation = true;
users.users.alice = { isNormalUser = true; extraGroups = [ "proc" ]; };
};
testScript =
@ -117,5 +119,12 @@ import ./make-test.nix ({ pkgs, ...} : {
subtest "sudo", sub {
$machine->succeed("su - sybil -c 'sudo true'");
};
# Test hidepid
subtest "hidepid", sub {
$machine->succeed("grep -Fq hidepid=2 /etc/mtab");
$machine->succeed("[ `su - sybil -c 'pgrep -c -u root'` = 0 ]");
$machine->succeed("[ `su - alice -c 'pgrep -c -u root'` != 0 ]");
};
'';
})