From 6feb61233bc66d00bdb28dc2375bd2c5221858fd Mon Sep 17 00:00:00 2001 From: "Ricardo M. Correia" Date: Fri, 29 May 2020 14:25:48 +0200 Subject: [PATCH 1/2] linux: make sure all config options have the same value Currently, kernel config options whose value is "yes" always override options whose value is "no". This is not always desired. Generally speaking, if someone defines an option to have the value "no", presumably they are disabling the option for a reason, so it's not always OK to silently enable it due to another, probably unrelated reason. For example, a user may want to reduce the kernel attack surface and therefore may want to disable features that are being enabled in common-config.nix. In fact, common-config.nix was already silently enabling options that were intended to be disabled in hardened/config.nix for security reasons, such as INET_DIAG. By eliminating the custom merge function, these config options will now use the default module option merge functions which make sure that all options with the highest priority have the same value. A user that wishes to override an option defined in common-config.nix can currently use mkForce or mkOverride to do so, e.g.: BINFMT_MISC = mkForce (option no); That said, this is not going to be necessary in the future, because the plan is for kernel config options defined in nixpkgs to use a lower priority by default, like it currently happens for other module options. --- nixos/modules/system/boot/kernel_config.nix | 22 +-------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/nixos/modules/system/boot/kernel_config.nix b/nixos/modules/system/boot/kernel_config.nix index 783685c9dfe..5d9534024b0 100644 --- a/nixos/modules/system/boot/kernel_config.nix +++ b/nixos/modules/system/boot/kernel_config.nix @@ -2,24 +2,6 @@ with lib; let - findWinner = candidates: winner: - any (x: x == winner) candidates; - - # winners is an ordered list where first item wins over 2nd etc - mergeAnswer = winners: locs: defs: - let - values = map (x: x.value) defs; - inter = intersectLists values winners; - winner = head winners; - in - if defs == [] then abort "This case should never happen." - else if winner == [] then abort "Give a valid list of winner" - else if inter == [] then mergeOneOption locs defs - else if findWinner values winner then - winner - else - mergeAnswer (tail winners) locs defs; - mergeFalseByDefault = locs: defs: if defs == [] then abort "This case should never happen." else if any (x: x == false) (getValues defs) then false @@ -28,9 +10,7 @@ let kernelItem = types.submodule { options = { tristate = mkOption { - type = types.enum [ "y" "m" "n" null ] // { - merge = mergeAnswer [ "y" "m" "n" ]; - }; + type = types.enum [ "y" "m" "n" null ]; default = null; internal = true; visible = true; From d81067f3f3c1c82231eeca2b0e69b89d544ea028 Mon Sep 17 00:00:00 2001 From: "Ricardo M. Correia" Date: Wed, 10 Jun 2020 16:29:14 +0200 Subject: [PATCH 2/2] linux: fix fallout from conflicting kernel configs The parent commit forbids conflicting kernel config options. Fix the hardened kernels by allowing options in common-config.nix to be overridden by conflicting ones in hardened/config.nix. I'm explicitly avoiding using a higher priority (e.g. using mkForce) in hardened/config.nix so that the user can easily override the options in that file. --- pkgs/os-specific/linux/kernel/common-config.nix | 13 +++++++------ pkgs/os-specific/linux/kernel/hardened/config.nix | 10 +++++++++- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/pkgs/os-specific/linux/kernel/common-config.nix b/pkgs/os-specific/linux/kernel/common-config.nix index 24c992dc907..62fe54bbe3f 100644 --- a/pkgs/os-specific/linux/kernel/common-config.nix +++ b/pkgs/os-specific/linux/kernel/common-config.nix @@ -193,16 +193,17 @@ let NET_DROP_MONITOR = yes; # needed for ss - INET_DIAG = module; - INET_TCP_DIAG = module; - INET_UDP_DIAG = module; - INET_RAW_DIAG = whenAtLeast "4.14" module; - INET_DIAG_DESTROY = whenAtLeast "4.9" yes; + # Use a lower priority to allow these options to be overridden in hardened/config.nix + INET_DIAG = mkDefault module; + INET_TCP_DIAG = mkDefault module; + INET_UDP_DIAG = mkDefault module; + INET_RAW_DIAG = whenAtLeast "4.14" (mkDefault module); + INET_DIAG_DESTROY = whenAtLeast "4.9" (mkDefault yes); # enable multipath-tcp MPTCP = whenAtLeast "5.6" yes; MPTCP_IPV6 = whenAtLeast "5.6" yes; - INET_MPTCP_DIAG = whenAtLeast "5.9" module; + INET_MPTCP_DIAG = whenAtLeast "5.9" (mkDefault module); }; wireless = { diff --git a/pkgs/os-specific/linux/kernel/hardened/config.nix b/pkgs/os-specific/linux/kernel/hardened/config.nix index bd0518650d6..acffa383f07 100644 --- a/pkgs/os-specific/linux/kernel/hardened/config.nix +++ b/pkgs/os-specific/linux/kernel/hardened/config.nix @@ -65,7 +65,7 @@ assert (versionAtLeast version "4.9"); PANIC_TIMEOUT = freeform "-1"; GCC_PLUGINS = yes; # Enable gcc plugin options - # Gather additional entropy at boot time for systems that may = no;ot have appropriate entropy sources. + # Gather additional entropy at boot time for systems that may not have appropriate entropy sources. GCC_PLUGIN_LATENT_ENTROPY = yes; GCC_PLUGIN_STRUCTLEAK = whenAtLeast "4.11" yes; # A port of the PaX structleak plugin @@ -79,6 +79,14 @@ assert (versionAtLeast version "4.9"); PROC_KCORE = no; # Exposes kernel text image layout INET_DIAG = no; # Has been used for heap based attacks in the past + # INET_DIAG=n causes the following options to not exist anymore, but since they are defined in common-config.nix, + # make them optional + INET_DIAG_DESTROY = option no; + INET_RAW_DIAG = option no; + INET_TCP_DIAG = option no; + INET_UDP_DIAG = option no; + INET_MPTCP_DIAG = option no; + # Use -fstack-protector-strong (gcc 4.9+) for best stack canary coverage. CC_STACKPROTECTOR_REGULAR = whenOlder "4.18" no; CC_STACKPROTECTOR_STRONG = whenOlder "4.18" yes;