nixos: add grsecurity module (#1875)

This module implements a significant refactoring in grsecurity
configuration for NixOS, making it far more usable by default and much
easier to configure.

 - New security.grsecurity NixOS attributes.
   - All grsec kernels supported
   - Allows default 'auto' grsec configuration, or custom config
   - Supports custom kernel options through kernelExtraConfig
   - Defaults to high-security - user must choose kernel, server/desktop
     mode, and any virtualisation software. That's all.
   - kptr_restrict is fixed under grsecurity (it's unwriteable)
 - grsecurity patch creation is now significantly abstracted
   - only need revision, version, and SHA1
   - kernel version requirements are asserted for sanity
   - built kernels can have the uname specify the exact grsec version
     for development or bug reports. Off by default (requires
     `security.grsecurity.config.verboseVersion = true;`)
 - grsecurity sysctl support
   - By default, disabled.
   - For people who enable it, NixOS deploys a 'grsec-lock' systemd
     service which runs at startup. You are expected to configure sysctl
     through NixOS like you regularly would, which will occur before the
     service is started. As a result, changing sysctl settings requires
     a reboot.
 - New default group: 'grsecurity'
   - Root is a member by default
   - GRKERNSEC_PROC_GID is implicitly set to the 'grsecurity' GID,
     making it possible to easily add users to this group for /proc
     access
 - AppArmor is now automatically enabled where it wasn't before, despite
   implying features.apparmor = true

The most trivial example of enabling grsecurity in your kernel is by
specifying:

    security.grsecurity.enable          = true;
    security.grsecurity.testing         = true;      # testing 3.13 kernel
    security.grsecurity.config.system   = "desktop"; # or "server"

This specifies absolutely no virtualisation support. In general, you
probably at least want KVM host support, which is a little more work.
So:

    security.grsecurity.enable = true;
    security.grsecurity.stable = true; # enable stable 3.2 kernel
    security.grsecurity.config = {
      system   = "server";
      priority = "security";
      virtualisationConfig   = "host";
      virtualisationSoftware = "kvm";
      hardwareVirtualisation = true;
    }

This module has primarily been tested on Hetzner EX40 & VQ7 servers
using NixOps.

Signed-off-by: Austin Seipp <aseipp@pobox.com>
This commit is contained in:
Austin Seipp 2014-04-06 14:18:12 -05:00
parent cf24cf1184
commit 172dc1336f
7 changed files with 468 additions and 63 deletions

View file

@ -6,7 +6,7 @@ let
sysctlOption = mkOptionType {
name = "sysctl option value";
check = x: isBool x || isString x || isInt x;
check = x: isBool x || isString x || isInt x || isNull x;
merge = args: defs: (last defs).value; # FIXME: hacky way to allow overriding in configuration.nix.
};
@ -29,8 +29,9 @@ in
<manvolnum>8</manvolnum></citerefentry>. Note that sysctl
parameters names must be enclosed in quotes
(e.g. <literal>"vm.swappiness"</literal> instead of
<literal>vm.swappiness</literal>). The value of each parameter
may be a string, integer or Boolean.
<literal>vm.swappiness</literal>). The value of each
parameter may be a string, integer, boolean, or null
(signifying the option will not appear at all).
'';
};
@ -39,7 +40,9 @@ in
config = {
environment.etc."sysctl.d/nixos.conf".text =
concatStrings (mapAttrsToList (n: v: "${n}=${if v == false then "0" else toString v}\n") config.boot.kernel.sysctl);
concatStrings (mapAttrsToList (n: v:
optionalString (v != null) "${n}=${if v == false then "0" else toString v}\n"
) config.boot.kernel.sysctl);
systemd.services.systemd-sysctl =
{ description = "Apply Kernel Variables";
@ -65,8 +68,9 @@ in
# Hide kernel pointers (e.g. in /proc/modules) for unprivileged
# users as these make it easier to exploit kernel vulnerabilities.
boot.kernel.sysctl."kernel.kptr_restrict" = 1;
#
# Removed under grsecurity.
boot.kernel.sysctl."kernel.kptr_restrict" =
if config.security.grsecurity.enable then null else 1;
};
}

View file

@ -392,6 +392,7 @@ in {
home = "/root";
shell = cfg.defaultUserShell;
group = "root";
extraGroups = [ "grsecurity" ];
hashedPassword = mkDefault config.security.initialRootPassword;
};
nobody = {
@ -420,6 +421,7 @@ in {
nixbld.gid = ids.gids.nixbld;
utmp.gid = ids.gids.utmp;
adm.gid = ids.gids.adm;
grsecurity.gid = ids.gids.grsecurity;
};
system.activationScripts.users =

View file

@ -231,6 +231,7 @@
foundationdb = 118;
newrelic = 119;
starbound = 120;
grsecurity = 121;
# When adding a gid, make sure it doesn't match an existing uid.

View file

@ -62,6 +62,7 @@
./security/apparmor-suid.nix
./security/ca.nix
./security/duosec.nix
./security/grsecurity.nix
./security/pam.nix
./security/pam_usb.nix
./security/polkit.nix

View file

@ -0,0 +1,421 @@
{ config, pkgs, ... }:
with pkgs.lib;
let
cfg = config.security.grsecurity;
mkKernel = kernel: patch:
assert patch.kversion == kernel.version;
{ inherit kernel patch;
inherit (patch) grversion revision;
};
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_13 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 ''
SECURITY_APPARMOR y
DEFAULT_SECURITY_APPARMOR y
GRKERNSEC y
${grsecMainConfig}
GRKERNSEC_PROC_USER ${boolToKernOpt cfg.config.restrictProc}
${if !cfg.config.restrictProc then ""
else "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);
in
{
options = {
security.grsecurity = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Enable grsecurity support. This enables advanced exploit
hardening for the Linux kernel, and adds support for
administrative Role-Based Acess Control (RBAC) via
<literal>gradm</literal>. It also includes traditional
utilities for PaX.
'';
};
stable = mkOption {
type = types.bool;
default = false;
description = ''
Enable the stable grsecurity patch, based on Linux 3.2.
'';
};
vserver = mkOption {
type = types.bool;
default = false;
description = ''
Enable the stable grsecurity/vserver patches, based on Linux 3.2.
'';
};
testing = mkOption {
type = types.bool;
default = false;
description = ''
Enable the testing grsecurity patch, based on Linux 3.13.
'';
};
config = {
mode = mkOption {
type = types.str;
default = "auto";
example = "custom";
description = ''
grsecurity configuration mode. This specifies whether
grsecurity is auto-configured or otherwise completely
manually configured. Can either by
<literal>custom</literal> or <literal>auto</literal>.
<literal>auto</literal> is recommended.
'';
};
priority = mkOption {
type = types.str;
default = "security";
example = "performance";
description = ''
grsecurity configuration priority. This specifies whether
the kernel configuration should emphasize speed or
security. Can either by <literal>security</literal> or
<literal>performance</literal>.
'';
};
system = mkOption {
type = types.str;
default = "";
example = "desktop";
description = ''
grsecurity system configuration. This specifies whether
the kernel configuration should be suitable for a Desktop
or a Server. Can either by <literal>server</literal> or
<literal>desktop</literal>.
'';
};
virtualisationConfig = mkOption {
type = types.str;
default = "none";
example = "host";
description = ''
grsecurity virtualisation configuration. This specifies
the virtualisation role of the machine - that is, whether
it will be a virtual machine guest, a virtual machine
host, or neither. Can be one of <literal>none</literal>,
<literal>host</literal>, or <literal>guest</literal>.
'';
};
hardwareVirtualisation = mkOption {
type = types.nullOr types.bool;
default = null;
example = true;
description = ''
grsecurity hardware virtualisation configuration. Set to
<literal>true</literal> if your machine supports hardware
accelerated virtualisation.
'';
};
virtualisationSoftware = mkOption {
type = types.str;
default = "";
example = "kvm";
description = ''
grsecurity virtualisation software. Set this to the
specified virtual machine technology if the machine is
running as a guest, or a host.
Can be one of <literal>kvm</literal>,
<literal>xen</literal>, <literal>vmware</literal> or
<literal>virtualbox</literal>.
'';
};
sysctl = mkOption {
type = types.bool;
default = false;
description = ''
If true, then set <literal>GRKERN_SYSCTL y</literal>. If
enabled then grsecurity can be controlled using sysctl
(and turned off). You are advised to *never* enable this,
but if you do, make sure to always set the sysctl
<literal>kernel.grsecurity.grsec_lock</literal> to
non-zero as soon as all sysctl options are set. *THIS IS
EXTREMELY IMPORTANT*!
If disabled, this also turns off the
<literal>systemd-sysctl</literal> service.
'';
};
denyChrootChmod = mkOption {
type = types.bool;
default = false;
description = ''
If true, then set <literal>GRKERN_CHROOT_CHMOD
y</literal>. If enabled, this denies processes inside a
chroot from setting the suid or sgid bits using
<literal>chmod</literal> or <literal>fchmod</literal>.
By default this protection is disabled - it makes it
impossible to use Nix to build software on your system,
which is what most users want.
If you are using NixOps to deploy your software to a
remote machine, you're encouraged to enable this as you
won't need to compile code.
'';
};
restrictProc = mkOption {
type = types.bool;
default = true;
description = ''
If true, then set <literal>GRKERN_PROC_USER
y</literal>. This restricts non-root users to only viewing
their own processes and restricts network-related
information, kernel symbols, and module information.
'';
};
unrestrictProcGid = mkOption {
type = types.int;
default = config.ids.gids.grsecurity;
description = ''
If set, specifies a GID which is exempt from
<literal>/proc</literal> restrictions (set by
<literal>GRKERN_PROC_USER</literal>). By default, this is
set to the GID for <literal>grsecurity</literal>, a
predefined NixOS group, which the <literal>root</literal>
account is a member of. You may conveniently add other
users to this group if you need access to
<literal>/proc</literal>
'';
};
disableRBAC = mkOption {
type = types.bool;
default = false;
description = ''
If true, then set <literal>GRKERN_NO_RBAC
y</literal>. This disables the
<literal>/dev/grsec</literal> device, which in turn
disables the RBAC system (and <literal>gradm</literal>).
'';
};
verboseVersion = mkOption {
type = types.bool;
default = false;
description = "Use verbose version in kernel localversion.";
};
kernelExtraConfig = mkOption {
type = types.str;
default = "";
description = "Extra kernel configuration parameters.";
};
};
};
};
config = mkIf cfg.enable {
assertions =
[ { assertion = cfg.stable || cfg.testing;
message = ''
If grsecurity is enabled, you must select either the
stable patch (with kernel 3.2), or the testing patch (with
kernel 3.13) to continue.
'';
}
{ assertion = (cfg.stable -> !cfg.testing) || (cfg.testing -> !cfg.stable);
message = ''
You must select either the stable or testing patch, not
both.
'';
}
{ assertion = (cfg.testing -> !cfg.vserver);
message = "The vserver patches are only supported in the stable kernel.";
}
{ assertion = config.boot.kernelPackages.kernel.features ? grsecurity
&& config.boot.kernelPackages.kernel.features.grsecurity;
message = "grsecurity enabled, but kernel doesn't have grsec support";
}
{ assertion = elem cfg.config.mode [ "auto" "custom" ];
message = "grsecurity mode must either be 'auto' or 'custom'.";
}
{ assertion = cfg.config.mode == "auto" -> elem cfg.config.system [ "desktop" "server" ];
message = "when using auto grsec mode, system must be either 'desktop' or 'server'";
}
{ assertion = cfg.config.mode == "auto" -> elem cfg.config.priority [ "performance" "security" ];
message = "when using auto grsec mode, priority must be 'performance' or 'security'.";
}
{ assertion = cfg.config.mode == "auto" -> elem cfg.config.virtualisationConfig [ "host" "guest" "none" ];
message = "when using auto grsec mode, 'virt' must be 'host', 'guest' or 'none'.";
}
{ assertion = (cfg.config.mode == "auto" && (elem cfg.config.virtualisationConfig [ "host" "guest" ])) ->
cfg.config.hardwareVirtualisation != null;
message = "when using auto grsec mode with virtualisation, you must specify if your hardware has virtualisation extensions";
}
{ assertion = (cfg.config.mode == "auto" && (elem cfg.config.virtualisationConfig [ "host" "guest" ])) ->
elem cfg.config.virtualisationSoftware [ "kvm" "xen" "virtualbox" "vmware" ];
message = "virtualisation software must be 'kvm', 'xen', 'vmware' or 'virtualbox'";
}
];
systemd.services.grsec-lock = mkIf cfg.config.sysctl {
description = "grsecurity sysctl-lock Service";
requires = [ "sysctl.service" ];
wantedBy = [ "multi-user.target" ];
serviceConfig.Type = "oneshot";
serviceConfig.RemainAfterExit = "yes";
script = ''
locked=`cat /proc/sys/kernel/grsecurity/grsec_lock`
if [ "$locked" == "0" ]; then
echo 1 > /proc/sys/kernel/grsecurity/grsec_lock
echo grsecurity sysctl lock - enabled
else
echo grsecurity sysctl lock already enabled - doing nothing
fi
'';
};
# systemd.services.grsec-learn = {
# description = "grsecurity learning Service";
# wantedBy = [ "local-fs.target" ];
# serviceConfig = {
# Type = "oneshot";
# RemainAfterExit = "yes";
# ExecStart = "${pkgs.gradm}/sbin/gradm -VFL /etc/grsec/learning.logs";
# ExecStop = "${pkgs.gradm}/sbin/gradm -D";
# };
# };
system.activationScripts.grsec =
''
mkdir -p /etc/grsec
if [ ! -f /etc/grsec/learn_config ]; then
cp ${pkgs.gradm}/etc/grsec/learn_config /etc/grsec
fi
if [ ! -f /etc/grsec/policy ]; then
cp ${pkgs.gradm}/etc/grsec/policy /etc/grsec
fi
chmod -R 0600 /etc/grsec
'';
# Enable apparmor support, gradm udev rules, and utilities
security.apparmor.enable = true;
boot.kernelPackages = grsecPackage;
services.udev.packages = [ pkgs.gradm ];
environment.systemPackages = [ pkgs.gradm pkgs.paxctl pkgs.pax-utils ];
};
}

View file

@ -18,6 +18,18 @@ let
};
};
grsecPatch = { grversion ? "3.0", kversion, revision, branch, sha256 }:
{ name = "grsecurity-${grversion}-${kversion}";
inherit grversion kversion revision;
patch = fetchurl {
url = "http://grsecurity.net/${branch}/grsecurity-${grversion}-${kversion}-${revision}.patch";
inherit sha256;
};
features.grsecurity = true;
# The grsec kernel patchset includes AppArmor patches
features.apparmor = true;
};
makeAppArmorPatch = {apparmor, version}:
stdenv.mkDerivation {
name = "apparmor-${version}.patch";
@ -26,6 +38,7 @@ let
cat ${apparmor}/kernel-patches/${version}/* > $out
'';
};
in
rec {
@ -71,31 +84,29 @@ rec {
sha256 = "00b1rqgd4yr206dxp4mcymr56ymbjcjfa4m82pxw73khj032qw3j";
};
grsecurity_3_0_3_2_57 =
{ name = "grsecurity-3.0-3.2.57";
patch = fetchurl {
url = http://grsecurity.net/stable/grsecurity-3.0-3.2.57-201404091758.patch;
sha256 = "07rswg6vqyak9ccan954izx1fr0c6c6fn8whlzl0787dabpai3i3";
};
features.grsecurity = true;
# The grsec kernel patch seems to include the apparmor patches as of 3.0-3.2.57
features.apparmor = true;
grsecurity_stable = grsecPatch
{ kversion = "3.2.57";
revision = "201404111812";
branch = "stable";
sha256 = "1kp2f5g5jdl6r833fm5l2sgf7qsjddl2br7mislc37iqgwzjmhlx";
};
grsecurity_3_0_3_13_9 =
{ name = "grsecurity-3.0-3.13.9";
patch = fetchurl {
url = http://grsecurity.net/test/grsecurity-3.0-3.13.9-201404062127.patch;
sha256 = "0kwqgw2a44wqhwjwws63ww15apb8jki372iccq7h1w5vi551sl0m";
};
features.grsecurity = true;
# The grsec kernel patch seems to include the apparmor patches as of 3.0-3.13.9
features.apparmor = true;
grsecurity_vserver = grsecPatch
{ kversion = "3.2.57";
revision = "vs2.3.2.16-201404111814";
branch = "vserver";
sha256 = "025kxk4j8kx7v5gmpafls67747l39ssfmzh0drg0hyg2yc0hjk2c";
};
grsec_path =
{ name = "grsec-path";
grsecurity_unstable = grsecPatch
{ kversion = "3.13.9";
revision = "201404111815";
branch = "test";
sha256 = "1ikqvi0hv32m5rgxa8dpqr5v84hx7bnjfr6c1bvsfqikc818isvy";
};
grsec_fix_path =
{ name = "grsec-fix-path";
patch = ./grsec-path.patch;
};
}

View file

@ -6907,39 +6907,6 @@ let
kernelPatches = [];
};
grsecurityOverrider = args: {
# 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 ++ [ gmp ];
preConfigure = ''
${args.preConfigure or ""}
sed -i 's|-I|-I${gmp}/include -I|' scripts/gcc-plugin.sh
sed -i 's|HOST_EXTRACFLAGS +=|HOST_EXTRACFLAGS += -I${gmp}/include|' tools/gcc/Makefile
sed -i 's|HOST_EXTRACXXFLAGS +=|HOST_EXTRACXXFLAGS += -I${gmp}/include|' tools/gcc/Makefile
'';
};
# Note: grsec is not enabled automatically, you need to specify which kernel
# config options you need (e.g. by overriding extraConfig). See list of options here:
# https://en.wikibooks.org/wiki/Grsecurity/Appendix/Grsecurity_and_PaX_Configuration_Options
linux_3_2_grsecurity = lowPrio (lib.addMetaAttrs {
maintainers = with lib.maintainers; [ wizeman thoughtpolice ];
} (lib.overrideDerivation (linux_3_2.override (args: {
kernelPatches = args.kernelPatches ++ [ kernelPatches.grsecurity_3_0_3_2_57 kernelPatches.grsec_path ];
argsOverride = {
modDirVersion = "${linux_3_2.modDirVersion}-grsec";
};
})) (args: grsecurityOverrider args)));
linux_3_13_grsecurity = lowPrio (lib.addMetaAttrs {
maintainers = with lib.maintainers; [ wizeman thoughtpolice ];
} (lib.overrideDerivation (linux_3_13.override (args: {
kernelPatches = args.kernelPatches ++ [ kernelPatches.grsecurity_3_0_3_13_9 kernelPatches.grsec_path ];
argsOverride = {
modDirVersion = "${linux_3_13.modDirVersion}-grsec";
};
})) (args: grsecurityOverrider args)));
linux_3_2_apparmor = lowPrio (linux_3_2.override {
kernelPatches = [ kernelPatches.apparmor_3_2 ];
extraConfig = ''
@ -7104,7 +7071,6 @@ let
# 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_apparmor = linuxPackagesFor pkgs.linux_3_2_apparmor linuxPackages_3_2_apparmor;
linuxPackages_3_2_grsecurity = linuxPackagesFor pkgs.linux_3_2_grsecurity linuxPackages_3_2_grsecurity;
linuxPackages_3_2_xen = linuxPackagesFor pkgs.linux_3_2_xen linuxPackages_3_2_xen;
linuxPackages_3_4 = recurseIntoAttrs (linuxPackagesFor pkgs.linux_3_4 linuxPackages_3_4);
linuxPackages_3_4_apparmor = linuxPackagesFor pkgs.linux_3_4_apparmor linuxPackages_3_4_apparmor;
@ -7112,7 +7078,6 @@ let
linuxPackages_3_10 = recurseIntoAttrs (linuxPackagesFor pkgs.linux_3_10 linuxPackages_3_10);
linuxPackages_3_10_tuxonice = linuxPackagesFor pkgs.linux_3_10_tuxonice linuxPackages_3_10_tuxonice;
linuxPackages_3_12 = recurseIntoAttrs (linuxPackagesFor pkgs.linux_3_12 linuxPackages_3_12);
linuxPackages_3_13_grsecurity = linuxPackagesFor pkgs.linux_3_13_grsecurity linuxPackages_3_13_grsecurity;
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!