diff options
author | Silvan Mosberger <infinisil@icloud.com> | 2019-01-28 10:38:00 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-28 10:38:00 +0100 |
commit | 51d2eed83b4787e167e59871380433c02c033c42 (patch) | |
tree | 2905fac4fc39c732be9369f075db977cff493e12 | |
parent | 8c2aaf37fde021717d7ca7b2ec651a628f9ae38b (diff) | |
parent | 045e1332d97d0db7c09265d2c2041fbca906286c (diff) | |
download | nixpkgs-51d2eed83b4787e167e59871380433c02c033c42.tar nixpkgs-51d2eed83b4787e167e59871380433c02c033c42.tar.gz nixpkgs-51d2eed83b4787e167e59871380433c02c033c42.tar.bz2 nixpkgs-51d2eed83b4787e167e59871380433c02c033c42.tar.lz nixpkgs-51d2eed83b4787e167e59871380433c02c033c42.tar.xz nixpkgs-51d2eed83b4787e167e59871380433c02c033c42.tar.zst nixpkgs-51d2eed83b4787e167e59871380433c02c033c42.zip |
Merge pull request #42838 from teto/kernel_autoconf
[RFC] add ability to merge structured configs
-rw-r--r-- | lib/kernel.nix | 62 | ||||
-rw-r--r-- | nixos/modules/system/boot/kernel_config.nix | 137 | ||||
-rw-r--r-- | pkgs/os-specific/linux/kernel/common-config.nix | 64 | ||||
-rw-r--r-- | pkgs/os-specific/linux/kernel/generic.nix | 47 | ||||
-rw-r--r-- | pkgs/os-specific/linux/kernel/hardened-config.nix | 212 | ||||
-rw-r--r-- | pkgs/test/default.nix | 2 | ||||
-rw-r--r-- | pkgs/test/kernel.nix | 53 | ||||
-rw-r--r-- | pkgs/top-level/all-packages.nix | 2 |
8 files changed, 363 insertions, 216 deletions
diff --git a/lib/kernel.nix b/lib/kernel.nix index 45b33aea7b8..5923011774b 100644 --- a/lib/kernel.nix +++ b/lib/kernel.nix @@ -1,57 +1,21 @@ -{ lib -# we pass the kernel version here to keep a nice syntax `whenOlder "4.13"` -# kernelVersion, e.g., config.boot.kernelPackages.version -, version -, mkValuePreprocess ? null -}: +{ lib, version }: with lib; rec { - # Common patterns - when = cond: opt: if cond then opt else null; - whenAtLeast = ver: when (versionAtLeast version ver); - whenOlder = ver: when (versionOlder version ver); - whenBetween = verLow: verHigh: when (versionAtLeast version verLow && versionOlder version verHigh); + # Common patterns/legacy + whenAtLeast = ver: mkIf (versionAtLeast version ver); + whenOlder = ver: mkIf (versionOlder version ver); + # range is (inclusive, exclusive) + whenBetween = verLow: verHigh: mkIf (versionAtLeast version verLow && versionOlder version verHigh); - # Keeping these around in case we decide to change this horrible implementation :) - option = x: if x == null then null else "?${x}"; - yes = "y"; - no = "n"; - module = "m"; - mkValue = val: - let - isNumber = c: elem c ["0" "1" "2" "3" "4" "5" "6" "7" "8" "9"]; - in - if val == "" then "\"\"" - else if val == yes || val == module || val == no then val - else if all isNumber (stringToCharacters val) then val - else if substring 0 2 val == "0x" then val - else val; # FIXME: fix quoting one day + # Keeping these around in case we decide to change this horrible implementation :) + option = x: + x // { optional = true; }; + yes = { tristate = "y"; }; + no = { tristate = "n"; }; + module = { tristate = "m"; }; + freeform = x: { freeform = x; }; - # generate nix intermediate kernel config file of the form - # - # VIRTIO_MMIO m - # VIRTIO_BLK y - # VIRTIO_CONSOLE n - # NET_9P_VIRTIO? y - # - # Use mkValuePreprocess to preprocess option values, aka mark 'modules' as - # 'yes' or vice-versa - # Borrowed from copumpkin https://github.com/NixOS/nixpkgs/pull/12158 - # returns a string, expr should be an attribute set - generateNixKConf = exprs: mkValuePreprocess: - let - mkConfigLine = key: rawval: - let - val = if builtins.isFunction mkValuePreprocess then mkValuePreprocess rawval else rawval; - in - if val == null - then "" - else if hasPrefix "?" val - then "${key}? ${mkValue (removePrefix "?" val)}\n" - else "${key} ${mkValue val}\n"; - mkConf = cfg: concatStrings (mapAttrsToList mkConfigLine cfg); - in mkConf exprs; } diff --git a/nixos/modules/system/boot/kernel_config.nix b/nixos/modules/system/boot/kernel_config.nix new file mode 100644 index 00000000000..fbbd0982b2c --- /dev/null +++ b/nixos/modules/system/boot/kernel_config.nix @@ -0,0 +1,137 @@ +{ lib, config, ... }: + +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; + freeformAnswer = intersectLists values winners; + 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) defs then false + else true; + + kernelItem = types.submodule { + options = { + tristate = mkOption { + type = types.enum [ "y" "m" "n" null ] // { + merge = mergeAnswer [ "y" "m" "n" ]; + }; + default = null; + internal = true; + visible = true; + description = '' + Use this field for tristate kernel options expecting a "y" or "m" or "n". + ''; + }; + + freeform = mkOption { + type = types.nullOr types.str // { + merge = mergeEqualOption; + }; + default = null; + example = ''MMC_BLOCK_MINORS.freeform = "32";''; + description = '' + Freeform description of a kernel configuration item value. + ''; + }; + + optional = mkOption { + type = types.bool // { merge = mergeFalseByDefault; }; + default = false; + description = '' + Wether option should generate a failure when unused. + ''; + }; + }; + }; + + mkValue = with lib; val: + let + isNumber = c: elem c ["0" "1" "2" "3" "4" "5" "6" "7" "8" "9"]; + + in + if (val == "") then "\"\"" + else if val == "y" || val == "m" || val == "n" then val + else if all isNumber (stringToCharacters val) then val + else if substring 0 2 val == "0x" then val + else val; # FIXME: fix quoting one day + + + # generate nix intermediate kernel config file of the form + # + # VIRTIO_MMIO m + # VIRTIO_BLK y + # VIRTIO_CONSOLE n + # NET_9P_VIRTIO? y + # + # Borrowed from copumpkin https://github.com/NixOS/nixpkgs/pull/12158 + # returns a string, expr should be an attribute set + # Use mkValuePreprocess to preprocess option values, aka mark 'modules' as 'yes' or vice-versa + # use the identity if you don't want to override the configured values + generateNixKConf = exprs: + let + mkConfigLine = key: item: + let + val = if item.freeform != null then item.freeform else item.tristate; + in + if val == null + then "" + else if (item.optional) + then "${key}? ${mkValue val}\n" + else "${key} ${mkValue val}\n"; + + mkConf = cfg: concatStrings (mapAttrsToList mkConfigLine cfg); + in mkConf exprs; + +in +{ + + options = { + + intermediateNixConfig = mkOption { + readOnly = true; + type = types.lines; + example = '' + USB? y + DEBUG n + ''; + description = '' + The result of converting the structured kernel configuration in settings + to an intermediate string that can be parsed by generate-config.pl to + answer the kernel `make defconfig`. + ''; + }; + + settings = mkOption { + type = types.attrsOf kernelItem; + example = literalExample '' with lib.kernel; { + "9P_NET" = yes; + USB = optional yes; + MMC_BLOCK_MINORS = freeform "32"; + }''; + description = '' + Structured kernel configuration. + ''; + }; + }; + + config = { + intermediateNixConfig = generateNixKConf config.settings; + }; +} diff --git a/pkgs/os-specific/linux/kernel/common-config.nix b/pkgs/os-specific/linux/kernel/common-config.nix index ddd1e9828d5..1a56e68fa4b 100644 --- a/pkgs/os-specific/linux/kernel/common-config.nix +++ b/pkgs/os-specific/linux/kernel/common-config.nix @@ -12,23 +12,12 @@ # Configuration { stdenv, version -# to let user override values, aka converting modules to included and vice-versa -, mkValueOverride ? null - -# new extraConfig as a flattened set -, structuredExtraConfig ? {} - -# legacy extraConfig as string -, extraConfig ? "" - , features ? { grsecurity = false; xen_dom0 = false; } }: -assert (mkValueOverride == null) || (builtins.isFunction mkValueOverride); - with stdenv.lib; -with import ../../../../lib/kernel.nix { inherit (stdenv) lib; inherit version; }; + with import ../../../../lib/kernel.nix { inherit (stdenv) lib; inherit version; }; let @@ -46,7 +35,7 @@ let DEBUG_NX_TEST = whenOlder "4.11" no; CPU_NOTIFIER_ERROR_INJECT = whenOlder "4.4" (option no); DEBUG_STACK_USAGE = no; - DEBUG_STACKOVERFLOW = when (!features.grsecurity) no; + DEBUG_STACKOVERFLOW = mkIf (!features.grsecurity) no; RCU_TORTURE_TEST = no; SCHEDSTATS = no; DETECT_HUNG_TASK = yes; @@ -114,7 +103,7 @@ let IP_DCCP_CCID3 = no; # experimental CLS_U32_PERF = yes; CLS_U32_MARK = yes; - BPF_JIT = when (stdenv.hostPlatform.system == "x86_64-linux") yes; + BPF_JIT = mkIf (stdenv.hostPlatform.system == "x86_64-linux") yes; WAN = yes; # Required by systemd per-cgroup firewalling CGROUP_BPF = option yes; @@ -184,7 +173,7 @@ let FB_VESA = yes; FRAMEBUFFER_CONSOLE = yes; FRAMEBUFFER_CONSOLE_ROTATION = yes; - FB_GEODE = when (stdenv.hostPlatform.system == "i686-linux") yes; + FB_GEODE = mkIf (stdenv.hostPlatform.system == "i686-linux") yes; }; video = { @@ -239,7 +228,7 @@ let }; usb = { - USB_DEBUG = option (whenOlder "4.18" no); + USB_DEBUG = { optional = true; tristate = whenOlder "4.18" "n";}; USB_EHCI_ROOT_HUB_TT = yes; # Root Hub Transaction Translators USB_EHCI_TT_NEWSCHED = yes; # Improved transaction translator scheduling }; @@ -250,7 +239,7 @@ let FANOTIFY = yes; TMPFS = yes; TMPFS_POSIX_ACL = yes; - FS_ENCRYPTION = option (whenAtLeast "4.9" module); + FS_ENCRYPTION = { optional = true; tristate = whenAtLeast "4.9" "m"; }; EXT2_FS_XATTR = yes; EXT2_FS_POSIX_ACL = yes; @@ -262,7 +251,7 @@ let EXT4_FS_POSIX_ACL = yes; EXT4_FS_SECURITY = yes; - EXT4_ENCRYPTION = option ((if (versionOlder version "4.8") then module else yes)); + EXT4_ENCRYPTION = { optional = true; tristate = if (versionOlder version "4.8") then "m" else "y"; }; REISERFS_FS_XATTR = option yes; REISERFS_FS_POSIX_ACL = option yes; @@ -324,7 +313,7 @@ let # Native Language Support modules, needed by some filesystems NLS = yes; - NLS_DEFAULT = "utf8"; + NLS_DEFAULT = freeform "utf8"; NLS_UTF8 = module; NLS_CODEPAGE_437 = module; # VFAT default for the codepage= mount option NLS_ISO8859_1 = module; # VFAT default for the iocharset= mount option @@ -334,13 +323,13 @@ let security = { # Detect writes to read-only module pages - DEBUG_SET_MODULE_RONX = option (whenOlder "4.11" yes); + 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 = "0"; # Disable SELinux by default + SECURITY_SELINUX_BOOTPARAM_VALUE = freeform "0"; # Disable SELinux by default # Prevent processes from ptracing non-children processes SECURITY_YAMA = option yes; - DEVKMEM = when (!features.grsecurity) no; # Disable /dev/kmem + DEVKMEM = mkIf (!features.grsecurity) no; # Disable /dev/kmem USER_NS = yes; # Support for user namespaces @@ -350,7 +339,7 @@ let } // optionalAttrs (!stdenv.hostPlatform.isAarch32) { # Detect buffer overflows on the stack - CC_STACKPROTECTOR_REGULAR = option (whenOlder "4.18" yes); + CC_STACKPROTECTOR_REGULAR = {optional = true; tristate = whenOlder "4.18" "y";}; }; microcode = { @@ -407,8 +396,8 @@ let FTRACE_SYSCALLS = yes; SCHED_TRACER = yes; STACK_TRACER = yes; - UPROBE_EVENT = option (whenOlder "4.11" yes); - UPROBE_EVENTS = option (whenAtLeast "4.11" yes); + UPROBE_EVENT = { optional = true; tristate = whenOlder "4.11" "y";}; + UPROBE_EVENTS = { optional = true; tristate = whenAtLeast "4.11" "y";}; BPF_SYSCALL = whenAtLeast "4.4" yes; BPF_EVENTS = whenAtLeast "4.4" yes; FUNCTION_PROFILER = yes; @@ -418,23 +407,23 @@ let virtualisation = { PARAVIRT = option yes; - HYPERVISOR_GUEST = when (!features.grsecurity) yes; + HYPERVISOR_GUEST = mkIf (!features.grsecurity) yes; PARAVIRT_SPINLOCKS = option yes; KVM_APIC_ARCHITECTURE = whenOlder "4.8" yes; KVM_ASYNC_PF = yes; - KVM_COMPAT = option (whenBetween "4.0" "4.12" yes); - KVM_DEVICE_ASSIGNMENT = option (whenBetween "3.10" "4.12" yes); + KVM_COMPAT = { optional = true; tristate = whenBetween "4.0" "4.12" "y"; }; + KVM_DEVICE_ASSIGNMENT = { optional = true; tristate = whenBetween "3.10" "4.12" "y"; }; KVM_GENERIC_DIRTYLOG_READ_PROTECT = whenAtLeast "4.0" yes; - KVM_GUEST = when (!features.grsecurity) yes; + KVM_GUEST = mkIf (!features.grsecurity) yes; KVM_MMIO = yes; KVM_VFIO = yes; KSM = yes; VIRT_DRIVERS = yes; # We nneed 64 GB (PAE) support for Xen guest support - HIGHMEM64G = option (when (!stdenv.is64bit) yes); + HIGHMEM64G = { optional = true; tristate = mkIf (!stdenv.is64bit) "y";}; - VFIO_PCI_VGA = when stdenv.is64bit yes; + VFIO_PCI_VGA = mkIf stdenv.is64bit yes; } // optionalAttrs (stdenv.isx86_64 || stdenv.isi686) ({ XEN = option yes; @@ -542,8 +531,8 @@ let CRYPTO_TEST = option no; EFI_TEST = option no; GLOB_SELFTEST = option no; - DRM_DEBUG_MM_SELFTEST = option (whenOlder "4.18" no); - LNET_SELFTEST = option (whenOlder "4.18" no); + DRM_DEBUG_MM_SELFTEST = { optional = true; tristate = whenOlder "4.18" "n";}; + LNET_SELFTEST = { optional = true; tristate = whenOlder "4.18" "n";}; LOCK_TORTURE_TEST = option no; MTD_TESTS = option no; NOTIFIER_ERROR_INJECTION = option no; @@ -598,7 +587,7 @@ let AIC79XX_DEBUG_ENABLE = no; AIC7XXX_DEBUG_ENABLE = no; AIC94XX_DEBUG = no; - B43_PCMCIA = option (whenOlder "4.4" yes); + B43_PCMCIA = { optional=true; tristate = whenOlder "4.4" "y";}; BLK_DEV_INTEGRITY = yes; @@ -651,7 +640,7 @@ let # GPIO on Intel Bay Trail, for some Chromebook internal eMMC disks PINCTRL_BAYTRAIL = yes; # 8 is default. Modern gpt tables on eMMC may go far beyond 8. - MMC_BLOCK_MINORS = "32"; + MMC_BLOCK_MINORS = freeform "32"; REGULATOR = yes; # Voltage and Current Regulator Support RC_DEVICES = option yes; # Enable IR devices @@ -698,7 +687,8 @@ let # Bump the maximum number of CPUs to support systems like EC2 x1.* # instances and Xeon Phi. - NR_CPUS = "384"; + NR_CPUS = freeform "384"; }; }; -in (generateNixKConf ((flattenKConf options) // structuredExtraConfig) mkValueOverride) + extraConfig +in + flattenKConf options diff --git a/pkgs/os-specific/linux/kernel/generic.nix b/pkgs/os-specific/linux/kernel/generic.nix index 30878d1b96c..a41f1eb989b 100644 --- a/pkgs/os-specific/linux/kernel/generic.nix +++ b/pkgs/os-specific/linux/kernel/generic.nix @@ -47,7 +47,6 @@ , preferBuiltin ? stdenv.hostPlatform.platform.kernelPreferBuiltin or false , kernelArch ? stdenv.hostPlatform.platform.kernelArch -, mkValueOverride ? null , ... }: @@ -68,20 +67,26 @@ let ia32Emulation = true; } // features) kernelPatches; - intermediateNixConfig = import ./common-config.nix { - inherit stdenv version structuredExtraConfig mkValueOverride; - - # append extraConfig for backwards compatibility but also means the user can't override the kernelExtraConfig part - extraConfig = extraConfig + lib.optionalString (stdenv.hostPlatform.platform ? kernelExtraConfig) stdenv.hostPlatform.platform.kernelExtraConfig; + commonStructuredConfig = import ./common-config.nix { + inherit stdenv version ; features = kernelFeatures; # Ensure we know of all extra patches, etc. }; - kernelConfigFun = baseConfig: + # extra config in legacy string format + extraConfig = extraConfig + lib.optionalString (stdenv.hostPlatform.platform ? kernelExtraConfig) stdenv.hostPlatform.platform.kernelExtraConfig; + + intermediateNixConfig = configfile.moduleStructuredConfig.intermediateNixConfig; + + structuredConfigFromPatches = + map ({extraStructuredConfig ? {}, ...}: {settings=extraStructuredConfig;}) kernelPatches; + + # appends kernel patches extraConfig + kernelConfigFun = baseConfigStr: let configFromPatches = map ({extraConfig ? "", ...}: extraConfig) kernelPatches; - in lib.concatStringsSep "\n" ([baseConfig] ++ configFromPatches); + in lib.concatStringsSep "\n" ([baseConfigStr] ++ configFromPatches); configfile = stdenv.mkDerivation { inherit ignoreConfigErrors autoModules preferBuiltin kernelArch; @@ -131,7 +136,30 @@ let installPhase = "mv $buildRoot/.config $out"; enableParallelBuilding = true; - }; + + passthru = rec { + + module = import ../../../../nixos/modules/system/boot/kernel_config.nix; + # used also in apache + # { modules = [ { options = res.options; config = svc.config or svc; } ]; + # check = false; + # The result is a set of two attributes + moduleStructuredConfig = (lib.evalModules { + modules = [ + module + { settings = commonStructuredConfig; } + { settings = structuredExtraConfig; } + ] + ++ structuredConfigFromPatches + ; + }).config; + + # + structuredConfig = moduleStructuredConfig.settings; + }; + + + }; # end of configfile derivation kernel = (callPackage ./manual-config.nix {}) { inherit version modDirVersion src kernelPatches stdenv extraMeta configfile; @@ -141,6 +169,7 @@ let passthru = { features = kernelFeatures; + inherit commonStructuredConfig; passthru = kernel.passthru // (removeAttrs passthru [ "passthru" ]); }; diff --git a/pkgs/os-specific/linux/kernel/hardened-config.nix b/pkgs/os-specific/linux/kernel/hardened-config.nix index ed540a9e751..f1f18c64130 100644 --- a/pkgs/os-specific/linux/kernel/hardened-config.nix +++ b/pkgs/os-specific/linux/kernel/hardened-config.nix @@ -11,138 +11,110 @@ { stdenv, version }: with stdenv.lib; +with import ../../../../lib/kernel.nix { inherit (stdenv) lib; inherit version; }; assert (versionAtLeast version "4.9"); -'' -# Report BUG() conditions and kill the offending process. -BUG y - -${optionalString (versionAtLeast version "4.10") '' - BUG_ON_DATA_CORRUPTION y -''} - -${optionalString (stdenv.hostPlatform.platform.kernelArch == "x86_64") '' - DEFAULT_MMAP_MIN_ADDR 65536 # Prevent allocation of first 64K of memory +optionalAttrs (stdenv.hostPlatform.platform.kernelArch == "x86_64") { + DEFAULT_MMAP_MIN_ADDR = freeform "65536"; # Prevent allocation of first 64K of memory # Reduce attack surface by disabling various emulations - IA32_EMULATION n - X86_X32 n + IA32_EMULATION = no; + X86_X32 = no; # Note: this config depends on EXPERT y and so will not take effect, hence # it is left "optional" for now. - MODIFY_LDT_SYSCALL? n - - VMAP_STACK y # Catch kernel stack overflows + MODIFY_LDT_SYSCALL = option no; + VMAP_STACK = yes; # Catch kernel stack overflows # Randomize position of kernel and memory. - RANDOMIZE_BASE y - RANDOMIZE_MEMORY y + RANDOMIZE_BASE = yes; + RANDOMIZE_MEMORY = yes; # Disable legacy virtual syscalls by default (modern glibc use vDSO instead). # # Note that the vanilla default is to *emulate* the legacy vsyscall mechanism, # which is supposed to be safer than the native variant (wrt. ret2libc), so # disabling it mainly helps reduce surface. - LEGACY_VSYSCALL_NONE y -''} - -# Safer page access permissions (wrt. code injection). Default on >=4.11. -${optionalString (versionOlder version "4.11") '' - DEBUG_RODATA y - DEBUG_SET_MODULE_RONX y -''} - -# Mark LSM hooks read-only after init. SECURITY_WRITABLE_HOOKS n -# conflicts with SECURITY_SELINUX_DISABLE y; disabling the latter -# implicitly marks LSM hooks read-only after init. -# -# SELinux can only be disabled at boot via selinux=0 -# -# We set SECURITY_WRITABLE_HOOKS n primarily for documentation purposes; the -# config builder fails to detect that it has indeed been unset. -${optionalString (versionAtLeast version "4.12") '' - SECURITY_SELINUX_DISABLE n - SECURITY_WRITABLE_HOOKS? n -''} - -DEBUG_WX y # boot-time warning on RWX mappings -${optionalString (versionAtLeast version "4.11") '' - STRICT_KERNEL_RWX y -''} - -# Stricter /dev/mem -STRICT_DEVMEM? y -IO_STRICT_DEVMEM? y - -# Perform additional validation of commonly targeted structures. -DEBUG_CREDENTIALS y -DEBUG_NOTIFIERS y -DEBUG_LIST y -DEBUG_PI_LIST y # doesn't BUG() -DEBUG_SG y -SCHED_STACK_END_CHECK y - -${optionalString (versionAtLeast version "4.13") '' - REFCOUNT_FULL y -''} - -# Perform usercopy bounds checking. -HARDENED_USERCOPY y -${optionalString (versionAtLeast version "4.16") '' - HARDENED_USERCOPY_FALLBACK n # for full whitelist enforcement -''} - -# Randomize allocator freelists. -SLAB_FREELIST_RANDOM y - -${optionalString (versionAtLeast version "4.14") '' - SLAB_FREELIST_HARDENED y -''} - -# Allow enabling slub/slab free poisoning with slub_debug=P -SLUB_DEBUG y - -# Wipe higher-level memory allocations on free() with page_poison=1 -PAGE_POISONING y -PAGE_POISONING_NO_SANITY y -PAGE_POISONING_ZERO y - -# Reboot devices immediately if kernel experiences an Oops. -PANIC_ON_OOPS y -PANIC_TIMEOUT -1 - -GCC_PLUGINS y # Enable gcc plugin options -# Gather additional entropy at boot time for systems that may not have appropriate entropy sources. -GCC_PLUGIN_LATENT_ENTROPY y - -${optionalString (versionAtLeast version "4.11") '' - GCC_PLUGIN_STRUCTLEAK y # A port of the PaX structleak plugin -''} -${optionalString (versionAtLeast version "4.14") '' - GCC_PLUGIN_STRUCTLEAK_BYREF_ALL y # Also cover structs passed by address -''} -${optionalString (versionAtLeast version "4.20") '' - GCC_PLUGIN_STACKLEAK y # A port of the PaX stackleak plugin -''} - -${optionalString (versionAtLeast version "4.13") '' - GCC_PLUGIN_RANDSTRUCT y # A port of the PaX randstruct plugin - GCC_PLUGIN_RANDSTRUCT_PERFORMANCE y -''} - -# Disable various dangerous settings -ACPI_CUSTOM_METHOD n # Allows writing directly to physical memory -PROC_KCORE n # Exposes kernel text image layout -INET_DIAG n # Has been used for heap based attacks in the past - -# Use -fstack-protector-strong (gcc 4.9+) for best stack canary coverage. -${optionalString (versionOlder version "4.18") '' - CC_STACKPROTECTOR_REGULAR n - CC_STACKPROTECTOR_STRONG y -''} - -# Enable compile/run-time buffer overflow detection ala glibc's _FORTIFY_SOURCE -${optionalString (versionAtLeast version "4.13") '' - FORTIFY_SOURCE y -''} -'' + LEGACY_VSYSCALL_NONE = yes; +} // { + # Report BUG() conditions and kill the offending process. + BUG = yes; + + BUG_ON_DATA_CORRUPTION = whenAtLeast "4.10" yes; + + # Safer page access permissions (wrt. code injection). Default on >=4.11. + DEBUG_RODATA = whenOlder "4.11" yes; + DEBUG_SET_MODULE_RONX = whenOlder "4.11" yes; + + # Mark LSM hooks read-only after init. SECURITY_WRITABLE_HOOKS n + # conflicts with SECURITY_SELINUX_DISABLE y; disabling the latter + # implicitly marks LSM hooks read-only after init. + # + # SELinux can only be disabled at boot via selinux=0 + # + # We set SECURITY_WRITABLE_HOOKS n primarily for documentation purposes; the + # config builder fails to detect that it has indeed been unset. + SECURITY_SELINUX_DISABLE = whenAtLeast "4.12" no; + SECURITY_WRITABLE_HOOKS = whenAtLeast "4.12" (option no); + + DEBUG_WX = yes; # boot-time warning on RWX mappings + STRICT_KERNEL_RWX = whenAtLeast "4.11" yes; + + # Stricter /dev/mem + STRICT_DEVMEM = option yes; + IO_STRICT_DEVMEM = option yes; + + # Perform additional validation of commonly targeted structures. + DEBUG_CREDENTIALS = yes; + DEBUG_NOTIFIERS = yes; + DEBUG_LIST = yes; + DEBUG_PI_LIST = yes; # doesn't BUG() + DEBUG_SG = yes; + SCHED_STACK_END_CHECK = yes; + + REFCOUNT_FULL = whenAtLeast "4.13" yes; + + # Perform usercopy bounds checking. + HARDENED_USERCOPY = yes; + HARDENED_USERCOPY_FALLBACK = whenAtLeast "4.16" no; # for full whitelist enforcement + + # Randomize allocator freelists. + SLAB_FREELIST_RANDOM = yes; + + SLAB_FREELIST_HARDENED = whenAtLeast "4.14" yes; + + # Allow enabling slub/slab free poisoning with slub_debug=P + SLUB_DEBUG = yes; + + # Wipe higher-level memory allocations on free() with page_poison=1 + PAGE_POISONING = yes; + PAGE_POISONING_NO_SANITY = yes; + PAGE_POISONING_ZERO = yes; + + # Reboot devices immediately if kernel experiences an Oops. + PANIC_ON_OOPS = yes; + 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. + GCC_PLUGIN_LATENT_ENTROPY = yes; + + GCC_PLUGIN_STRUCTLEAK = whenAtLeast "4.11" yes; # A port of the PaX structleak plugin + GCC_PLUGIN_STRUCTLEAK_BYREF_ALL = whenAtLeast "4.14" yes; # Also cover structs passed by address + GCC_PLUGIN_STACKLEAK = whenAtLeast "4.20" yes; # A port of the PaX stackleak plugin + GCC_PLUGIN_RANDSTRUCT = whenAtLeast "4.13" yes; # A port of the PaX randstruct plugin + GCC_PLUGIN_RANDSTRUCT_PERFORMANCE = whenAtLeast "4.13" yes; + + # Disable various dangerous settings + ACPI_CUSTOM_METHOD = no; # Allows writing directly to physical memory + PROC_KCORE = no; # Exposes kernel text image layout + INET_DIAG = no; # Has been used for heap based attacks in the past + + # 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; + + # Enable compile/run-time buffer overflow detection ala glibc's _FORTIFY_SOURCE + FORTIFY_SOURCE = whenAtLeast "4.13" yes; + +} diff --git a/pkgs/test/default.nix b/pkgs/test/default.nix index 809b2d0b553..9b434da7a84 100644 --- a/pkgs/test/default.nix +++ b/pkgs/test/default.nix @@ -24,6 +24,8 @@ with pkgs; cc-multilib-gcc = callPackage ./cc-wrapper/multilib.nix { stdenv = gccMultiStdenv; }; cc-multilib-clang = callPackage ./cc-wrapper/multilib.nix { stdenv = clangMultiStdenv; }; + kernel-config = callPackage ./kernel.nix {}; + ld-library-path = callPackage ./ld-library-path {}; macOSSierraShared = callPackage ./macos-sierra-shared {}; diff --git a/pkgs/test/kernel.nix b/pkgs/test/kernel.nix new file mode 100644 index 00000000000..14a4d5ea104 --- /dev/null +++ b/pkgs/test/kernel.nix @@ -0,0 +1,53 @@ +{ stdenv, lib, pkgs }: + +with lib.kernel; +with lib.asserts; +with lib.modules; + +# 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; + + mandatoryVsOptionalConfig = mkMerge [ + { USB_DEBUG = option yes;} + { USB_DEBUG = 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: + ]; + + yesWinsOverNoConfig = mkMerge [ + # default for "8139TOO_PIO" is no + { "8139TOO_PIO" = yes; } # yes wins over no by default + { "8139TOO_PIO" = no; } + ]; +in +{ + # mandatory flag should win over optional + mandatoryCheck = (kernelTestConfig mandatoryVsOptionalConfig); + + # check that freeform options are unique + # Should trigger + # > The option `settings.MMC_BLOCK_MINORS.freeform' has conflicting definitions, in `<unknown-file>' and `<unknown-file>' + freeformCheck = let + res = builtins.tryEval ( (kernelTestConfig freeformConfig).MMC_BLOCK_MINORS.freeform); + in + assertTrue (res.success == false); + + yesVsNoCheck = let + res = kernelTestConfig yesWinsOverNoConfig; + in + assertTrue (res."8139TOO_PIO".tristate == "y"); +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index a0ad2ea28d3..6ebc487ce6b 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -14756,7 +14756,7 @@ in # Hardened linux hardenedLinuxPackagesFor = kernel: linuxPackagesFor (kernel.override { features.ia32Emulation = false; - extraConfig = import ../os-specific/linux/kernel/hardened-config.nix { + structuredExtraConfig = import ../os-specific/linux/kernel/hardened-config.nix { inherit stdenv; inherit (kernel) version; }; |