Refactor grsecurity support.

Nota bene: this probably does not work! Caveat emptor, etc.

This inverts the grsecurity builder, making it much simpler. Instead,
users just give a full description of the type of kernel they want to
build, and the result is an attribute set containing kernel and
kernelPackages results.

Now, in order to build a custom grsecurity kernel, you do something more
like:

    let
      kver  = "4.0.4";
      grver = "3.1-${kver}-201505222222";

      kernel = rec
        { version  = kver;
          localver = "-grsec";
          src      = fetchurl rec {
            name  = "linux-${kver}.tar.xz";
            url   = "mirror://kernel/linux/kernel/v4.x/${name}.tar.xz";
            sha256 = "1j5l87z6gd05cqzg680id0x1nk38kd6sjffd2lifl0fz5k6iqr9h";
        };
      };

      patches =
        [ fetchurl rec {
            name   = "grsecurity-${grver}.patch";
            url    = "https://grsecurity.net/test/grsecurity-${grver}.patch";
            sha256 = "0ampby10y3kr36f7rvzm5fdk9f2gcfmcdgkzf67b5kj78y52ypfz";
          }
        ];

      customGrsecKern = customGrsecKernelPackages { inherit kernel patches; };
    in
    {
      ...
      boot.kernelPackages = customGrsecKern.kernelPackages;
    }

Which is far more flexible and easier to think about; plus, it gives
full control over the kernel localver and modDirVer, as well as support
for other patches (because you may have other patches to apply on-top of
grsec, or you may bundle grsec with some other distribution, and still
need the builder support.) It also gives you full control of the kernel
tarball, in case you want to use e.g. libre-linux.

Signed-off-by: Austin Seipp <aseipp@pobox.com>
This commit is contained in:
Austin Seipp 2015-04-13 20:03:20 -05:00
parent 74d867e95c
commit 26fa60ac55
4 changed files with 71 additions and 192 deletions

View File

@ -4,12 +4,6 @@ with lib;
let let
cfg = config.security.grsecurity; cfg = config.security.grsecurity;
customGrsecPkg =
(import ../../../pkgs/build-support/grsecurity {
grsecOptions = cfg;
inherit pkgs lib;
}).grsecPackage;
in in
{ {
options = { options = {
@ -18,14 +12,24 @@ in
type = types.bool; type = types.bool;
default = false; default = false;
description = '' description = ''
Enable grsecurity support. This enables advanced exploit Enable grsecurity support system-wide. This enables advanced exploit
hardening for the Linux kernel, and adds support for hardening for the Linux kernel, and adds support for
administrative Role-Based Acess Control (RBAC) via administrative Role-Based Acess Control (RBAC) via
<literal>gradm</literal>. It also includes traditional <literal>gradm</literal>. It also includes traditional
utilities for PaX. utilities for PaX, and more.
''; '';
}; };
kernelPackages = mkOption {
type = types.package;
description = ''
The kernel package set to use. In order to
understand how to set this option appropriately, please see
the NixOS wiki: TODO FIXME.
'';
};
/*
stable = mkOption { stable = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
@ -214,10 +218,12 @@ in
description = "Extra kernel configuration parameters."; description = "Extra kernel configuration parameters.";
}; };
}; };
*/
}; };
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
/*
assertions = assertions =
[ { assertion = cfg.stable || cfg.testing; [ { assertion = cfg.stable || cfg.testing;
message = '' message = ''
@ -246,6 +252,7 @@ in
message = "grsecurity configured for virtualisation but no virtualisation software specified"; message = "grsecurity configured for virtualisation but no virtualisation software specified";
} }
]; ];
*/
systemd.services.grsec-lock = mkIf cfg.config.sysctl { systemd.services.grsec-lock = mkIf cfg.config.sysctl {
description = "grsecurity sysctl-lock Service"; description = "grsecurity sysctl-lock Service";
@ -287,10 +294,9 @@ in
chmod -R 0600 /etc/grsec chmod -R 0600 /etc/grsec
''; }; ''; };
# Enable AppArmor, gradm udev rules, and utilities # Enable gradm udev rules and utilities
security.apparmor.enable = true; boot.kernelPackages = cfg.kernelPackages;
boot.kernelPackages = customGrsecPkg; services.udev.packages = [ pkgs.gradm ];
services.udev.packages = lib.optional (!cfg.config.disableRBAC) pkgs.gradm; environment.systemPackages = [ pkgs.paxctl pkgs.pax-utils pkgs.gradm ];
environment.systemPackages = [ pkgs.paxctl pkgs.pax-utils ] ++ lib.optional (!cfg.config.disableRBAC) pkgs.gradm;
}; };
} }

View File

@ -1,126 +1,38 @@
{ grsecOptions, lib, pkgs }: { pkgs, lib, ... }:
with pkgs;
with lib; with lib;
let let
cfg = { grsec_path_patch = { name "grsec-path"; patch = ./grsec-path.patch; };
stable = grsecOptions.stable or false; genericKernelBuilder = import ../../os-specific/linux/kernel/generic.nix;
testing = grsecOptions.testing or false;
config = {
mode = "auto";
sysctl = false;
denyChrootChmod = false;
denyUSB = 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; grsecurity_stable;
grKernel = if cfg.stable
then mkKernel pkgs.linux_3_14 stable-patch
else mkKernel pkgs.linux_3_19 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 == null 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 == null 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 in
if cfg.config.virtualisationConfig == null then "" {
else if cfg.config.virtualisationSoftware == "xen" then virtCfg "XEN" customGrsecKernelPackages = p:
else if cfg.config.virtualisationSoftware == "kvm" then virtCfg "KVM" let
else if cfg.config.virtualisationSoftware == "vmware" then virtCfg "VMWARE" version = p.kernel.version;
else virtCfg "VIRTUALBOX"; localver = p.kernel.localver or "";
modDirVersion = p.kernel.modDirVersion or (version+localver);
features = p.kernel.features or {};
src = with p.kernel; fetchurl { inherit url sha256; };
grsecMainConfig = if cfg.config.mode == "custom" then "" else '' kernel = overrideDerivation (genericKernelBuilder (rec {
GRKERNSEC_CONFIG_AUTO y inherit version modDirVersion src;
${grsecPrioCfg}
${grsecSystemCfg}
${grsecVirtCfg}
${grsecHwvirtCfg}
${grsecVirtswCfg}
'';
grsecConfig = /* Add any 'quirky' patches (like bridge_stp_helper and
let boolToKernOpt = b: if b then "y" else "n"; * grsec_path_patch, which fix NixOS-specific quirks) plus the ones
# Disable RANDSTRUCT under virtualbox, as it has some kind of * the user specified. */
# breakage with the vbox guest drivers kernelPatches = [ grsec_path_patch
#randstruct = optionalString config.services.virtualboxGuest.enable kernelPatches.bridge_stp_helper
# "GRKERNSEC_RANDSTRUCT n"; ] ++ (map fetchurl p.patches);
# Disable restricting links under the testing kernel, as something /* Default features */
# has changed causing it to fail miserably during boot. features.iwlwifi = true;
restrictLinks = optionalString cfg.testing features.efiBootStub = true;
"GRKERNSEC_LINK n"; features.needsCifsUtils = true;
in '' features.canDisableNetfilterConntrackHelpers = true;
GRKERNSEC y features.netfilterRPFilter = true;
${grsecMainConfig} })) (args: {
${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_DENYUSB ${boolToKernOpt cfg.config.denyUSB}
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) # Apparently as of gcc 4.6, gcc-plugin headers (which are needed by PaX plugins)
# include libgmp headers, so we need these extra tweaks # include libgmp headers, so we need these extra tweaks
buildInputs = args.buildInputs ++ [ pkgs.gmp ]; buildInputs = args.buildInputs ++ [ pkgs.gmp ];
@ -130,25 +42,15 @@ let
sed -i 's|HOST_EXTRACFLAGS +=|HOST_EXTRACFLAGS += -I${pkgs.gmp}/include|' tools/gcc/Makefile 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 sed -i 's|HOST_EXTRACXXFLAGS +=|HOST_EXTRACXXFLAGS += -I${pkgs.gmp}/include|' tools/gcc/Makefile
rm localversion-grsec rm localversion-grsec
echo ${localver grkern} > localversion-grsec ${if localver == "" then "" else ''
echo ${localver} > localversion-nix
''}
''; '';
}) // features;
kernelPackages = let self = linuxPackagesFor kernel self; in recurseIntoAttrs self;
in {
inherit kernel;
inherit kernelPackages;
}; };
}
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 grKernel;
grsecPackage = mkGrsecPkg grsecKernel;
};
in vals

View File

@ -1,16 +1,6 @@
{ stdenv, fetchurl }: { stdenv, fetchurl }:
let let
grsecPatch = { grversion ? "3.1", 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;
};
patches = rec { patches = rec {
btrfs_fix_deadlock = btrfs_fix_deadlock =
{ name = "btrfs-fix-deadlock"; { name = "btrfs-fix-deadlock";
@ -21,24 +11,5 @@ let
{ name = "bridge-stp-helper"; { name = "bridge-stp-helper";
patch = ./patches/bridge-stp-helper.patch; patch = ./patches/bridge-stp-helper.patch;
}; };
grsec_fix_path =
{ name = "grsec-fix-path";
patch = ./patches/grsec-path.patch;
};
grsecurity_stable = grsecPatch
{ kversion = "3.14.37";
revision = "201504051405";
branch = "stable";
sha256 = "0w1rz5g4wwd22ivii7m7qjgakdynzjwpqxiydx51kiw5j0avkzs3";
};
grsecurity_unstable = grsecPatch
{ kversion = "3.19.3";
revision = "201504021826";
branch = "test";
sha256 = "0r3gsha4x9bkzg9n4rcwzi9f3hkbqrf8yga1dd83kyd10fns4lzm";
};
}; };
in patches in patches