Merge pull request #42838 from teto/kernel_autoconf
[RFC] add ability to merge structured configs
This commit is contained in:
commit
51d2eed83b
@ -1,57 +1,21 @@
|
|||||||
{ lib
|
{ lib, version }:
|
||||||
# we pass the kernel version here to keep a nice syntax `whenOlder "4.13"`
|
|
||||||
# kernelVersion, e.g., config.boot.kernelPackages.version
|
|
||||||
, version
|
|
||||||
, mkValuePreprocess ? null
|
|
||||||
}:
|
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
rec {
|
rec {
|
||||||
# Common patterns
|
# Common patterns/legacy
|
||||||
when = cond: opt: if cond then opt else null;
|
whenAtLeast = ver: mkIf (versionAtLeast version ver);
|
||||||
whenAtLeast = ver: when (versionAtLeast version ver);
|
whenOlder = ver: mkIf (versionOlder version ver);
|
||||||
whenOlder = ver: when (versionOlder version ver);
|
# range is (inclusive, exclusive)
|
||||||
whenBetween = verLow: verHigh: when (versionAtLeast version verLow && versionOlder version verHigh);
|
whenBetween = verLow: verHigh: mkIf (versionAtLeast version verLow && versionOlder version verHigh);
|
||||||
|
|
||||||
|
|
||||||
# Keeping these around in case we decide to change this horrible implementation :)
|
# Keeping these around in case we decide to change this horrible implementation :)
|
||||||
option = x: if x == null then null else "?${x}";
|
option = x:
|
||||||
yes = "y";
|
x // { optional = true; };
|
||||||
no = "n";
|
|
||||||
module = "m";
|
|
||||||
|
|
||||||
mkValue = val:
|
yes = { tristate = "y"; };
|
||||||
let
|
no = { tristate = "n"; };
|
||||||
isNumber = c: elem c ["0" "1" "2" "3" "4" "5" "6" "7" "8" "9"];
|
module = { tristate = "m"; };
|
||||||
in
|
freeform = x: { freeform = x; };
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
# 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;
|
|
||||||
}
|
}
|
||||||
|
137
nixos/modules/system/boot/kernel_config.nix
Normal file
137
nixos/modules/system/boot/kernel_config.nix
Normal file
@ -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;
|
||||||
|
};
|
||||||
|
}
|
@ -12,20 +12,9 @@
|
|||||||
# Configuration
|
# Configuration
|
||||||
{ stdenv, version
|
{ 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; }
|
, features ? { grsecurity = false; xen_dom0 = false; }
|
||||||
}:
|
}:
|
||||||
|
|
||||||
assert (mkValueOverride == null) || (builtins.isFunction mkValueOverride);
|
|
||||||
|
|
||||||
with stdenv.lib;
|
with stdenv.lib;
|
||||||
|
|
||||||
with import ../../../../lib/kernel.nix { inherit (stdenv) lib; inherit version; };
|
with import ../../../../lib/kernel.nix { inherit (stdenv) lib; inherit version; };
|
||||||
@ -46,7 +35,7 @@ let
|
|||||||
DEBUG_NX_TEST = whenOlder "4.11" no;
|
DEBUG_NX_TEST = whenOlder "4.11" no;
|
||||||
CPU_NOTIFIER_ERROR_INJECT = whenOlder "4.4" (option no);
|
CPU_NOTIFIER_ERROR_INJECT = whenOlder "4.4" (option no);
|
||||||
DEBUG_STACK_USAGE = no;
|
DEBUG_STACK_USAGE = no;
|
||||||
DEBUG_STACKOVERFLOW = when (!features.grsecurity) no;
|
DEBUG_STACKOVERFLOW = mkIf (!features.grsecurity) no;
|
||||||
RCU_TORTURE_TEST = no;
|
RCU_TORTURE_TEST = no;
|
||||||
SCHEDSTATS = no;
|
SCHEDSTATS = no;
|
||||||
DETECT_HUNG_TASK = yes;
|
DETECT_HUNG_TASK = yes;
|
||||||
@ -114,7 +103,7 @@ let
|
|||||||
IP_DCCP_CCID3 = no; # experimental
|
IP_DCCP_CCID3 = no; # experimental
|
||||||
CLS_U32_PERF = yes;
|
CLS_U32_PERF = yes;
|
||||||
CLS_U32_MARK = 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;
|
WAN = yes;
|
||||||
# Required by systemd per-cgroup firewalling
|
# Required by systemd per-cgroup firewalling
|
||||||
CGROUP_BPF = option yes;
|
CGROUP_BPF = option yes;
|
||||||
@ -184,7 +173,7 @@ let
|
|||||||
FB_VESA = yes;
|
FB_VESA = yes;
|
||||||
FRAMEBUFFER_CONSOLE = yes;
|
FRAMEBUFFER_CONSOLE = yes;
|
||||||
FRAMEBUFFER_CONSOLE_ROTATION = yes;
|
FRAMEBUFFER_CONSOLE_ROTATION = yes;
|
||||||
FB_GEODE = when (stdenv.hostPlatform.system == "i686-linux") yes;
|
FB_GEODE = mkIf (stdenv.hostPlatform.system == "i686-linux") yes;
|
||||||
};
|
};
|
||||||
|
|
||||||
video = {
|
video = {
|
||||||
@ -239,7 +228,7 @@ let
|
|||||||
};
|
};
|
||||||
|
|
||||||
usb = {
|
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_ROOT_HUB_TT = yes; # Root Hub Transaction Translators
|
||||||
USB_EHCI_TT_NEWSCHED = yes; # Improved transaction translator scheduling
|
USB_EHCI_TT_NEWSCHED = yes; # Improved transaction translator scheduling
|
||||||
};
|
};
|
||||||
@ -250,7 +239,7 @@ let
|
|||||||
FANOTIFY = yes;
|
FANOTIFY = yes;
|
||||||
TMPFS = yes;
|
TMPFS = yes;
|
||||||
TMPFS_POSIX_ACL = 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_XATTR = yes;
|
||||||
EXT2_FS_POSIX_ACL = yes;
|
EXT2_FS_POSIX_ACL = yes;
|
||||||
@ -262,7 +251,7 @@ let
|
|||||||
|
|
||||||
EXT4_FS_POSIX_ACL = yes;
|
EXT4_FS_POSIX_ACL = yes;
|
||||||
EXT4_FS_SECURITY = 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_XATTR = option yes;
|
||||||
REISERFS_FS_POSIX_ACL = option yes;
|
REISERFS_FS_POSIX_ACL = option yes;
|
||||||
@ -324,7 +313,7 @@ let
|
|||||||
|
|
||||||
# Native Language Support modules, needed by some filesystems
|
# Native Language Support modules, needed by some filesystems
|
||||||
NLS = yes;
|
NLS = yes;
|
||||||
NLS_DEFAULT = "utf8";
|
NLS_DEFAULT = freeform "utf8";
|
||||||
NLS_UTF8 = module;
|
NLS_UTF8 = module;
|
||||||
NLS_CODEPAGE_437 = module; # VFAT default for the codepage= mount option
|
NLS_CODEPAGE_437 = module; # VFAT default for the codepage= mount option
|
||||||
NLS_ISO8859_1 = module; # VFAT default for the iocharset= mount option
|
NLS_ISO8859_1 = module; # VFAT default for the iocharset= mount option
|
||||||
@ -334,13 +323,13 @@ let
|
|||||||
|
|
||||||
security = {
|
security = {
|
||||||
# Detect writes to read-only module pages
|
# 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;
|
RANDOMIZE_BASE = option yes;
|
||||||
STRICT_DEVMEM = option yes; # Filter access to /dev/mem
|
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
|
# Prevent processes from ptracing non-children processes
|
||||||
SECURITY_YAMA = option yes;
|
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
|
USER_NS = yes; # Support for user namespaces
|
||||||
|
|
||||||
@ -350,7 +339,7 @@ let
|
|||||||
} // optionalAttrs (!stdenv.hostPlatform.isAarch32) {
|
} // optionalAttrs (!stdenv.hostPlatform.isAarch32) {
|
||||||
|
|
||||||
# Detect buffer overflows on the stack
|
# 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 = {
|
microcode = {
|
||||||
@ -407,8 +396,8 @@ let
|
|||||||
FTRACE_SYSCALLS = yes;
|
FTRACE_SYSCALLS = yes;
|
||||||
SCHED_TRACER = yes;
|
SCHED_TRACER = yes;
|
||||||
STACK_TRACER = yes;
|
STACK_TRACER = yes;
|
||||||
UPROBE_EVENT = option (whenOlder "4.11" yes);
|
UPROBE_EVENT = { optional = true; tristate = whenOlder "4.11" "y";};
|
||||||
UPROBE_EVENTS = option (whenAtLeast "4.11" yes);
|
UPROBE_EVENTS = { optional = true; tristate = whenAtLeast "4.11" "y";};
|
||||||
BPF_SYSCALL = whenAtLeast "4.4" yes;
|
BPF_SYSCALL = whenAtLeast "4.4" yes;
|
||||||
BPF_EVENTS = whenAtLeast "4.4" yes;
|
BPF_EVENTS = whenAtLeast "4.4" yes;
|
||||||
FUNCTION_PROFILER = yes;
|
FUNCTION_PROFILER = yes;
|
||||||
@ -418,23 +407,23 @@ let
|
|||||||
virtualisation = {
|
virtualisation = {
|
||||||
PARAVIRT = option yes;
|
PARAVIRT = option yes;
|
||||||
|
|
||||||
HYPERVISOR_GUEST = when (!features.grsecurity) yes;
|
HYPERVISOR_GUEST = mkIf (!features.grsecurity) yes;
|
||||||
PARAVIRT_SPINLOCKS = option yes;
|
PARAVIRT_SPINLOCKS = option yes;
|
||||||
|
|
||||||
KVM_APIC_ARCHITECTURE = whenOlder "4.8" yes;
|
KVM_APIC_ARCHITECTURE = whenOlder "4.8" yes;
|
||||||
KVM_ASYNC_PF = yes;
|
KVM_ASYNC_PF = yes;
|
||||||
KVM_COMPAT = option (whenBetween "4.0" "4.12" yes);
|
KVM_COMPAT = { optional = true; tristate = whenBetween "4.0" "4.12" "y"; };
|
||||||
KVM_DEVICE_ASSIGNMENT = option (whenBetween "3.10" "4.12" yes);
|
KVM_DEVICE_ASSIGNMENT = { optional = true; tristate = whenBetween "3.10" "4.12" "y"; };
|
||||||
KVM_GENERIC_DIRTYLOG_READ_PROTECT = whenAtLeast "4.0" yes;
|
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_MMIO = yes;
|
||||||
KVM_VFIO = yes;
|
KVM_VFIO = yes;
|
||||||
KSM = yes;
|
KSM = yes;
|
||||||
VIRT_DRIVERS = yes;
|
VIRT_DRIVERS = yes;
|
||||||
# We nneed 64 GB (PAE) support for Xen guest support
|
# 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) ({
|
} // optionalAttrs (stdenv.isx86_64 || stdenv.isi686) ({
|
||||||
XEN = option yes;
|
XEN = option yes;
|
||||||
@ -542,8 +531,8 @@ let
|
|||||||
CRYPTO_TEST = option no;
|
CRYPTO_TEST = option no;
|
||||||
EFI_TEST = option no;
|
EFI_TEST = option no;
|
||||||
GLOB_SELFTEST = option no;
|
GLOB_SELFTEST = option no;
|
||||||
DRM_DEBUG_MM_SELFTEST = option (whenOlder "4.18" no);
|
DRM_DEBUG_MM_SELFTEST = { optional = true; tristate = whenOlder "4.18" "n";};
|
||||||
LNET_SELFTEST = option (whenOlder "4.18" no);
|
LNET_SELFTEST = { optional = true; tristate = whenOlder "4.18" "n";};
|
||||||
LOCK_TORTURE_TEST = option no;
|
LOCK_TORTURE_TEST = option no;
|
||||||
MTD_TESTS = option no;
|
MTD_TESTS = option no;
|
||||||
NOTIFIER_ERROR_INJECTION = option no;
|
NOTIFIER_ERROR_INJECTION = option no;
|
||||||
@ -598,7 +587,7 @@ let
|
|||||||
AIC79XX_DEBUG_ENABLE = no;
|
AIC79XX_DEBUG_ENABLE = no;
|
||||||
AIC7XXX_DEBUG_ENABLE = no;
|
AIC7XXX_DEBUG_ENABLE = no;
|
||||||
AIC94XX_DEBUG = no;
|
AIC94XX_DEBUG = no;
|
||||||
B43_PCMCIA = option (whenOlder "4.4" yes);
|
B43_PCMCIA = { optional=true; tristate = whenOlder "4.4" "y";};
|
||||||
|
|
||||||
BLK_DEV_INTEGRITY = yes;
|
BLK_DEV_INTEGRITY = yes;
|
||||||
|
|
||||||
@ -651,7 +640,7 @@ let
|
|||||||
# GPIO on Intel Bay Trail, for some Chromebook internal eMMC disks
|
# GPIO on Intel Bay Trail, for some Chromebook internal eMMC disks
|
||||||
PINCTRL_BAYTRAIL = yes;
|
PINCTRL_BAYTRAIL = yes;
|
||||||
# 8 is default. Modern gpt tables on eMMC may go far beyond 8.
|
# 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
|
REGULATOR = yes; # Voltage and Current Regulator Support
|
||||||
RC_DEVICES = option yes; # Enable IR devices
|
RC_DEVICES = option yes; # Enable IR devices
|
||||||
@ -698,7 +687,8 @@ let
|
|||||||
|
|
||||||
# Bump the maximum number of CPUs to support systems like EC2 x1.*
|
# Bump the maximum number of CPUs to support systems like EC2 x1.*
|
||||||
# instances and Xeon Phi.
|
# instances and Xeon Phi.
|
||||||
NR_CPUS = "384";
|
NR_CPUS = freeform "384";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in (generateNixKConf ((flattenKConf options) // structuredExtraConfig) mkValueOverride) + extraConfig
|
in
|
||||||
|
flattenKConf options
|
||||||
|
@ -47,7 +47,6 @@
|
|||||||
, preferBuiltin ? stdenv.hostPlatform.platform.kernelPreferBuiltin or false
|
, preferBuiltin ? stdenv.hostPlatform.platform.kernelPreferBuiltin or false
|
||||||
, kernelArch ? stdenv.hostPlatform.platform.kernelArch
|
, kernelArch ? stdenv.hostPlatform.platform.kernelArch
|
||||||
|
|
||||||
, mkValueOverride ? null
|
|
||||||
, ...
|
, ...
|
||||||
}:
|
}:
|
||||||
|
|
||||||
@ -68,20 +67,26 @@ let
|
|||||||
ia32Emulation = true;
|
ia32Emulation = true;
|
||||||
} // features) kernelPatches;
|
} // features) kernelPatches;
|
||||||
|
|
||||||
intermediateNixConfig = import ./common-config.nix {
|
commonStructuredConfig = import ./common-config.nix {
|
||||||
inherit stdenv version structuredExtraConfig mkValueOverride;
|
inherit stdenv version ;
|
||||||
|
|
||||||
# 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;
|
|
||||||
|
|
||||||
features = kernelFeatures; # Ensure we know of all extra patches, etc.
|
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
|
let
|
||||||
configFromPatches =
|
configFromPatches =
|
||||||
map ({extraConfig ? "", ...}: extraConfig) kernelPatches;
|
map ({extraConfig ? "", ...}: extraConfig) kernelPatches;
|
||||||
in lib.concatStringsSep "\n" ([baseConfig] ++ configFromPatches);
|
in lib.concatStringsSep "\n" ([baseConfigStr] ++ configFromPatches);
|
||||||
|
|
||||||
configfile = stdenv.mkDerivation {
|
configfile = stdenv.mkDerivation {
|
||||||
inherit ignoreConfigErrors autoModules preferBuiltin kernelArch;
|
inherit ignoreConfigErrors autoModules preferBuiltin kernelArch;
|
||||||
@ -131,8 +136,31 @@ let
|
|||||||
installPhase = "mv $buildRoot/.config $out";
|
installPhase = "mv $buildRoot/.config $out";
|
||||||
|
|
||||||
enableParallelBuilding = true;
|
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 {}) {
|
kernel = (callPackage ./manual-config.nix {}) {
|
||||||
inherit version modDirVersion src kernelPatches stdenv extraMeta configfile;
|
inherit version modDirVersion src kernelPatches stdenv extraMeta configfile;
|
||||||
|
|
||||||
@ -141,6 +169,7 @@ let
|
|||||||
|
|
||||||
passthru = {
|
passthru = {
|
||||||
features = kernelFeatures;
|
features = kernelFeatures;
|
||||||
|
inherit commonStructuredConfig;
|
||||||
passthru = kernel.passthru // (removeAttrs passthru [ "passthru" ]);
|
passthru = kernel.passthru // (removeAttrs passthru [ "passthru" ]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11,46 +11,40 @@
|
|||||||
{ stdenv, version }:
|
{ stdenv, version }:
|
||||||
|
|
||||||
with stdenv.lib;
|
with stdenv.lib;
|
||||||
|
with import ../../../../lib/kernel.nix { inherit (stdenv) lib; inherit version; };
|
||||||
|
|
||||||
assert (versionAtLeast version "4.9");
|
assert (versionAtLeast version "4.9");
|
||||||
|
|
||||||
''
|
optionalAttrs (stdenv.hostPlatform.platform.kernelArch == "x86_64") {
|
||||||
# Report BUG() conditions and kill the offending process.
|
DEFAULT_MMAP_MIN_ADDR = freeform "65536"; # Prevent allocation of first 64K of memory
|
||||||
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
|
|
||||||
|
|
||||||
# Reduce attack surface by disabling various emulations
|
# Reduce attack surface by disabling various emulations
|
||||||
IA32_EMULATION n
|
IA32_EMULATION = no;
|
||||||
X86_X32 n
|
X86_X32 = no;
|
||||||
# Note: this config depends on EXPERT y and so will not take effect, hence
|
# Note: this config depends on EXPERT y and so will not take effect, hence
|
||||||
# it is left "optional" for now.
|
# it is left "optional" for now.
|
||||||
MODIFY_LDT_SYSCALL? n
|
MODIFY_LDT_SYSCALL = option no;
|
||||||
|
VMAP_STACK = yes; # Catch kernel stack overflows
|
||||||
VMAP_STACK y # Catch kernel stack overflows
|
|
||||||
|
|
||||||
# Randomize position of kernel and memory.
|
# Randomize position of kernel and memory.
|
||||||
RANDOMIZE_BASE y
|
RANDOMIZE_BASE = yes;
|
||||||
RANDOMIZE_MEMORY y
|
RANDOMIZE_MEMORY = yes;
|
||||||
|
|
||||||
# Disable legacy virtual syscalls by default (modern glibc use vDSO instead).
|
# Disable legacy virtual syscalls by default (modern glibc use vDSO instead).
|
||||||
#
|
#
|
||||||
# Note that the vanilla default is to *emulate* the legacy vsyscall mechanism,
|
# 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
|
# which is supposed to be safer than the native variant (wrt. ret2libc), so
|
||||||
# disabling it mainly helps reduce surface.
|
# disabling it mainly helps reduce surface.
|
||||||
LEGACY_VSYSCALL_NONE 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.
|
# Safer page access permissions (wrt. code injection). Default on >=4.11.
|
||||||
${optionalString (versionOlder version "4.11") ''
|
DEBUG_RODATA = whenOlder "4.11" yes;
|
||||||
DEBUG_RODATA y
|
DEBUG_SET_MODULE_RONX = whenOlder "4.11" yes;
|
||||||
DEBUG_SET_MODULE_RONX y
|
|
||||||
''}
|
|
||||||
|
|
||||||
# Mark LSM hooks read-only after init. SECURITY_WRITABLE_HOOKS n
|
# Mark LSM hooks read-only after init. SECURITY_WRITABLE_HOOKS n
|
||||||
# conflicts with SECURITY_SELINUX_DISABLE y; disabling the latter
|
# conflicts with SECURITY_SELINUX_DISABLE y; disabling the latter
|
||||||
@ -60,89 +54,67 @@ ${optionalString (versionOlder version "4.11") ''
|
|||||||
#
|
#
|
||||||
# We set SECURITY_WRITABLE_HOOKS n primarily for documentation purposes; the
|
# We set SECURITY_WRITABLE_HOOKS n primarily for documentation purposes; the
|
||||||
# config builder fails to detect that it has indeed been unset.
|
# config builder fails to detect that it has indeed been unset.
|
||||||
${optionalString (versionAtLeast version "4.12") ''
|
SECURITY_SELINUX_DISABLE = whenAtLeast "4.12" no;
|
||||||
SECURITY_SELINUX_DISABLE n
|
SECURITY_WRITABLE_HOOKS = whenAtLeast "4.12" (option no);
|
||||||
SECURITY_WRITABLE_HOOKS? n
|
|
||||||
''}
|
|
||||||
|
|
||||||
DEBUG_WX y # boot-time warning on RWX mappings
|
DEBUG_WX = yes; # boot-time warning on RWX mappings
|
||||||
${optionalString (versionAtLeast version "4.11") ''
|
STRICT_KERNEL_RWX = whenAtLeast "4.11" yes;
|
||||||
STRICT_KERNEL_RWX y
|
|
||||||
''}
|
|
||||||
|
|
||||||
# Stricter /dev/mem
|
# Stricter /dev/mem
|
||||||
STRICT_DEVMEM? y
|
STRICT_DEVMEM = option yes;
|
||||||
IO_STRICT_DEVMEM? y
|
IO_STRICT_DEVMEM = option yes;
|
||||||
|
|
||||||
# Perform additional validation of commonly targeted structures.
|
# Perform additional validation of commonly targeted structures.
|
||||||
DEBUG_CREDENTIALS y
|
DEBUG_CREDENTIALS = yes;
|
||||||
DEBUG_NOTIFIERS y
|
DEBUG_NOTIFIERS = yes;
|
||||||
DEBUG_LIST y
|
DEBUG_LIST = yes;
|
||||||
DEBUG_PI_LIST y # doesn't BUG()
|
DEBUG_PI_LIST = yes; # doesn't BUG()
|
||||||
DEBUG_SG y
|
DEBUG_SG = yes;
|
||||||
SCHED_STACK_END_CHECK y
|
SCHED_STACK_END_CHECK = yes;
|
||||||
|
|
||||||
${optionalString (versionAtLeast version "4.13") ''
|
REFCOUNT_FULL = whenAtLeast "4.13" yes;
|
||||||
REFCOUNT_FULL y
|
|
||||||
''}
|
|
||||||
|
|
||||||
# Perform usercopy bounds checking.
|
# Perform usercopy bounds checking.
|
||||||
HARDENED_USERCOPY y
|
HARDENED_USERCOPY = yes;
|
||||||
${optionalString (versionAtLeast version "4.16") ''
|
HARDENED_USERCOPY_FALLBACK = whenAtLeast "4.16" no; # for full whitelist enforcement
|
||||||
HARDENED_USERCOPY_FALLBACK n # for full whitelist enforcement
|
|
||||||
''}
|
|
||||||
|
|
||||||
# Randomize allocator freelists.
|
# Randomize allocator freelists.
|
||||||
SLAB_FREELIST_RANDOM y
|
SLAB_FREELIST_RANDOM = yes;
|
||||||
|
|
||||||
${optionalString (versionAtLeast version "4.14") ''
|
SLAB_FREELIST_HARDENED = whenAtLeast "4.14" yes;
|
||||||
SLAB_FREELIST_HARDENED y
|
|
||||||
''}
|
|
||||||
|
|
||||||
# Allow enabling slub/slab free poisoning with slub_debug=P
|
# Allow enabling slub/slab free poisoning with slub_debug=P
|
||||||
SLUB_DEBUG y
|
SLUB_DEBUG = yes;
|
||||||
|
|
||||||
# Wipe higher-level memory allocations on free() with page_poison=1
|
# Wipe higher-level memory allocations on free() with page_poison=1
|
||||||
PAGE_POISONING y
|
PAGE_POISONING = yes;
|
||||||
PAGE_POISONING_NO_SANITY y
|
PAGE_POISONING_NO_SANITY = yes;
|
||||||
PAGE_POISONING_ZERO y
|
PAGE_POISONING_ZERO = yes;
|
||||||
|
|
||||||
# Reboot devices immediately if kernel experiences an Oops.
|
# Reboot devices immediately if kernel experiences an Oops.
|
||||||
PANIC_ON_OOPS y
|
PANIC_ON_OOPS = yes;
|
||||||
PANIC_TIMEOUT -1
|
PANIC_TIMEOUT = freeform "-1";
|
||||||
|
|
||||||
GCC_PLUGINS y # Enable gcc plugin options
|
GCC_PLUGINS = yes; # Enable gcc plugin options
|
||||||
# Gather additional entropy at boot time for systems that may not have appropriate entropy sources.
|
# Gather additional entropy at boot time for systems that may = no;ot have appropriate entropy sources.
|
||||||
GCC_PLUGIN_LATENT_ENTROPY y
|
GCC_PLUGIN_LATENT_ENTROPY = yes;
|
||||||
|
|
||||||
${optionalString (versionAtLeast version "4.11") ''
|
GCC_PLUGIN_STRUCTLEAK = whenAtLeast "4.11" yes; # A port of the PaX structleak plugin
|
||||||
GCC_PLUGIN_STRUCTLEAK y # 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
|
||||||
${optionalString (versionAtLeast version "4.14") ''
|
GCC_PLUGIN_RANDSTRUCT = whenAtLeast "4.13" yes; # A port of the PaX randstruct plugin
|
||||||
GCC_PLUGIN_STRUCTLEAK_BYREF_ALL y # Also cover structs passed by address
|
GCC_PLUGIN_RANDSTRUCT_PERFORMANCE = whenAtLeast "4.13" yes;
|
||||||
''}
|
|
||||||
${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
|
# Disable various dangerous settings
|
||||||
ACPI_CUSTOM_METHOD n # Allows writing directly to physical memory
|
ACPI_CUSTOM_METHOD = no; # Allows writing directly to physical memory
|
||||||
PROC_KCORE n # Exposes kernel text image layout
|
PROC_KCORE = no; # Exposes kernel text image layout
|
||||||
INET_DIAG n # Has been used for heap based attacks in the past
|
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.
|
# Use -fstack-protector-strong (gcc 4.9+) for best stack canary coverage.
|
||||||
${optionalString (versionOlder version "4.18") ''
|
CC_STACKPROTECTOR_REGULAR = whenOlder "4.18" no;
|
||||||
CC_STACKPROTECTOR_REGULAR n
|
CC_STACKPROTECTOR_STRONG = whenOlder "4.18" yes;
|
||||||
CC_STACKPROTECTOR_STRONG y
|
|
||||||
''}
|
|
||||||
|
|
||||||
# Enable compile/run-time buffer overflow detection ala glibc's _FORTIFY_SOURCE
|
# Enable compile/run-time buffer overflow detection ala glibc's _FORTIFY_SOURCE
|
||||||
${optionalString (versionAtLeast version "4.13") ''
|
FORTIFY_SOURCE = whenAtLeast "4.13" yes;
|
||||||
FORTIFY_SOURCE y
|
|
||||||
''}
|
}
|
||||||
''
|
|
||||||
|
@ -24,6 +24,8 @@ with pkgs;
|
|||||||
cc-multilib-gcc = callPackage ./cc-wrapper/multilib.nix { stdenv = gccMultiStdenv; };
|
cc-multilib-gcc = callPackage ./cc-wrapper/multilib.nix { stdenv = gccMultiStdenv; };
|
||||||
cc-multilib-clang = callPackage ./cc-wrapper/multilib.nix { stdenv = clangMultiStdenv; };
|
cc-multilib-clang = callPackage ./cc-wrapper/multilib.nix { stdenv = clangMultiStdenv; };
|
||||||
|
|
||||||
|
kernel-config = callPackage ./kernel.nix {};
|
||||||
|
|
||||||
ld-library-path = callPackage ./ld-library-path {};
|
ld-library-path = callPackage ./ld-library-path {};
|
||||||
|
|
||||||
macOSSierraShared = callPackage ./macos-sierra-shared {};
|
macOSSierraShared = callPackage ./macos-sierra-shared {};
|
||||||
|
53
pkgs/test/kernel.nix
Normal file
53
pkgs/test/kernel.nix
Normal file
@ -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");
|
||||||
|
}
|
@ -14756,7 +14756,7 @@ in
|
|||||||
# Hardened linux
|
# Hardened linux
|
||||||
hardenedLinuxPackagesFor = kernel: linuxPackagesFor (kernel.override {
|
hardenedLinuxPackagesFor = kernel: linuxPackagesFor (kernel.override {
|
||||||
features.ia32Emulation = false;
|
features.ia32Emulation = false;
|
||||||
extraConfig = import ../os-specific/linux/kernel/hardened-config.nix {
|
structuredExtraConfig = import ../os-specific/linux/kernel/hardened-config.nix {
|
||||||
inherit stdenv;
|
inherit stdenv;
|
||||||
inherit (kernel) version;
|
inherit (kernel) version;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user