at 16.09-beta 4.8 kB view raw
1{ config, pkgs, lib, ... }: 2 3with lib; 4 5let 6 cfg = config.security.grsecurity; 7 grsecLockPath = "/proc/sys/kernel/grsecurity/grsec_lock"; 8 9 # Ascertain whether ZFS is required for booting the system; grsecurity is 10 # currently incompatible with ZFS, rendering the system unbootable. 11 zfsNeededForBoot = filter 12 (fs: (fs.neededForBoot 13 || elem fs.mountPoint [ "/" "/nix" "/nix/store" "/var" "/var/log" "/var/lib" "/etc" ]) 14 && fs.fsType == "zfs") 15 config.system.build.fileSystems != []; 16 17 # Ascertain whether NixOS container support is required 18 containerSupportRequired = 19 config.boot.enableContainers && config.containers != {}; 20in 21 22{ 23 meta = { 24 maintainers = with maintainers; [ joachifm ]; 25 doc = ./grsecurity.xml; 26 }; 27 28 options.security.grsecurity = { 29 30 enable = mkEnableOption "grsecurity/PaX"; 31 32 lockTunables = mkOption { 33 type = types.bool; 34 example = false; 35 default = true; 36 description = '' 37 Whether to automatically lock grsecurity tunables 38 (<option>boot.kernel.sysctl."kernel.grsecurity.*"</option>). Disable 39 this to allow runtime configuration of grsecurity features. Activate 40 the <literal>grsec-lock</literal> service unit to prevent further 41 configuration until the next reboot. 42 ''; 43 }; 44 45 disableEfiRuntimeServices = mkOption { 46 type = types.bool; 47 example = false; 48 default = true; 49 description = '' 50 Whether to disable access to EFI runtime services. Enabling EFI runtime 51 services creates a venue for code injection attacks on the kernel and 52 should be disabled if at all possible. Changing this option enters into 53 effect upon reboot. 54 ''; 55 }; 56 57 }; 58 59 config = mkIf cfg.enable { 60 61 # Allow the user to select a different package set, subject to the stated 62 # required kernel config 63 boot.kernelPackages = mkDefault pkgs.linuxPackages_grsec_nixos; 64 65 boot.kernelParams = optional cfg.disableEfiRuntimeServices "noefi"; 66 67 system.requiredKernelConfig = with config.lib.kernelConfig; 68 [ (isEnabled "GRKERNSEC") 69 (isEnabled "PAX") 70 (isYES "GRKERNSEC_SYSCTL") 71 (isYES "GRKERNSEC_SYSCTL_DISTRO") 72 (isNO "GRKERNSEC_NO_RBAC") 73 ]; 74 75 # Install PaX related utillities into the system profile. 76 environment.systemPackages = with pkgs; [ gradm paxctl pax-utils ]; 77 78 # Install rules for the grsec device node 79 services.udev.packages = [ pkgs.gradm ]; 80 81 # This service unit is responsible for locking the grsecurity tunables. The 82 # unit is always defined, but only activated on bootup if lockTunables is 83 # toggled. When lockTunables is toggled, failure to activate the unit will 84 # enter emergency mode. The intent is to make it difficult to silently 85 # enter multi-user mode without having locked the tunables. Some effort is 86 # made to ensure that starting the unit is an idempotent operation. 87 systemd.services.grsec-lock = { 88 description = "Lock grsecurity tunables"; 89 90 wantedBy = optional cfg.lockTunables "multi-user.target"; 91 92 wants = [ "local-fs.target" "systemd-sysctl.service" ]; 93 after = [ "local-fs.target" "systemd-sysctl.service" ]; 94 conflicts = [ "shutdown.target" ]; 95 96 restartIfChanged = false; 97 98 script = '' 99 if ${pkgs.gnugrep}/bin/grep -Fq 0 ${grsecLockPath} ; then 100 echo -n 1 > ${grsecLockPath} 101 fi 102 ''; 103 104 unitConfig = { 105 ConditionPathIsReadWrite = grsecLockPath; 106 DefaultDependencies = false; 107 } // optionalAttrs cfg.lockTunables { 108 OnFailure = "emergency.target"; 109 }; 110 111 serviceConfig = { 112 Type = "oneshot"; 113 RemainAfterExit = true; 114 }; 115 }; 116 117 # Configure system tunables 118 boot.kernel.sysctl = { 119 # Read-only under grsecurity 120 "kernel.kptr_restrict" = mkForce null; 121 } // optionalAttrs config.nix.useSandbox { 122 # chroot(2) restrictions that conflict with sandboxed Nix builds 123 "kernel.grsecurity.chroot_caps" = mkForce 0; 124 "kernel.grsecurity.chroot_deny_chroot" = mkForce 0; 125 "kernel.grsecurity.chroot_deny_mount" = mkForce 0; 126 "kernel.grsecurity.chroot_deny_pivot" = mkForce 0; 127 "kernel.grsecurity.chroot_deny_chmod" = mkForce 0; 128 } // optionalAttrs containerSupportRequired { 129 # chroot(2) restrictions that conflict with NixOS lightweight containers 130 "kernel.grsecurity.chroot_deny_chmod" = mkForce 0; 131 "kernel.grsecurity.chroot_deny_mount" = mkForce 0; 132 "kernel.grsecurity.chroot_restrict_nice" = mkForce 0; 133 "kernel.grsecurity.chroot_caps" = mkForce 0; 134 }; 135 136 assertions = [ 137 { assertion = !zfsNeededForBoot; 138 message = "grsecurity is currently incompatible with ZFS"; 139 } 140 ]; 141 142 }; 143}