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 <aseipp@pobox.com>
This commit is contained in:
Austin Seipp 2014-05-14 12:04:40 -05:00
parent cb894d4fc3
commit 4f27ad14a1
6 changed files with 252 additions and 128 deletions

View File

@ -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 = {

View File

@ -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

View File

@ -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;
}

View File

@ -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 ''

View File

@ -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;
}

View File

@ -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;