383 lines
14 KiB
XML
383 lines
14 KiB
XML
<chapter xmlns="http://docbook.org/ns/docbook"
|
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
xmlns:xi="http://www.w3.org/2001/XInclude"
|
|
version="5.0"
|
|
xml:id="sec-grsecurity">
|
|
|
|
<title>Grsecurity/PaX</title>
|
|
|
|
<para>
|
|
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
|
|
application bugs.
|
|
</para>
|
|
|
|
<para>
|
|
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>
|
|
and the
|
|
<link xlink:href="https://wiki.archlinux.org/index.php/Grsecurity">Arch
|
|
Linux wiki page on grsecurity</link>.
|
|
|
|
<note><para>grsecurity/PaX is only available for the latest linux -stable
|
|
kernel; patches against older kernels are available from upstream only for
|
|
a fee.</para></note>
|
|
<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>
|
|
</para>
|
|
|
|
<sect1 xml:id="sec-grsec-enable"><title>Enabling grsecurity/PaX</title>
|
|
|
|
<para>
|
|
To make use of grsecurity/PaX on NixOS, add the following to your
|
|
<filename>configuration.nix</filename>:
|
|
<programlisting>
|
|
security.grsecurity.enable = true;
|
|
</programlisting>
|
|
followed by
|
|
<programlisting>
|
|
# nixos-rebuild boot
|
|
# reboot
|
|
</programlisting>
|
|
<note><para>
|
|
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.
|
|
</para></note>
|
|
|
|
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" />.
|
|
</para>
|
|
|
|
<para>
|
|
Once booted into the new system, you can optionally use
|
|
<command>paxtest</command> to exercise various PaX features:
|
|
<screen><![CDATA[
|
|
# nix-shell -p paxtest --command 'paxtest blackhat'
|
|
Executable anonymous mapping : Killed
|
|
Executable bss : Killed
|
|
# ... remaining output truncated for brevity
|
|
]]></screen>
|
|
</para>
|
|
|
|
</sect1>
|
|
|
|
<sect1 xml:id="sec-grsec-declarative-tuning"><title>Declarative tuning</title>
|
|
|
|
<para>
|
|
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.
|
|
</para>
|
|
|
|
<para>
|
|
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>).
|
|
</para>
|
|
|
|
</sect1>
|
|
|
|
<sect1 xml:id="sec-grsec-manual-tuning"><title>Manual tuning</title>
|
|
|
|
<para>
|
|
To permit manual tuning of grsecurity runtime parameters, set:
|
|
<programlisting>
|
|
security.grsecurity.lockTunables = false;
|
|
</programlisting>
|
|
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.
|
|
</para>
|
|
|
|
<para>
|
|
To lock all grsecurity tunables until the next boot, do:
|
|
<screen>
|
|
# systemctl start grsec-lock
|
|
</screen>
|
|
</para>
|
|
|
|
</sect1>
|
|
|
|
<sect1 xml:id="sec-grsec-security"><title>Security considerations</title>
|
|
|
|
<para>
|
|
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
|
|
compromise security.
|
|
|
|
<warning><para>There may be additional problems not covered here!</para>
|
|
</warning>
|
|
</para>
|
|
|
|
<itemizedlist>
|
|
|
|
<listitem><para>
|
|
The following hardening features are disabled in the NixOS kernel:
|
|
<itemizedlist>
|
|
<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>
|
|
</itemizedlist>
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
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.
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
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
|
|
usermode helper.
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
The following features are disabled because they overlap with
|
|
vanilla kernel mechanisms:
|
|
|
|
<itemizedlist>
|
|
<listitem><para><filename class="directory">/proc</filename> hardening:
|
|
use <option>security.hideProcessInformation</option> instead. This
|
|
trades weaker protection for greater compatibility.
|
|
</para></listitem>
|
|
|
|
<listitem><para><command>dmesg</command> restrictions:
|
|
use <option>boot.kernel.sysctl."kernel.dmesg_restrict"</option> instead
|
|
</para></listitem>
|
|
</itemizedlist>
|
|
</para></listitem>
|
|
|
|
</itemizedlist>
|
|
|
|
</sect1>
|
|
|
|
<sect1 xml:id="sec-grsec-custom-kernel"><title>Using a custom grsecurity/PaX kernel</title>
|
|
|
|
<para>
|
|
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.
|
|
</para>
|
|
|
|
<para>
|
|
To build a custom kernel using upstream's recommended settings for server
|
|
deployments, while still using the NixOS module:
|
|
<programlisting>
|
|
nixpkgs.config.packageOverrides = super: {
|
|
linux_grsec_nixos = super.linux_grsec_nixos.override {
|
|
extraConfig = ''
|
|
GRKERNSEC_CONFIG_AUTO y
|
|
GRKERNSEC_CONFIG_SERVER y
|
|
GRKERNSEC_CONFIG_SECURITY y
|
|
'';
|
|
};
|
|
};
|
|
</programlisting>
|
|
</para>
|
|
|
|
<para>
|
|
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>.
|
|
</para>
|
|
|
|
<para>
|
|
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
|
|
module.
|
|
</para>
|
|
|
|
<para>
|
|
If not using the NixOS module, a custom grsecurity package set can
|
|
be specified inline instead, as in
|
|
<programlisting>
|
|
boot.kernelPackages =
|
|
let
|
|
kernel = pkgs.linux_grsec_nixos.override {
|
|
extraConfig = /* as above */;
|
|
};
|
|
self = pkgs.linuxPackagesFor kernel self;
|
|
in self;
|
|
</programlisting>
|
|
</para>
|
|
|
|
</sect1>
|
|
|
|
<sect1 xml:id="sec-grsec-pax-flags"><title>Per-executable PaX flags</title>
|
|
|
|
<para>
|
|
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).
|
|
</para>
|
|
|
|
<para>
|
|
For executables installed outside of the Nix store, PaX flags can be set
|
|
using the <command>paxctl</command> utility:
|
|
<programlisting>
|
|
paxctl -czem <replaceable>foo</replaceable>
|
|
</programlisting>
|
|
|
|
<warning>
|
|
<para><command>paxctl</command> overwrites files in-place.</para>
|
|
</warning>
|
|
|
|
Equivalently, on file systems that support extended attributes:
|
|
<programlisting>
|
|
setfattr -n user.pax.flags -v em <replaceable>foo</replaceable>
|
|
</programlisting>
|
|
|
|
<!-- TODO: PaX flags via RBAC policy -->
|
|
</para>
|
|
|
|
</sect1>
|
|
|
|
<sect1 xml:id="sec-grsec-issues"><title>Issues and work-arounds</title>
|
|
|
|
<itemizedlist>
|
|
<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.
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
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
|
|
<programlisting>
|
|
boot.kernel.sysctl."kernel.grsecurity.harden_ptrace" = 0;
|
|
</programlisting>
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
Overflows in boot critical code (e.g., the root filesystem module) can
|
|
render the system unbootable. Work around by setting
|
|
<programlisting>
|
|
boot.kernelParams = [ "pax_size_overflow_report_only" ];
|
|
</programlisting>
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
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
|
|
on this syscall, set
|
|
<programlisting>
|
|
boot.kernel.sysctl."kernel.modify_ldt" = 1;
|
|
</programlisting>
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
The gitlab service (<xref linkend="module-services-gitlab" />)
|
|
requires a variant of the <literal>ruby</literal> interpreter
|
|
built without `mprotect()` hardening, as in
|
|
<programlisting>
|
|
services.gitlab.packages.gitlab = pkgs.gitlab.override {
|
|
ruby = pkgs.ruby.overrideAttrs (attrs: {
|
|
postFixup = "paxmark m $out/bin/ruby";
|
|
});
|
|
};
|
|
</programlisting>
|
|
</para></listitem>
|
|
|
|
</itemizedlist>
|
|
|
|
</sect1>
|
|
|
|
<sect1 xml:id="sec-grsec-kernel-params"><title>Grsecurity/PaX kernel parameters</title>
|
|
|
|
<para>
|
|
The NixOS kernel supports the following kernel command line parameters:
|
|
<itemizedlist>
|
|
<listitem><para>
|
|
<literal>pax_nouderef</literal>: disable UDEREF (separate kernel and
|
|
user address spaces).
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
<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>).
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
<literal>pax_sanitize_slab={off|fast|full}</literal>: control kernel
|
|
slab object sanitization. Defaults to <literal>fast</literal>
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
<literal>pax_size_overflow_report_only</literal>: log size overflow
|
|
violations but leave the violating task running
|
|
</para></listitem>
|
|
|
|
<listitem><para>
|
|
<literal>grsec_sysfs_restrict=[0|1]</literal>: toggle sysfs
|
|
restrictions. The NixOS module sets this to <literal>0</literal>
|
|
for systemd compatibility
|
|
</para></listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
|
|
</sect1>
|
|
|
|
</chapter>
|