···
-
<chapter xmlns="http://docbook.org/ns/docbook"
-
xmlns:xlink="http://www.w3.org/1999/xlink"
-
xmlns:xi="http://www.w3.org/2001/XInclude"
-
xml:id="sec-grsecurity">
-
<title>Grsecurity/PaX</title>
-
Grsecurity/PaX is a set of patches against the Linux kernel that
-
implements an extensive suite of
-
<link xlink:href="https://grsecurity.net/features.php">features</link>
-
designed to increase the difficulty of exploiting kernel and
-
The NixOS grsecurity/PaX module is designed with casual users in mind and is
-
intended to be compatible with normal desktop usage, without
-
<emphasis>unnecessarily</emphasis> compromising security. The
-
following sections describe the configuration and administration of
-
a grsecurity/PaX enabled NixOS system. For more comprehensive
-
coverage, please refer to the
-
<link xlink:href="https://en.wikibooks.org/wiki/Grsecurity">grsecurity wikibook</link>
-
<link xlink:href="https://wiki.archlinux.org/index.php/Grsecurity">Arch
-
Linux wiki page on grsecurity</link>.
-
<warning><para>Upstream has ceased free support for grsecurity/PaX. See
-
<link xlink:href="https://grsecurity.net/passing_the_baton.php">
-
the announcement</link> for more information. Consequently, NixOS
-
support for grsecurity/PaX also must cease. Enabling this module will
-
result in a build error.</para></warning>
-
<note><para>We standardise on a desktop oriented configuration primarily due
-
to lack of resources. The grsecurity/PaX configuration state space is huge
-
and each configuration requires quite a bit of testing to ensure that the
-
resulting packages work as advertised. Defining additional package sets
-
would likely result in a large number of functionally broken packages, to
-
nobody's benefit.</para></note>
-
<sect1 xml:id="sec-grsec-enable"><title>Enabling grsecurity/PaX</title>
-
To make use of grsecurity/PaX on NixOS, add the following to your
-
<filename>configuration.nix</filename>:
-
security.grsecurity.enable = true;
-
Enabling the grsecurity module overrides
-
<option>boot.kernelPackages</option>, to reduce the risk of
-
misconfiguration. <xref linkend="sec-grsec-custom-kernel" />
-
describes how to use a custom kernel package set.
-
For most users, further configuration should be unnecessary. All users
-
are encouraged to look over <xref linkend="sec-grsec-security" /> before
-
using the system, however. If you experience problems, please refer to
-
<xref linkend="sec-grsec-issues" />.
-
Once booted into the new system, you can optionally use
-
<command>paxtest</command> to exercise various PaX features:
-
# nix-shell -p paxtest --command 'paxtest blackhat'
-
Executable anonymous mapping : Killed
-
Executable bss : Killed
-
# ... remaining output truncated for brevity
-
<sect1 xml:id="sec-grsec-declarative-tuning"><title>Declarative tuning</title>
-
The default configuration mode is strictly declarative. Some features
-
simply cannot be changed at all after boot, while others are locked once the
-
system is up and running. Moreover, changes to the configuration enter
-
into effect only upon booting into the new system.
-
The NixOS module exposes a limited number of options for tuning the behavior
-
of grsecurity/PaX. These are options thought to be of particular interest
-
to most users. For experts, further tuning is possible via
-
<option>boot.kernelParams</option> (see
-
<xref linkend="sec-grsec-kernel-params" />) and
-
<option>boot.kernel.sysctl."kernel.grsecurity.*"</option> (the wikibook
-
contains an <link xlink:href="https://en.wikibooks.org/wiki/Grsecurity/Appendix/Sysctl_Options">
-
exhaustive listing of grsecurity sysctl tunables</link>).
-
<sect1 xml:id="sec-grsec-manual-tuning"><title>Manual tuning</title>
-
To permit manual tuning of grsecurity runtime parameters, set:
-
security.grsecurity.lockTunables = false;
-
Once booted into this system, grsecurity features that have a corresponding
-
sysctl tunable can be changed without rebooting, either by switching into
-
a new system profile or via the <command>sysctl</command> utility.
-
To lock all grsecurity tunables until the next boot, do:
-
# systemctl start grsec-lock
-
<sect1 xml:id="sec-grsec-security"><title>Security considerations</title>
-
The NixOS kernel is built using upstream's recommended settings for a
-
desktop deployment that generally favours security over performance. This
-
section details deviations from upstream's recommendations that may
-
<warning><para>There may be additional problems not covered here!</para>
-
The following hardening features are disabled in the NixOS kernel:
-
<listitem><para>Kernel symbol hiding: rendered useless by redistributing
-
kernel objects.</para></listitem>
-
<listitem><para>Randomization of kernel structures: rendered useless by
-
redistributing kernel objects.</para></listitem>
-
<listitem><para>TCP simultaneous OPEN connection is permitted: breaking
-
strict TCP conformance is inappropriate for a general purpose kernel.
-
The trade-off is that an attacker may be able to deny outgoing
-
connections if they are able to guess the source port allocated by your
-
OS for that connection <emphasis>and</emphasis> also manage to initiate
-
a TCP simultaneous OPEN on that port before the connection is actually
-
established.</para></listitem>
-
<listitem><para>Trusted path execution: a desirable feature, but
-
requires some more work to operate smoothly on NixOS.</para></listitem>
-
The NixOS module conditionally weakens <command>chroot</command>
-
restrictions to accommodate NixOS lightweight containers and sandboxed Nix
-
builds. This can be problematic if the deployment also runs privileged
-
network facing processes that <emphasis>rely</emphasis> on
-
<command>chroot</command> for isolation.
-
The NixOS kernel is patched to allow usermode helpers from anywhere in the
-
Nix store. A usermode helper is an executable called by the kernel in
-
certain circumstances, e.g., <command>modprobe</command>. Vanilla
-
grsecurity only allows usermode helpers from paths typically owned by the
-
super user. The NixOS kernel allows an attacker to inject malicious code
-
into the Nix store which could then be executed by the kernel as a
-
The following features are disabled because they overlap with
-
vanilla kernel mechanisms:
-
<listitem><para><filename class="directory">/proc</filename> hardening:
-
use <option>security.hideProcessInformation</option> instead. This
-
trades weaker protection for greater compatibility.
-
<listitem><para><command>dmesg</command> restrictions:
-
use <option>boot.kernel.sysctl."kernel.dmesg_restrict"</option> instead
-
<sect1 xml:id="sec-grsec-custom-kernel"><title>Using a custom grsecurity/PaX kernel</title>
-
The NixOS kernel is likely to be either too permissive or too restrictive
-
for many deployment scenarios. In addition to producing a kernel more
-
suitable for a particular deployment, a custom kernel may improve security
-
by depriving an attacker the ability to study the kernel object code, adding
-
yet more guesswork to successfully carry out certain exploits.
-
To build a custom kernel using upstream's recommended settings for server
-
deployments, while still using the NixOS module:
-
nixpkgs.config.packageOverrides = super: {
-
linux_grsec_nixos = super.linux_grsec_nixos.override {
-
GRKERNSEC_CONFIG_AUTO y
-
GRKERNSEC_CONFIG_SERVER y
-
GRKERNSEC_CONFIG_SECURITY y
-
The grsecurity/PaX wikibook provides an exhaustive listing of
-
<link xlink:href="https://en.wikibooks.org/wiki/Grsecurity/Appendix/Grsecurity_and_PaX_Configuration_Options">kernel configuration options</link>.
-
The NixOS module makes several assumptions about the kernel and so
-
may be incompatible with your customised kernel. Currently, the only way
-
to work around these incompatibilities is to eschew the NixOS
-
If not using the NixOS module, a custom grsecurity package set can
-
be specified inline instead, as in
-
kernel = pkgs.linux_grsec_nixos.override {
-
extraConfig = /* as above */;
-
self = pkgs.linuxPackagesFor kernel self;
-
<sect1 xml:id="sec-grsec-pax-flags"><title>Per-executable PaX flags</title>
-
Manual tuning of per-file PaX flags for executables in the Nix store is
-
impossible on a properly configured system. If a package in Nixpkgs fails
-
due to PaX, that is a bug in the package recipe and should be reported to
-
the maintainer (including relevant <command>dmesg</command> output).
-
For executables installed outside of the Nix store, PaX flags can be set
-
using the <command>paxctl</command> utility:
-
paxctl -czem <replaceable>foo</replaceable>
-
<para><command>paxctl</command> overwrites files in-place.</para>
-
Equivalently, on file systems that support extended attributes:
-
setfattr -n user.pax.flags -v em <replaceable>foo</replaceable>
-
<!-- TODO: PaX flags via RBAC policy -->
-
<sect1 xml:id="sec-grsec-issues"><title>Issues and work-arounds</title>
-
<listitem><para>User namespaces require <literal>CAP_SYS_ADMIN</literal>:
-
consequently, unprivileged namespaces are unsupported. Applications that
-
rely on namespaces for sandboxing must use a privileged helper. For chromium
-
there is <option>security.chromiumSuidSandbox.enable</option>.</para></listitem>
-
<listitem><para>Access to EFI runtime services is disabled by default:
-
this plugs a potential code injection attack vector; use
-
<option>security.grsecurity.disableEfiRuntimeServices</option> to override
-
this behavior.</para></listitem>
-
<listitem><para>User initiated autoloading of modules (e.g., when
-
using fuse or loop devices) is disallowed; either load requisite modules
-
as root or add them to <option>boot.kernelModules</option>.</para></listitem>
-
<listitem><para>Virtualization: KVM is the preferred virtualization
-
solution. Xen, Virtualbox, and VMWare are
-
<emphasis>unsupported</emphasis> and most likely require a custom kernel.
-
Attaching <command>gdb</command> to a running process is disallowed by
-
default: unprivileged users can only ptrace processes that are children of
-
the ptracing process. To relax this restriction, set
-
boot.kernel.sysctl."kernel.grsecurity.harden_ptrace" = 0;
-
Overflows in boot critical code (e.g., the root filesystem module) can
-
render the system unbootable. Work around by setting
-
boot.kernelParams = [ "pax_size_overflow_report_only" ];
-
The <citerefentry><refentrytitle>modify_ldt
-
</refentrytitle><manvolnum>2</manvolnum></citerefentry> syscall is disabled
-
by default. This restriction can interfere with programs designed to run
-
legacy 16-bit or segmented 32-bit code. To support applications that rely
-
boot.kernel.sysctl."kernel.modify_ldt" = 1;
-
The gitlab service (<xref linkend="module-services-gitlab" />)
-
requires a variant of the <literal>ruby</literal> interpreter
-
built without `mprotect()` hardening, as in
-
services.gitlab.packages.gitlab = pkgs.gitlab.override {
-
ruby = pkgs.ruby.overrideAttrs (attrs: {
-
postFixup = "paxmark m $out/bin/ruby";
-
<sect1 xml:id="sec-grsec-kernel-params"><title>Grsecurity/PaX kernel parameters</title>
-
The NixOS kernel supports the following kernel command line parameters:
-
<literal>pax_nouderef</literal>: disable UDEREF (separate kernel and
-
<literal>pax_weakuderef</literal>: enable a faster but
-
weaker variant of UDEREF on 64-bit processors with PCID support
-
(check <code>grep pcid /proc/cpuinfo</code>).
-
<literal>pax_sanitize_slab={off|fast|full}</literal>: control kernel
-
slab object sanitization. Defaults to <literal>fast</literal>
-
<literal>pax_size_overflow_report_only</literal>: log size overflow
-
violations but leave the violating task running
-
<literal>grsec_sysfs_restrict=[0|1]</literal>: toggle sysfs
-
restrictions. The NixOS module sets this to <literal>0</literal>
-
for systemd compatibility