146 lines
4.7 KiB
Nix
146 lines
4.7 KiB
Nix
{ config, pkgs, lib, ... }:
|
|
|
|
with lib;
|
|
|
|
let
|
|
cfg = config.security.grsecurity;
|
|
grsecLockPath = "/proc/sys/kernel/grsecurity/grsec_lock";
|
|
|
|
# Ascertain whether ZFS is required for booting the system; grsecurity is
|
|
# currently incompatible with ZFS, rendering the system unbootable.
|
|
zfsNeededForBoot = filter
|
|
(fs: (fs.neededForBoot
|
|
|| elem fs.mountPoint [ "/" "/nix" "/nix/store" "/var" "/var/log" "/var/lib" "/etc" ])
|
|
&& fs.fsType == "zfs")
|
|
config.system.build.fileSystems != [];
|
|
|
|
# Ascertain whether NixOS container support is required
|
|
containerSupportRequired =
|
|
config.boot.enableContainers && config.containers != {};
|
|
in
|
|
|
|
{
|
|
meta = {
|
|
maintainers = with maintainers; [ joachifm ];
|
|
doc = ./grsecurity.xml;
|
|
};
|
|
|
|
options.security.grsecurity = {
|
|
|
|
enable = mkEnableOption "grsecurity/PaX";
|
|
|
|
lockTunables = mkOption {
|
|
type = types.bool;
|
|
example = false;
|
|
default = true;
|
|
description = ''
|
|
Whether to automatically lock grsecurity tunables
|
|
(<option>boot.kernel.sysctl."kernel.grsecurity.*"</option>). Disable
|
|
this to allow runtime configuration of grsecurity features. Activate
|
|
the <literal>grsec-lock</literal> service unit to prevent further
|
|
configuration until the next reboot.
|
|
'';
|
|
};
|
|
|
|
disableEfiRuntimeServices = mkOption {
|
|
type = types.bool;
|
|
example = false;
|
|
default = true;
|
|
description = ''
|
|
Whether to disable access to EFI runtime services. Enabling EFI runtime
|
|
services creates a venue for code injection attacks on the kernel and
|
|
should be disabled if at all possible. Changing this option enters into
|
|
effect upon reboot.
|
|
'';
|
|
};
|
|
|
|
};
|
|
|
|
config = mkIf cfg.enable {
|
|
|
|
# Allow the user to select a different package set, subject to the stated
|
|
# required kernel config
|
|
boot.kernelPackages = mkDefault pkgs.linuxPackages_grsec_nixos;
|
|
|
|
boot.kernelParams = optional cfg.disableEfiRuntimeServices "noefi";
|
|
|
|
system.requiredKernelConfig = with config.lib.kernelConfig;
|
|
[ (isEnabled "GRKERNSEC")
|
|
(isEnabled "PAX")
|
|
(isYes "GRKERNSEC_SYSCTL")
|
|
(isYes "GRKERNSEC_SYSCTL_DISTRO")
|
|
(isNo "GRKERNSEC_NO_RBAC")
|
|
];
|
|
|
|
nixpkgs.config.grsecurity = true;
|
|
|
|
# Install PaX related utillities into the system profile.
|
|
environment.systemPackages = with pkgs; [ gradm paxctl pax-utils ];
|
|
|
|
# Install rules for the grsec device node
|
|
services.udev.packages = [ pkgs.gradm ];
|
|
|
|
# This service unit is responsible for locking the grsecurity tunables. The
|
|
# unit is always defined, but only activated on bootup if lockTunables is
|
|
# toggled. When lockTunables is toggled, failure to activate the unit will
|
|
# enter emergency mode. The intent is to make it difficult to silently
|
|
# enter multi-user mode without having locked the tunables. Some effort is
|
|
# made to ensure that starting the unit is an idempotent operation.
|
|
systemd.services.grsec-lock = {
|
|
description = "Lock grsecurity tunables";
|
|
|
|
wantedBy = optional cfg.lockTunables "multi-user.target";
|
|
|
|
wants = [ "local-fs.target" "systemd-sysctl.service" ];
|
|
after = [ "local-fs.target" "systemd-sysctl.service" ];
|
|
conflicts = [ "shutdown.target" ];
|
|
|
|
restartIfChanged = false;
|
|
|
|
script = ''
|
|
if ${pkgs.gnugrep}/bin/grep -Fq 0 ${grsecLockPath} ; then
|
|
echo -n 1 > ${grsecLockPath}
|
|
fi
|
|
'';
|
|
|
|
unitConfig = {
|
|
ConditionPathIsReadWrite = grsecLockPath;
|
|
DefaultDependencies = false;
|
|
} // optionalAttrs cfg.lockTunables {
|
|
OnFailure = "emergency.target";
|
|
};
|
|
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
RemainAfterExit = true;
|
|
};
|
|
};
|
|
|
|
# Configure system tunables
|
|
boot.kernel.sysctl = {
|
|
# Read-only under grsecurity
|
|
"kernel.kptr_restrict" = mkForce null;
|
|
} // optionalAttrs config.nix.useSandbox {
|
|
# chroot(2) restrictions that conflict with sandboxed Nix builds
|
|
"kernel.grsecurity.chroot_caps" = mkForce 0;
|
|
"kernel.grsecurity.chroot_deny_chroot" = mkForce 0;
|
|
"kernel.grsecurity.chroot_deny_mount" = mkForce 0;
|
|
"kernel.grsecurity.chroot_deny_pivot" = mkForce 0;
|
|
"kernel.grsecurity.chroot_deny_chmod" = mkForce 0;
|
|
} // optionalAttrs containerSupportRequired {
|
|
# chroot(2) restrictions that conflict with NixOS lightweight containers
|
|
"kernel.grsecurity.chroot_deny_chmod" = mkForce 0;
|
|
"kernel.grsecurity.chroot_deny_mount" = mkForce 0;
|
|
"kernel.grsecurity.chroot_restrict_nice" = mkForce 0;
|
|
"kernel.grsecurity.chroot_caps" = mkForce 0;
|
|
};
|
|
|
|
assertions = [
|
|
{ assertion = !zfsNeededForBoot;
|
|
message = "grsecurity is currently incompatible with ZFS";
|
|
}
|
|
];
|
|
|
|
};
|
|
}
|