nixpkgs/nixos/modules/security/grsecurity.nix
Austin Seipp 26fa60ac55 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>
2015-05-25 10:58:26 -05:00

303 lines
10 KiB
Nix

{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.security.grsecurity;
in
{
options = {
security.grsecurity = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Enable grsecurity support system-wide. 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, 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 {
type = types.bool;
default = false;
description = ''
Enable the stable grsecurity patch, based on Linux 3.14.
'';
};
testing = mkOption {
type = types.bool;
default = false;
description = ''
Enable the testing grsecurity patch, based on Linux 3.19.
'';
};
config = {
mode = mkOption {
type = types.enum [ "auto" "custom" ];
default = "auto";
description = ''
grsecurity configuration mode. This specifies whether
grsecurity is auto-configured or otherwise completely
manually configured.
'';
};
priority = mkOption {
type = types.enum [ "security" "performance" ];
default = "security";
description = ''
grsecurity configuration priority. This specifies whether
the kernel configuration should emphasize speed or
security.
'';
};
system = mkOption {
type = types.enum [ "desktop" "server" ];
default = "desktop";
description = ''
grsecurity system configuration.
'';
};
virtualisationConfig = mkOption {
type = types.nullOr (types.enum [ "host" "guest" ]);
default = null;
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.
'';
};
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.nullOr (types.enum [ "kvm" "xen" "vmware" "virtualbox" ]);
default = null;
description = ''
Configure grsecurity for use with this virtualisation software.
'';
};
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*!
'';
};
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.
'';
};
denyUSB = mkOption {
type = types.bool;
default = false;
description = ''
If true, then set <literal>GRKERNSEC_DENYUSB y</literal>.
This enables a sysctl with name
<literal>kernel.grsecurity.deny_new_usb</literal>. Setting
its value to <literal>1</literal> will prevent any new USB
devices from being recognized by the OS. Any attempted
USB device insertion will be logged.
This option is intended to be used against custom USB
devices designed to exploit vulnerabilities in various USB
device drivers.
'';
};
restrictProc = mkOption {
type = types.bool;
default = false;
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.
'';
};
restrictProcWithGroup = mkOption {
type = types.bool;
default = true;
description = ''
If true, then set <literal>GRKERN_PROC_USERGROUP
y</literal>. This is similar to
<literal>restrictProc</literal> except it allows a special
group (specified by <literal>unrestrictProcGid</literal>)
to still access otherwise classified information in
<literal>/proc</literal>.
'';
};
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_USERGROUP</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.14), or the testing patch (with
kernel 3.19) to continue.
'';
}
{ assertion = !(cfg.stable && cfg.testing);
message = "Select either one of the stable or testing patch";
}
{ assertion = (cfg.config.restrictProc -> !cfg.config.restrictProcWithGroup) ||
(cfg.config.restrictProcWithGroup -> !cfg.config.restrictProc);
message = "You cannot enable both restrictProc and restrictProcWithGroup";
}
{ assertion = config.boot.kernelPackages.kernel.features ? grsecurity
&& config.boot.kernelPackages.kernel.features.grsecurity;
message = "grsecurity enabled, but kernel doesn't have grsec support";
}
{ assertion = (cfg.config.mode == "auto" && (cfg.config.virtualisationConfig != null)) ->
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" && (cfg.config.virtualisationConfig != null)) ->
cfg.config.virtualisationSoftware != null;
message = "grsecurity configured for virtualisation but no virtualisation software specified";
}
];
*/
systemd.services.grsec-lock = mkIf cfg.config.sysctl {
description = "grsecurity sysctl-lock Service";
requires = [ "systemd-sysctl.service" ];
wantedBy = [ "multi-user.target" ];
serviceConfig.Type = "oneshot";
serviceConfig.RemainAfterExit = "yes";
unitConfig.ConditionPathIsReadWrite = "/proc/sys/kernel/grsecurity/grsec_lock";
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 = lib.optionalAttrs (!cfg.config.disableRBAC) { 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 gradm udev rules and utilities
boot.kernelPackages = cfg.kernelPackages;
services.udev.packages = [ pkgs.gradm ];
environment.systemPackages = [ pkgs.paxctl pkgs.pax-utils pkgs.gradm ];
};
}