From 4f27ad14a1ca4fcac1c572c7309cf6b8ef9e3d00 Mon Sep 17 00:00:00 2001 From: Austin Seipp Date: Wed, 14 May 2014 12:04:40 -0500 Subject: [PATCH] grsec: refactor grsecurity packages This now provides a handful of different grsecurity kernels for slightly different 'flavors' of packages. This doesn't change the grsecurity module to use them just yet, however. Signed-off-by: Austin Seipp --- nixos/modules/security/grsecurity.nix | 125 +------------- pkgs/build-support/grsecurity/default.nix | 153 ++++++++++++++++++ pkgs/build-support/grsecurity/flavors.nix | 32 ++++ .../linux/kernel/common-config.nix | 2 +- pkgs/os-specific/linux/kernel/linux-3.2.nix | 2 +- pkgs/top-level/all-packages.nix | 66 +++++++- 6 files changed, 252 insertions(+), 128 deletions(-) create mode 100644 pkgs/build-support/grsecurity/default.nix create mode 100644 pkgs/build-support/grsecurity/flavors.nix diff --git a/nixos/modules/security/grsecurity.nix b/nixos/modules/security/grsecurity.nix index a0f63cdf3a9e..78baa0cc5c3f 100644 --- a/nixos/modules/security/grsecurity.nix +++ b/nixos/modules/security/grsecurity.nix @@ -3,128 +3,11 @@ with lib; let - cfg = config.security.grsecurity; - - mkKernel = kernel: patch: - assert patch.kversion == kernel.version; - { inherit kernel patch; - inherit (patch) grversion revision; + customGrsecPkg = + (import ../../../pkgs/build-support/grsecurity + { grsecOptions = config.security.grsecurity; }; - - stable-patch = with pkgs.kernelPatches; - if cfg.vserver then grsecurity_vserver else grsecurity_stable; - stableKernel = mkKernel pkgs.linux_3_2 stable-patch; - testKernel = mkKernel pkgs.linux_3_14 pkgs.kernelPatches.grsecurity_unstable; - - ## -- grsecurity configuration ----------------------------------------------- - - grsecPrioCfg = - if cfg.config.priority == "security" then - "GRKERNSEC_CONFIG_PRIORITY_SECURITY y" - else - "GRKERNSEC_CONFIG_PRIORITY_PERF y"; - - grsecSystemCfg = - if cfg.config.system == "desktop" then - "GRKERNSEC_CONFIG_DESKTOP y" - else - "GRKERNSEC_CONFIG_SERVER y"; - - grsecVirtCfg = - if cfg.config.virtualisationConfig == "none" then - "GRKERNSEC_CONFIG_VIRT_NONE y" - else if cfg.config.virtualisationConfig == "host" then - "GRKERNSEC_CONFIG_VIRT_HOST y" - else - "GRKERNSEC_CONFIG_VIRT_GUEST y"; - - grsecHwvirtCfg = if cfg.config.virtualisationConfig == "none" then "" else - if cfg.config.hardwareVirtualisation == true then - "GRKERNSEC_CONFIG_VIRT_EPT y" - else - "GRKERNSEC_CONFIG_VIRT_SOFT y"; - - grsecVirtswCfg = - let virtCfg = opt: "GRKERNSEC_CONFIG_VIRT_"+opt+" y"; - in - if cfg.config.virtualisationConfig == "none" then "" - else if cfg.config.virtualisationSoftware == "xen" then virtCfg "XEN" - else if cfg.config.virtualisationSoftware == "kvm" then virtCfg "KVM" - else if cfg.config.virtualisationSoftware == "vmware" then virtCfg "VMWARE" - else virtCfg "VIRTUALBOX"; - - grsecMainConfig = if cfg.config.mode == "custom" then "" else '' - GRKERNSEC_CONFIG_AUTO y - ${grsecPrioCfg} - ${grsecSystemCfg} - ${grsecVirtCfg} - ${grsecHwvirtCfg} - ${grsecVirtswCfg} - ''; - - grsecConfig = - let boolToKernOpt = b: if b then "y" else "n"; - # Disable RANDSTRUCT under virtualbox, as it has some kind of - # breakage with the vbox guest drivers - randstruct = optionalString config.services.virtualbox.enable - "GRKERNSEC_RANDSTRUCT n"; - # Disable restricting links under the testing kernel, as something - # has changed causing it to fail miserably during boot. - restrictLinks = optionalString cfg.testing - "GRKERNSEC_LINK n"; - in '' - GRKERNSEC y - ${grsecMainConfig} - - ${if cfg.config.restrictProc then - "GRKERNSEC_PROC_USER y" - else - optionalString cfg.config.restrictProcWithGroup '' - GRKERNSEC_PROC_USERGROUP y - GRKERNSEC_PROC_GID ${toString cfg.config.unrestrictProcGid} - '' - } - - GRKERNSEC_SYSCTL ${boolToKernOpt cfg.config.sysctl} - GRKERNSEC_CHROOT_CHMOD ${boolToKernOpt cfg.config.denyChrootChmod} - GRKERNSEC_NO_RBAC ${boolToKernOpt cfg.config.disableRBAC} - ${randstruct} - ${restrictLinks} - - ${cfg.config.kernelExtraConfig} - ''; - - ## -- grsecurity kernel packages --------------------------------------------- - - localver = grkern: - "-grsec" + optionalString cfg.config.verboseVersion - "-${grkern.grversion}-${grkern.revision}"; - - grsecurityOverrider = args: grkern: { - # Apparently as of gcc 4.6, gcc-plugin headers (which are needed by PaX plugins) - # include libgmp headers, so we need these extra tweaks - buildInputs = args.buildInputs ++ [ pkgs.gmp ]; - preConfigure = '' - ${args.preConfigure or ""} - sed -i 's|-I|-I${pkgs.gmp}/include -I|' scripts/gcc-plugin.sh - sed -i 's|HOST_EXTRACFLAGS +=|HOST_EXTRACFLAGS += -I${pkgs.gmp}/include|' tools/gcc/Makefile - sed -i 's|HOST_EXTRACXXFLAGS +=|HOST_EXTRACXXFLAGS += -I${pkgs.gmp}/include|' tools/gcc/Makefile - rm localversion-grsec - echo ${localver grkern} > localversion-grsec - ''; - }; - - mkGrsecPkg = grkern: - let kernelPkg = lowPrio (overrideDerivation (grkern.kernel.override (args: { - kernelPatches = args.kernelPatches ++ [ grkern.patch pkgs.kernelPatches.grsec_fix_path ]; - argsOverride = { - modDirVersion = "${grkern.kernel.modDirVersion}${localver grkern}"; - }; - extraConfig = grsecConfig; - })) (args: grsecurityOverrider args grkern)); - in pkgs.linuxPackagesFor kernelPkg (mkGrsecPkg grkern); - - grsecPackage = mkGrsecPkg (if cfg.stable then stableKernel else testKernel); + ).grsecPackage; in { options = { diff --git a/pkgs/build-support/grsecurity/default.nix b/pkgs/build-support/grsecurity/default.nix new file mode 100644 index 000000000000..c44fcafe1970 --- /dev/null +++ b/pkgs/build-support/grsecurity/default.nix @@ -0,0 +1,153 @@ +{ grsecOptions, lib, pkgs }: + +with lib; + +let + cfg = { + stable = grsecOptions.stable or false; + vserver = grsecOptions.vserver or false; + testing = grsecOptions.testing or false; + config = { + mode = "auto"; + sysctl = false; + denyChrootChmod = false; + restrictProc = false; + restrictProcWithGroup = true; + unrestrictProcGid = 121; # Ugh, an awful hack. See grsecurity NixOS gid + disableRBAC = false; + verboseVersion = false; + kernelExtraConfig = ""; + } // grsecOptions.config; + }; + + vals = rec { + + mkKernel = kernel: patch: + assert patch.kversion == kernel.version; + { inherit kernel patch; + inherit (patch) grversion revision; + }; + + test-patch = with pkgs.kernelPatches; grsecurity_unstable; + stable-patch = with pkgs.kernelPatches; + if (cfg.vserver or false) then grsecurity_vserver else grsecurity_stable; + + stableKernel = mkKernel pkgs.linux_3_2 stable-patch; + testKernel = mkKernel pkgs.linux_3_14 test-patch; + + ## -- grsecurity configuration --------------------------------------------- + + grsecPrioCfg = + if cfg.config.priority == "security" then + "GRKERNSEC_CONFIG_PRIORITY_SECURITY y" + else + "GRKERNSEC_CONFIG_PRIORITY_PERF y"; + + grsecSystemCfg = + if cfg.config.system == "desktop" then + "GRKERNSEC_CONFIG_DESKTOP y" + else + "GRKERNSEC_CONFIG_SERVER y"; + + grsecVirtCfg = + if cfg.config.virtualisationConfig == "none" then + "GRKERNSEC_CONFIG_VIRT_NONE y" + else if cfg.config.virtualisationConfig == "host" then + "GRKERNSEC_CONFIG_VIRT_HOST y" + else + "GRKERNSEC_CONFIG_VIRT_GUEST y"; + + grsecHwvirtCfg = if cfg.config.virtualisationConfig == "none" then "" else + if cfg.config.hardwareVirtualisation == true then + "GRKERNSEC_CONFIG_VIRT_EPT y" + else + "GRKERNSEC_CONFIG_VIRT_SOFT y"; + + grsecVirtswCfg = + let virtCfg = opt: "GRKERNSEC_CONFIG_VIRT_"+opt+" y"; + in + if cfg.config.virtualisationConfig == "none" then "" + else if cfg.config.virtualisationSoftware == "xen" then virtCfg "XEN" + else if cfg.config.virtualisationSoftware == "kvm" then virtCfg "KVM" + else if cfg.config.virtualisationSoftware == "vmware" then virtCfg "VMWARE" + else virtCfg "VIRTUALBOX"; + + grsecMainConfig = if cfg.config.mode == "custom" then "" else '' + GRKERNSEC_CONFIG_AUTO y + ${grsecPrioCfg} + ${grsecSystemCfg} + ${grsecVirtCfg} + ${grsecHwvirtCfg} + ${grsecVirtswCfg} + ''; + + grsecConfig = + let boolToKernOpt = b: if b then "y" else "n"; + # Disable RANDSTRUCT under virtualbox, as it has some kind of + # breakage with the vbox guest drivers + #randstruct = optionalString config.services.virtualbox.enable + # "GRKERNSEC_RANDSTRUCT n"; + + # Disable restricting links under the testing kernel, as something + # has changed causing it to fail miserably during boot. + restrictLinks = optionalString cfg.testing + "GRKERNSEC_LINK n"; + in '' + GRKERNSEC y + ${grsecMainConfig} + + ${if cfg.config.restrictProc then + "GRKERNSEC_PROC_USER y" + else + optionalString cfg.config.restrictProcWithGroup '' + GRKERNSEC_PROC_USERGROUP y + GRKERNSEC_PROC_GID ${toString cfg.config.unrestrictProcGid} + '' + } + + GRKERNSEC_SYSCTL ${boolToKernOpt cfg.config.sysctl} + GRKERNSEC_CHROOT_CHMOD ${boolToKernOpt cfg.config.denyChrootChmod} + GRKERNSEC_NO_RBAC ${boolToKernOpt cfg.config.disableRBAC} + ${restrictLinks} + + ${cfg.config.kernelExtraConfig} + ''; + + ## -- grsecurity kernel packages ------------------------------------------- + + localver = grkern: + "-grsec" + optionalString cfg.config.verboseVersion + "-${grkern.grversion}-${grkern.revision}"; + + grsecurityOverrider = args: grkern: { + # Apparently as of gcc 4.6, gcc-plugin headers (which are needed by PaX plugins) + # include libgmp headers, so we need these extra tweaks + buildInputs = args.buildInputs ++ [ pkgs.gmp ]; + preConfigure = '' + ${args.preConfigure or ""} + sed -i 's|-I|-I${pkgs.gmp}/include -I|' scripts/gcc-plugin.sh + sed -i 's|HOST_EXTRACFLAGS +=|HOST_EXTRACFLAGS += -I${pkgs.gmp}/include|' tools/gcc/Makefile + sed -i 's|HOST_EXTRACXXFLAGS +=|HOST_EXTRACXXFLAGS += -I${pkgs.gmp}/include|' tools/gcc/Makefile + rm localversion-grsec + echo ${localver grkern} > localversion-grsec + ''; + }; + + mkGrsecKern = grkern: + lowPrio (overrideDerivation (grkern.kernel.override (args: { + kernelPatches = args.kernelPatches ++ [ grkern.patch pkgs.kernelPatches.grsec_fix_path ]; + argsOverride = { + modDirVersion = "${grkern.kernel.modDirVersion}${localver grkern}"; + }; + extraConfig = grsecConfig; + features.grsecurity = true; + })) (args: grsecurityOverrider args grkern)); + + mkGrsecPkg = grkern: pkgs.linuxPackagesFor grkern (mkGrsecPkg grkern); + + ## -- Kernel packages ------------------------------------------------------ + + grsecKernel = mkGrsecKern (if cfg.stable then stableKernel else testKernel); + grsecPackage = mkGrsecPkg grsecKernel; + }; +in vals diff --git a/pkgs/build-support/grsecurity/flavors.nix b/pkgs/build-support/grsecurity/flavors.nix new file mode 100644 index 000000000000..57d52e7cf943 --- /dev/null +++ b/pkgs/build-support/grsecurity/flavors.nix @@ -0,0 +1,32 @@ +let + mkOpts = ver: prio: sys: virt: swvirt: hwvirt: + { config.priority = prio; + config.system = sys; + config.virtualisationConfig = virt; + config.hardwareVirtualisation = hwvirt; + config.virtualisationSoftware = swvirt; + } // builtins.listToAttrs [ { name = ver; value = true; } ]; +in +{ + # Stable kernels + linux_grsec_stable_desktop = + mkOpts "stable" "performance" "desktop" "host" "kvm" true; + linux_grsec_stable_server = + mkOpts "stable" "security" "server" "host" "kvm" true; + linux_grsec_stable_server_xen = + mkOpts "stable" "security" "server" "guest" "xen" true; + + # Stable+vserver kernels - server versions only + linux_grsec_vserver_server = + mkOpts "vserver" "security" "server" "host" "kvm" true; + linux_grsec_vserver_server_xen = + mkOpts "vserver" "security" "server" "guest" "xen" true; + + # Testing kernels + linux_grsec_testing_desktop = + mkOpts "testing" "performance" "desktop" "host" "kvm" true; + linux_grsec_testing_server = + mkOpts "testing" "security" "server" "host" "kvm" true; + linux_grsec_testing_server_xen = + mkOpts "testing" "security" "server" "guest" "xen" true; +} \ No newline at end of file diff --git a/pkgs/os-specific/linux/kernel/common-config.nix b/pkgs/os-specific/linux/kernel/common-config.nix index 7f668c96bc52..3f623a66a512 100644 --- a/pkgs/os-specific/linux/kernel/common-config.nix +++ b/pkgs/os-specific/linux/kernel/common-config.nix @@ -167,7 +167,7 @@ with stdenv.lib; # Security related features. STRICT_DEVMEM y # Filter access to /dev/mem SECURITY_SELINUX_BOOTPARAM_VALUE 0 # Disable SELinux by default - DEVKMEM n # Disable /dev/kmem + DEVKMEM? n # Disable /dev/kmem ${if versionOlder version "3.14" then '' CC_STACKPROTECTOR y # Detect buffer overflows on the stack '' else '' diff --git a/pkgs/os-specific/linux/kernel/linux-3.2.nix b/pkgs/os-specific/linux/kernel/linux-3.2.nix index 4cb26a78abb1..1ff3b48676fc 100644 --- a/pkgs/os-specific/linux/kernel/linux-3.2.nix +++ b/pkgs/os-specific/linux/kernel/linux-3.2.nix @@ -12,7 +12,7 @@ import ./generic.nix (args // rec { # We don't provide these patches if grsecurity is enabled, because # the grsec 3.2 -stable patchset already includes them. kernelPatches = args.kernelPatches ++ ( - stdenv.lib.optional (!(args.features.grsecurity or false)) + stdenv.lib.optionals (!(args.features.grsecurity or false)) [ { name = "0001-AppArmor-compatibility-patch-for-v5-network-controll"; patch = ./apparmor-patches/3.2/0001-AppArmor-compatibility-patch-for-v5-network-controll.patch; } diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 77af3087b3d6..9252be00344c 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -7033,6 +7033,8 @@ let linuxConsoleTools = callPackage ../os-specific/linux/consoletools { }; + # -- Linux kernel expressions ------------------------------------------------ + linuxHeaders = linuxHeaders_3_7; linuxHeaders24Cross = forceNativeDrv (import ../os-specific/linux/kernel-headers/2.4.nix { @@ -7127,6 +7129,43 @@ let ]; }; + /* grsec configuration + + We build several flavors of 'default' grsec kernels. These are + built by default with Hydra. If the user selects a matching + 'default' flavor, then the pre-canned package set can be + chosen. Typically, users will make very basic choices like + 'security' + 'server' or 'performance' + 'desktop' with + virtualisation support. These will then be picked. + + Note: Xen guest kernels are included for e.g. NixOps deployments + to EC2, where Xen is the Hypervisor. + */ + + grFlavors = import ../build-support/grsecurity/flavors.nix; + + mkGrsecurity = opts: + (import ../build-support/grsecurity { + grsecOptions = opts; + inherit pkgs lib; + }); + + grKernel = opts: (mkGrsecurity opts).grsecKernel; + grPackage = opts: recurseIntoAttrs (mkGrsecurity opts).grsecPackage; + + # Stable kernels + linux_grsec_stable_desktop = grKernel grFlavors.linux_grsec_stable_desktop; + linux_grsec_stable_server = grKernel grFlavors.linux_grsec_stable_server; + linux_grsec_stable_server_xen = grKernel grFlavors.linux_grsec_stable_server_xen; + + # Stable+vserver kernels - server versions only + linux_grsec_vserver_server = grKernel grFlavors.linux_grsec_vserver_server; + linux_grsec_vserver_server_xen = grKernel grFlavors.linux_grsec_vserver_server_xen; + + # Testing kernels + linux_grsec_testing_desktop = grKernel grFlavors.linux_grsec_testing_desktop; + linux_grsec_testing_server = grKernel grFlavors.linux_grsec_testing_server; + linux_grsec_testing_server_xen = grKernel grFlavors.linux_grsec_testing_server_xen; /* Linux kernel modules are inherently tied to a specific kernel. So rather than provide specific instances of those packages for a @@ -7215,6 +7254,14 @@ let zfs_git = callPackage ../os-specific/linux/zfs/git.nix { }; }; + # The current default kernel / kernel modules. + linux = linuxPackages.kernel; + linuxPackages = linuxPackages_3_12; + + # Update this when adding the newest kernel major version! + linux_latest = pkgs.linux_3_14; + linuxPackages_latest = pkgs.linuxPackages_3_14; + # Build the kernel modules for the some of the kernels. linuxPackages_3_2 = recurseIntoAttrs (linuxPackagesFor pkgs.linux_3_2 linuxPackages_3_2); linuxPackages_3_2_xen = linuxPackagesFor pkgs.linux_3_2_xen linuxPackages_3_2_xen; @@ -7225,12 +7272,21 @@ let linuxPackages_3_12 = recurseIntoAttrs (linuxPackagesFor pkgs.linux_3_12 linuxPackages_3_12); linuxPackages_3_13 = recurseIntoAttrs (linuxPackagesFor pkgs.linux_3_13 linuxPackages_3_13); linuxPackages_3_14 = recurseIntoAttrs (linuxPackagesFor pkgs.linux_3_14 linuxPackages_3_14); - # Update this when adding a new version! - linuxPackages_latest = pkgs.linuxPackages_3_14; - # The current default kernel / kernel modules. - linux = linuxPackages.kernel; - linuxPackages = linuxPackages_3_12; + # grsecurity flavors + # Stable kernels + linuxPackages_grsec_stable_desktop = grPackage grFlavors.linux_grsec_stable_desktop; + linuxPackages_grsec_stable_server = grPackage grFlavors.linux_grsec_stable_server; + linuxPackages_grsec_stable_server_xen = grPackage grFlavors.linux_grsec_stable_server_xen; + + # Stable+vserver kernels - server versions only + linuxPackages_grsec_vserver_server = grPackage grFlavors.linux_grsec_vserver_server; + linuxPackages_grsec_vserver_server_xen = grPackage grFlavors.linux_grsec_vserver_server_xen; + + # Testing kernels + linuxPackages_grsec_testing_desktop = grPackage grFlavors.linux_grsec_testing_desktop; + linuxPackages_grsec_testing_server = grPackage grFlavors.linux_grsec_testing_server; + linuxPackages_grsec_testing_server_xen = grPackage grFlavors.linux_grsec_testing_server_xen; # A function to build a manually-configured kernel linuxManualConfig = pkgs.buildLinux;