1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.security.grsecurity; 7 8 customGrsecPkg = 9 (import ../../../pkgs/build-support/grsecurity { 10 grsecOptions = cfg; 11 inherit pkgs lib; 12 }).grsecPackage; 13in 14{ 15 options = { 16 security.grsecurity = { 17 enable = mkOption { 18 type = types.bool; 19 default = false; 20 description = '' 21 Enable grsecurity support. This enables advanced exploit 22 hardening for the Linux kernel, and adds support for 23 administrative Role-Based Acess Control (RBAC) via 24 <literal>gradm</literal>. It also includes traditional 25 utilities for PaX. 26 ''; 27 }; 28 29 stable = mkOption { 30 type = types.bool; 31 default = false; 32 description = '' 33 Enable the stable grsecurity patch, based on Linux 3.14. 34 ''; 35 }; 36 37 testing = mkOption { 38 type = types.bool; 39 default = false; 40 description = '' 41 Enable the testing grsecurity patch, based on Linux 4.0. 42 ''; 43 }; 44 45 config = { 46 mode = mkOption { 47 type = types.enum [ "auto" "custom" ]; 48 default = "auto"; 49 description = '' 50 grsecurity configuration mode. This specifies whether 51 grsecurity is auto-configured or otherwise completely 52 manually configured. 53 ''; 54 }; 55 56 priority = mkOption { 57 type = types.enum [ "security" "performance" ]; 58 default = "security"; 59 description = '' 60 grsecurity configuration priority. This specifies whether 61 the kernel configuration should emphasize speed or 62 security. 63 ''; 64 }; 65 66 system = mkOption { 67 type = types.enum [ "desktop" "server" ]; 68 default = "desktop"; 69 description = '' 70 grsecurity system configuration. 71 ''; 72 }; 73 74 virtualisationConfig = mkOption { 75 type = types.nullOr (types.enum [ "host" "guest" ]); 76 default = null; 77 description = '' 78 grsecurity virtualisation configuration. This specifies 79 the virtualisation role of the machine - that is, whether 80 it will be a virtual machine guest, a virtual machine 81 host, or neither. 82 ''; 83 }; 84 85 hardwareVirtualisation = mkOption { 86 type = types.nullOr types.bool; 87 default = null; 88 example = true; 89 description = '' 90 grsecurity hardware virtualisation configuration. Set to 91 <literal>true</literal> if your machine supports hardware 92 accelerated virtualisation. 93 ''; 94 }; 95 96 virtualisationSoftware = mkOption { 97 type = types.nullOr (types.enum [ "kvm" "xen" "vmware" "virtualbox" ]); 98 default = null; 99 description = '' 100 Configure grsecurity for use with this virtualisation software. 101 ''; 102 }; 103 104 sysctl = mkOption { 105 type = types.bool; 106 default = false; 107 description = '' 108 If true, then set <literal>GRKERN_SYSCTL y</literal>. If 109 enabled then grsecurity can be controlled using sysctl 110 (and turned off). You are advised to *never* enable this, 111 but if you do, make sure to always set the sysctl 112 <literal>kernel.grsecurity.grsec_lock</literal> to 113 non-zero as soon as all sysctl options are set. *THIS IS 114 EXTREMELY IMPORTANT*! 115 ''; 116 }; 117 118 denyChrootChmod = mkOption { 119 type = types.bool; 120 default = false; 121 description = '' 122 If true, then set <literal>GRKERN_CHROOT_CHMOD 123 y</literal>. If enabled, this denies processes inside a 124 chroot from setting the suid or sgid bits using 125 <literal>chmod</literal> or <literal>fchmod</literal>. 126 127 By default this protection is disabled - it makes it 128 impossible to use Nix to build software on your system, 129 which is what most users want. 130 131 If you are using NixOps to deploy your software to a 132 remote machine, you're encouraged to enable this as you 133 won't need to compile code. 134 ''; 135 }; 136 137 denyUSB = mkOption { 138 type = types.bool; 139 default = false; 140 description = '' 141 If true, then set <literal>GRKERNSEC_DENYUSB y</literal>. 142 143 This enables a sysctl with name 144 <literal>kernel.grsecurity.deny_new_usb</literal>. Setting 145 its value to <literal>1</literal> will prevent any new USB 146 devices from being recognized by the OS. Any attempted 147 USB device insertion will be logged. 148 149 This option is intended to be used against custom USB 150 devices designed to exploit vulnerabilities in various USB 151 device drivers. 152 ''; 153 }; 154 155 restrictProc = mkOption { 156 type = types.bool; 157 default = false; 158 description = '' 159 If true, then set <literal>GRKERN_PROC_USER 160 y</literal>. This restricts non-root users to only viewing 161 their own processes and restricts network-related 162 information, kernel symbols, and module information. 163 ''; 164 }; 165 166 restrictProcWithGroup = mkOption { 167 type = types.bool; 168 default = true; 169 description = '' 170 If true, then set <literal>GRKERN_PROC_USERGROUP 171 y</literal>. This is similar to 172 <literal>restrictProc</literal> except it allows a special 173 group (specified by <literal>unrestrictProcGid</literal>) 174 to still access otherwise classified information in 175 <literal>/proc</literal>. 176 ''; 177 }; 178 179 unrestrictProcGid = mkOption { 180 type = types.int; 181 default = config.ids.gids.grsecurity; 182 description = '' 183 If set, specifies a GID which is exempt from 184 <literal>/proc</literal> restrictions (set by 185 <literal>GRKERN_PROC_USERGROUP</literal>). By default, 186 this is set to the GID for <literal>grsecurity</literal>, 187 a predefined NixOS group, which the 188 <literal>root</literal> account is a member of. You may 189 conveniently add other users to this group if you need 190 access to <literal>/proc</literal> 191 ''; 192 }; 193 194 disableRBAC = mkOption { 195 type = types.bool; 196 default = false; 197 description = '' 198 If true, then set <literal>GRKERN_NO_RBAC 199 y</literal>. This disables the 200 <literal>/dev/grsec</literal> device, which in turn 201 disables the RBAC system (and <literal>gradm</literal>). 202 ''; 203 }; 204 205 verboseVersion = mkOption { 206 type = types.bool; 207 default = false; 208 description = "Use verbose version in kernel localversion."; 209 }; 210 211 kernelExtraConfig = mkOption { 212 type = types.str; 213 default = ""; 214 description = "Extra kernel configuration parameters."; 215 }; 216 }; 217 }; 218 }; 219 220 config = mkIf cfg.enable { 221 assertions = 222 [ { assertion = cfg.stable || cfg.testing; 223 message = '' 224 If grsecurity is enabled, you must select either the 225 stable patch (with kernel 3.14), or the testing patch (with 226 kernel 4.0) to continue. 227 ''; 228 } 229 { assertion = !(cfg.stable && cfg.testing); 230 message = "Select either one of the stable or testing patch"; 231 } 232 { assertion = (cfg.config.restrictProc -> !cfg.config.restrictProcWithGroup) || 233 (cfg.config.restrictProcWithGroup -> !cfg.config.restrictProc); 234 message = "You cannot enable both restrictProc and restrictProcWithGroup"; 235 } 236 { assertion = config.boot.kernelPackages.kernel.features ? grsecurity 237 && config.boot.kernelPackages.kernel.features.grsecurity; 238 message = "grsecurity enabled, but kernel doesn't have grsec support"; 239 } 240 { assertion = (cfg.config.mode == "auto" && (cfg.config.virtualisationConfig != null)) -> 241 cfg.config.hardwareVirtualisation != null; 242 message = "when using auto grsec mode with virtualisation, you must specify if your hardware has virtualisation extensions"; 243 } 244 { assertion = (cfg.config.mode == "auto" && (cfg.config.virtualisationConfig != null)) -> 245 cfg.config.virtualisationSoftware != null; 246 message = "grsecurity configured for virtualisation but no virtualisation software specified"; 247 } 248 ]; 249 250 systemd.services.grsec-lock = mkIf cfg.config.sysctl { 251 description = "grsecurity sysctl-lock Service"; 252 requires = [ "systemd-sysctl.service" ]; 253 wantedBy = [ "multi-user.target" ]; 254 serviceConfig.Type = "oneshot"; 255 serviceConfig.RemainAfterExit = "yes"; 256 unitConfig.ConditionPathIsReadWrite = "/proc/sys/kernel/grsecurity/grsec_lock"; 257 script = '' 258 locked=`cat /proc/sys/kernel/grsecurity/grsec_lock` 259 if [ "$locked" == "0" ]; then 260 echo 1 > /proc/sys/kernel/grsecurity/grsec_lock 261 echo grsecurity sysctl lock - enabled 262 else 263 echo grsecurity sysctl lock already enabled - doing nothing 264 fi 265 ''; 266 }; 267 268# systemd.services.grsec-learn = { 269# description = "grsecurity learning Service"; 270# wantedBy = [ "local-fs.target" ]; 271# serviceConfig = { 272# Type = "oneshot"; 273# RemainAfterExit = "yes"; 274# ExecStart = "${pkgs.gradm}/sbin/gradm -VFL /etc/grsec/learning.logs"; 275# ExecStop = "${pkgs.gradm}/sbin/gradm -D"; 276# }; 277# }; 278 279 system.activationScripts = lib.optionalAttrs (!cfg.config.disableRBAC) { grsec = '' 280 mkdir -p /etc/grsec 281 if [ ! -f /etc/grsec/learn_config ]; then 282 cp ${pkgs.gradm}/etc/grsec/learn_config /etc/grsec 283 fi 284 if [ ! -f /etc/grsec/policy ]; then 285 cp ${pkgs.gradm}/etc/grsec/policy /etc/grsec 286 fi 287 chmod -R 0600 /etc/grsec 288 ''; }; 289 290 # Enable AppArmor, gradm udev rules, and utilities 291 security.apparmor.enable = true; 292 boot.kernelPackages = customGrsecPkg; 293 services.udev.packages = lib.optional (!cfg.config.disableRBAC) pkgs.gradm; 294 environment.systemPackages = [ pkgs.paxctl pkgs.pax-utils ] ++ lib.optional (!cfg.config.disableRBAC) pkgs.gradm; 295 }; 296}