diff --git a/nixos/modules/profiles/hardened.nix b/nixos/modules/profiles/hardened.nix index 61e871bcaca5..bad4cb81639d 100644 --- a/nixos/modules/profiles/hardened.nix +++ b/nixos/modules/profiles/hardened.nix @@ -20,6 +20,8 @@ with lib; security.allowUserNamespaces = mkDefault false; + security.protectKernelImage = mkDefault true; + security.apparmor.enable = mkDefault true; boot.kernelParams = [ @@ -28,9 +30,6 @@ with lib; # Disable legacy virtual syscalls "vsyscall=none" - - # Disable hibernation (allows replacing the running kernel) - "nohibernate" ]; boot.blacklistedKernelModules = [ @@ -44,9 +43,6 @@ with lib; # (e.g., parent/child) boot.kernel.sysctl."kernel.yama.ptrace_scope" = mkOverride 500 1; - # Prevent replacing the running kernel image w/o reboot - boot.kernel.sysctl."kernel.kexec_load_disabled" = mkDefault true; - # Restrict access to kernel ring buffer (information leaks) boot.kernel.sysctl."kernel.dmesg_restrict" = mkDefault true; diff --git a/nixos/modules/security/misc.nix b/nixos/modules/security/misc.nix index f3fc6db22ead..b1db0bc8da85 100644 --- a/nixos/modules/security/misc.nix +++ b/nixos/modules/security/misc.nix @@ -22,6 +22,14 @@ with lib; a user namespace fails with "no space left on device" (ENOSPC). ''; }; + + security.protectKernelImage = mkOption { + type = types.bool; + default = false; + description = '' + Whether to prevent replacing the running kernel image. + ''; + }; }; config = mkMerge [ @@ -37,5 +45,12 @@ with lib; } ]; }) + + (mkIf config.security.protectKernelImage { + # Disable hibernation (allows replacing the running kernel) + boot.kernelParams = [ "nohibernate" ]; + # Prevent replacing the running kernel image w/o reboot + boot.kernel.sysctl."kernel.kexec_load_disabled" = mkDefault true; + }) ]; } diff --git a/nixos/tests/hardened.nix b/nixos/tests/hardened.nix index e10a6363164a..683f56c45af4 100644 --- a/nixos/tests/hardened.nix +++ b/nixos/tests/hardened.nix @@ -70,5 +70,11 @@ import ./make-test.nix ({ pkgs, ...} : { $machine->fail("su -l nobody -s /bin/sh -c 'nix ping-store'"); $machine->succeed("su -l alice -c 'nix ping-store'") =~ "OK"; }; + + # Test kernel image protection + subtest "kernelimage", sub { + $machine->fail("systemctl hibernate"); + $machine->fail("systemctl kexec"); + }; ''; })