From b9a4e6953d0234cde64ac0cc55136adb3e92794b Mon Sep 17 00:00:00 2001 From: Matthieu Coudron Date: Wed, 1 Apr 2020 03:20:33 +0200 Subject: [PATCH 1/3] kernel: fix config generation Addresses https://github.com/NixOS/nixpkgs/issues/71803: Kernel options are not merged as described, especially the "optional" aspects. The error silences legitimate warnings. --- lib/kernel.nix | 8 +- nixos/modules/system/boot/kernel_config.nix | 5 +- pkgs/os-specific/linux/kernel/generic.nix | 3 - pkgs/test/kernel.nix | 88 +++++++++++++-------- 4 files changed, 64 insertions(+), 40 deletions(-) diff --git a/lib/kernel.nix b/lib/kernel.nix index 2ce19f8cb68c..a0f986ee1160 100644 --- a/lib/kernel.nix +++ b/lib/kernel.nix @@ -8,10 +8,10 @@ with lib; option = x: x // { optional = true; }; - yes = { tristate = "y"; }; - no = { tristate = "n"; }; - module = { tristate = "m"; }; - freeform = x: { freeform = x; }; + yes = { tristate = "y"; optional = false; }; + no = { tristate = "n"; optional = false; }; + module = { tristate = "m"; optional = false; }; + freeform = x: { freeform = x; optional = false; }; /* Common patterns/legacy used in common-config/hardened-config.nix diff --git a/nixos/modules/system/boot/kernel_config.nix b/nixos/modules/system/boot/kernel_config.nix index a316782dfc57..85bd420e3044 100644 --- a/nixos/modules/system/boot/kernel_config.nix +++ b/nixos/modules/system/boot/kernel_config.nix @@ -22,7 +22,7 @@ let mergeFalseByDefault = locs: defs: if defs == [] then abort "This case should never happen." - else if any (x: x == false) defs then false + else if any (x: x == false) (getValues defs) then false else true; kernelItem = types.submodule { @@ -55,6 +55,7 @@ let default = false; description = '' Wether option should generate a failure when unused. + Upon merging values, mandatory wins over optional. ''; }; }; @@ -121,7 +122,7 @@ in type = types.attrsOf kernelItem; example = literalExample '' with lib.kernel; { "9P_NET" = yes; - USB = optional yes; + USB = option yes; MMC_BLOCK_MINORS = freeform "32"; }''; description = '' diff --git a/pkgs/os-specific/linux/kernel/generic.nix b/pkgs/os-specific/linux/kernel/generic.nix index e6e1bd842363..a9d0cf451688 100644 --- a/pkgs/os-specific/linux/kernel/generic.nix +++ b/pkgs/os-specific/linux/kernel/generic.nix @@ -158,11 +158,8 @@ let ; }).config; - # structuredConfig = moduleStructuredConfig.settings; }; - - }; # end of configfile derivation kernel = (callPackage ./manual-config.nix {}) { diff --git a/pkgs/test/kernel.nix b/pkgs/test/kernel.nix index 86f1b8d8e9ac..a4da10030332 100644 --- a/pkgs/test/kernel.nix +++ b/pkgs/test/kernel.nix @@ -1,53 +1,79 @@ +# to run these tests: +# nix-instantiate --eval --strict . -A tests.kernel-config +# +# make sure to use NON EXISTING kernel settings else they may conflict with +# common-config.nix { lib, pkgs }: -with lib.kernel; -with lib.asserts; -with lib.modules; +with lib; +with kernel; -# To test nixos/modules/system/boot/kernel_config.nix; let - # copied from release-lib.nix - assertTrue = bool: - if bool - then pkgs.runCommand "evaluated-to-true" {} "touch $out" - else pkgs.runCommand "evaluated-to-false" {} "false"; - lts_kernel = pkgs.linuxPackages.kernel; - kernelTestConfig = structuredConfig: (lts_kernel.override { - structuredExtraConfig = structuredConfig; - }).configfile.structuredConfig; + # to see the result once the module transformed the lose structured config + getConfig = structuredConfig: + (lts_kernel.override { + structuredExtraConfig = structuredConfig; + }).configfile.structuredConfig; mandatoryVsOptionalConfig = mkMerge [ - { USB_DEBUG = option yes;} - { USB_DEBUG = yes;} + { NIXOS_FAKE_USB_DEBUG = yes;} + { NIXOS_FAKE_USB_DEBUG = option yes; } ]; freeformConfig = mkMerge [ - { MMC_BLOCK_MINORS = freeform "32"; } # same as default, won't trigger any error - { MMC_BLOCK_MINORS = freeform "64"; } # will trigger an error but the message is not great: + { NIXOS_FAKE_MMC_BLOCK_MINORS = freeform "32"; } # same as default, won't trigger any error + { NIXOS_FAKE_MMC_BLOCK_MINORS = freeform "64"; } # will trigger an error but the message is not great: ]; yesWinsOverNoConfig = mkMerge [ - # default for "8139TOO_PIO" is no - { "8139TOO_PIO" = yes; } # yes wins over no by default - { "8139TOO_PIO" = no; } + # default for "NIXOS_TEST_BOOLEAN" is no + { "NIXOS_TEST_BOOLEAN" = yes; } # yes wins over no by default + { "NIXOS_TEST_BOOLEAN" = no; } ]; + + optionalNoWins = mkMerge [ + { NIXOS_FAKE_USB_DEBUG = option yes;} + { NIXOS_FAKE_USB_DEBUG = yes;} + ]; + + allOptionalRemainOptional = mkMerge [ + { NIXOS_FAKE_USB_DEBUG = option yes;} + { NIXOS_FAKE_USB_DEBUG = option yes;} + ]; + in -{ +runTests { + testEasy = { + expr = (getConfig { NIXOS_FAKE_USB_DEBUG = yes;}).NIXOS_FAKE_USB_DEBUG; + expected = { tristate = "y"; optional = false; freeform = null; }; + }; + # mandatory flag should win over optional - mandatoryCheck = (kernelTestConfig mandatoryVsOptionalConfig); + testMandatoryCheck = { + expr = (getConfig mandatoryVsOptionalConfig).NIXOS_FAKE_USB_DEBUG.optional; + expected = false; + }; + + testYesWinsOverNo = { + expr = (getConfig yesWinsOverNoConfig)."NIXOS_TEST_BOOLEAN".tristate; + expected = "y"; + }; + + testAllOptionalRemainOptional = { + expr = (getConfig allOptionalRemainOptional)."NIXOS_FAKE_USB_DEBUG".optional; + expected = true; + }; # check that freeform options are unique # Should trigger - # > The option `settings.MMC_BLOCK_MINORS.freeform' has conflicting definitions, in `' and `' - freeformCheck = let - res = builtins.tryEval ( (kernelTestConfig freeformConfig).MMC_BLOCK_MINORS.freeform); - in - assertTrue (res.success == false); + # > The option `settings.NIXOS_FAKE_MMC_BLOCK_MINORS.freeform' has conflicting definitions, in `' and `' + testTreeform = let + res = builtins.tryEval ( (getConfig freeformConfig).NIXOS_FAKE_MMC_BLOCK_MINORS.freeform); + in { + expr = res.success; + expected = false; + }; - yesVsNoCheck = let - res = kernelTestConfig yesWinsOverNoConfig; - in - assertTrue (res."8139TOO_PIO".tristate == "y"); } From 121b17e1ac3fa41d82c827a9a9cfa505a0730871 Mon Sep 17 00:00:00 2001 From: Matthieu Coudron Date: Wed, 1 Apr 2020 22:25:21 +0200 Subject: [PATCH 2/3] kernel: fix errors in configuration With the fix in kernel configuration merging, some kernel configuration items marked as mandatory now correctly trigger an error when unused (while they previously were unused). --- pkgs/os-specific/linux/kernel/common-config.nix | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkgs/os-specific/linux/kernel/common-config.nix b/pkgs/os-specific/linux/kernel/common-config.nix index 2c8b8de65b31..f1762054661e 100644 --- a/pkgs/os-specific/linux/kernel/common-config.nix +++ b/pkgs/os-specific/linux/kernel/common-config.nix @@ -42,7 +42,7 @@ let TIMER_STATS = whenOlder "4.11" yes; DEBUG_NX_TEST = whenOlder "4.11" no; DEBUG_STACK_USAGE = no; - DEBUG_STACKOVERFLOW = mkIf (!features.grsecurity) no; + DEBUG_STACKOVERFLOW = mkIf (!features.grsecurity) (option no); RCU_TORTURE_TEST = no; SCHEDSTATS = no; DETECT_HUNG_TASK = yes; @@ -179,7 +179,7 @@ let # needed for ss INET_DIAG = yes; - INET_TCP_DIAG = module; + INET_TCP_DIAG = option module; INET_UDP_DIAG = module; INET_RAW_DIAG = whenAtLeast "4.14" module; INET_DIAG_DESTROY = whenAtLeast "4.9" yes; @@ -337,7 +337,7 @@ let CIFS_STATS = whenOlder "4.19" yes; CIFS_WEAK_PW_HASH = yes; CIFS_UPCALL = yes; - CIFS_ACL = yes; + CIFS_ACL = option yes; CIFS_DFS_UPCALL = yes; CIFS_SMB2 = whenOlder "4.13" yes; @@ -368,7 +368,7 @@ let DEBUG_SET_MODULE_RONX = { optional = true; tristate = whenOlder "4.11" "y"; }; RANDOMIZE_BASE = option yes; STRICT_DEVMEM = option yes; # Filter access to /dev/mem - SECURITY_SELINUX_BOOTPARAM_VALUE = freeform "0"; # Disable SELinux by default + SECURITY_SELINUX_BOOTPARAM_VALUE = option (freeform "0"); # Disable SELinux by default # Prevent processes from ptracing non-children processes SECURITY_YAMA = option yes; DEVKMEM = mkIf (!features.grsecurity) no; # Disable /dev/kmem @@ -676,7 +676,7 @@ let KEXEC_JUMP = option yes; # Windows Logical Disk Manager (Dynamic Disk) support - LDM_PARTITION = yes; + LDM_PARTITION = option yes; LOGIRUMBLEPAD2_FF = yes; # Logitech Rumblepad 2 force feedback LOGO = no; # not needed MEDIA_ATTACH = yes; From bc6b37e9678f3a095211764b8d4f8c12d8ea7d4e Mon Sep 17 00:00:00 2001 From: Matthieu Coudron Date: Sat, 11 Apr 2020 14:04:25 +0200 Subject: [PATCH 3/3] fixup! kernel: fix errors in configuration --- pkgs/os-specific/linux/kernel/common-config.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/os-specific/linux/kernel/common-config.nix b/pkgs/os-specific/linux/kernel/common-config.nix index f1762054661e..53f2988e9cd0 100644 --- a/pkgs/os-specific/linux/kernel/common-config.nix +++ b/pkgs/os-specific/linux/kernel/common-config.nix @@ -179,7 +179,6 @@ let # needed for ss INET_DIAG = yes; - INET_TCP_DIAG = option module; INET_UDP_DIAG = module; INET_RAW_DIAG = whenAtLeast "4.14" module; INET_DIAG_DESTROY = whenAtLeast "4.9" yes;