nixpkgs/nixos/modules/security/grsecurity.xml

382 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 make it
harder to exploit bugs. The patchset includes protections such as
enforcement of non-executable memory, address space layout randomization,
and chroot jail hardening. These and other
<link xlink:href="https://grsecurity.net/features.php">features</link>
render entire classes of exploits inert without additional efforts on the
part of the adversary.
</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 unnecessarily
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 operational 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 is problematic if the deployment also runs a privileged
network facing process that <emphasis>relies</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 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 incompatibilities is to eschew the NixOS module.
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.kernel.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>