1<chapter xmlns="http://docbook.org/ns/docbook"
2 xmlns:xlink="http://www.w3.org/1999/xlink"
3 xmlns:xi="http://www.w3.org/2001/XInclude"
4 version="5.0"
5 xml:id="sec-grsecurity">
6
7 <title>Grsecurity/PaX</title>
8
9 <para>
10 Grsecurity/PaX is a set of patches against the Linux kernel that
11 implements an extensive suite of
12 <link xlink:href="https://grsecurity.net/features.php">features</link>
13 designed to increase the difficulty of exploiting kernel and
14 application bugs.
15 </para>
16
17 <para>
18 The NixOS grsecurity/PaX module is designed with casual users in mind and is
19 intended to be compatible with normal desktop usage, without
20 <emphasis>unnecessarily</emphasis> compromising security. The
21 following sections describe the configuration and administration of
22 a grsecurity/PaX enabled NixOS system. For more comprehensive
23 coverage, please refer to the
24 <link xlink:href="https://en.wikibooks.org/wiki/Grsecurity">grsecurity wikibook</link>
25 and the
26 <link xlink:href="https://wiki.archlinux.org/index.php/Grsecurity">Arch
27 Linux wiki page on grsecurity</link>.
28
29 <warning><para>Upstream has ceased free support for grsecurity/PaX. See
30 <link xlink:href="https://grsecurity.net/passing_the_baton.php">
31 the announcement</link> for more information. Consequently, NixOS
32 support for grsecurity/PaX also must cease. Enabling this module will
33 result in a build error.</para></warning>
34 <note><para>We standardise on a desktop oriented configuration primarily due
35 to lack of resources. The grsecurity/PaX configuration state space is huge
36 and each configuration requires quite a bit of testing to ensure that the
37 resulting packages work as advertised. Defining additional package sets
38 would likely result in a large number of functionally broken packages, to
39 nobody's benefit.</para></note>
40 </para>
41
42 <sect1 xml:id="sec-grsec-enable"><title>Enabling grsecurity/PaX</title>
43
44 <para>
45 To make use of grsecurity/PaX on NixOS, add the following to your
46 <filename>configuration.nix</filename>:
47 <programlisting>
48 security.grsecurity.enable = true;
49 </programlisting>
50 followed by
51 <programlisting>
52 # nixos-rebuild boot
53 # reboot
54 </programlisting>
55 <note><para>
56 Enabling the grsecurity module overrides
57 <option>boot.kernelPackages</option>, to reduce the risk of
58 misconfiguration. <xref linkend="sec-grsec-custom-kernel" />
59 describes how to use a custom kernel package set.
60 </para></note>
61
62 For most users, further configuration should be unnecessary. All users
63 are encouraged to look over <xref linkend="sec-grsec-security" /> before
64 using the system, however. If you experience problems, please refer to
65 <xref linkend="sec-grsec-issues" />.
66 </para>
67
68 <para>
69 Once booted into the new system, you can optionally use
70 <command>paxtest</command> to exercise various PaX features:
71 <screen><![CDATA[
72 # nix-shell -p paxtest --command 'paxtest blackhat'
73 Executable anonymous mapping : Killed
74 Executable bss : Killed
75 # ... remaining output truncated for brevity
76 ]]></screen>
77 </para>
78
79 </sect1>
80
81 <sect1 xml:id="sec-grsec-declarative-tuning"><title>Declarative tuning</title>
82
83 <para>
84 The default configuration mode is strictly declarative. Some features
85 simply cannot be changed at all after boot, while others are locked once the
86 system is up and running. Moreover, changes to the configuration enter
87 into effect only upon booting into the new system.
88 </para>
89
90 <para>
91 The NixOS module exposes a limited number of options for tuning the behavior
92 of grsecurity/PaX. These are options thought to be of particular interest
93 to most users. For experts, further tuning is possible via
94 <option>boot.kernelParams</option> (see
95 <xref linkend="sec-grsec-kernel-params" />) and
96 <option>boot.kernel.sysctl."kernel.grsecurity.*"</option> (the wikibook
97 contains an <link xlink:href="https://en.wikibooks.org/wiki/Grsecurity/Appendix/Sysctl_Options">
98 exhaustive listing of grsecurity sysctl tunables</link>).
99 </para>
100
101 </sect1>
102
103 <sect1 xml:id="sec-grsec-manual-tuning"><title>Manual tuning</title>
104
105 <para>
106 To permit manual tuning of grsecurity runtime parameters, set:
107 <programlisting>
108 security.grsecurity.lockTunables = false;
109 </programlisting>
110 Once booted into this system, grsecurity features that have a corresponding
111 sysctl tunable can be changed without rebooting, either by switching into
112 a new system profile or via the <command>sysctl</command> utility.
113 </para>
114
115 <para>
116 To lock all grsecurity tunables until the next boot, do:
117 <screen>
118 # systemctl start grsec-lock
119 </screen>
120 </para>
121
122 </sect1>
123
124 <sect1 xml:id="sec-grsec-security"><title>Security considerations</title>
125
126 <para>
127 The NixOS kernel is built using upstream's recommended settings for a
128 desktop deployment that generally favours security over performance. This
129 section details deviations from upstream's recommendations that may
130 compromise security.
131
132 <warning><para>There may be additional problems not covered here!</para>
133 </warning>
134 </para>
135
136 <itemizedlist>
137
138 <listitem><para>
139 The following hardening features are disabled in the NixOS kernel:
140 <itemizedlist>
141 <listitem><para>Kernel symbol hiding: rendered useless by redistributing
142 kernel objects.</para></listitem>
143
144 <listitem><para>Randomization of kernel structures: rendered useless by
145 redistributing kernel objects.</para></listitem>
146
147 <listitem><para>TCP simultaneous OPEN connection is permitted: breaking
148 strict TCP conformance is inappropriate for a general purpose kernel.
149 The trade-off is that an attacker may be able to deny outgoing
150 connections if they are able to guess the source port allocated by your
151 OS for that connection <emphasis>and</emphasis> also manage to initiate
152 a TCP simultaneous OPEN on that port before the connection is actually
153 established.</para></listitem>
154
155 <listitem><para>Trusted path execution: a desirable feature, but
156 requires some more work to operate smoothly on NixOS.</para></listitem>
157 </itemizedlist>
158 </para></listitem>
159
160 <listitem><para>
161 The NixOS module conditionally weakens <command>chroot</command>
162 restrictions to accommodate NixOS lightweight containers and sandboxed Nix
163 builds. This can be problematic if the deployment also runs privileged
164 network facing processes that <emphasis>rely</emphasis> on
165 <command>chroot</command> for isolation.
166 </para></listitem>
167
168 <listitem><para>
169 The NixOS kernel is patched to allow usermode helpers from anywhere in the
170 Nix store. A usermode helper is an executable called by the kernel in
171 certain circumstances, e.g., <command>modprobe</command>. Vanilla
172 grsecurity only allows usermode helpers from paths typically owned by the
173 super user. The NixOS kernel allows an attacker to inject malicious code
174 into the Nix store which could then be executed by the kernel as a
175 usermode helper.
176 </para></listitem>
177
178 <listitem><para>
179 The following features are disabled because they overlap with
180 vanilla kernel mechanisms:
181
182 <itemizedlist>
183 <listitem><para><filename class="directory">/proc</filename> hardening:
184 use <option>security.hideProcessInformation</option> instead. This
185 trades weaker protection for greater compatibility.
186 </para></listitem>
187
188 <listitem><para><command>dmesg</command> restrictions:
189 use <option>boot.kernel.sysctl."kernel.dmesg_restrict"</option> instead
190 </para></listitem>
191 </itemizedlist>
192 </para></listitem>
193
194 </itemizedlist>
195
196 </sect1>
197
198 <sect1 xml:id="sec-grsec-custom-kernel"><title>Using a custom grsecurity/PaX kernel</title>
199
200 <para>
201 The NixOS kernel is likely to be either too permissive or too restrictive
202 for many deployment scenarios. In addition to producing a kernel more
203 suitable for a particular deployment, a custom kernel may improve security
204 by depriving an attacker the ability to study the kernel object code, adding
205 yet more guesswork to successfully carry out certain exploits.
206 </para>
207
208 <para>
209 To build a custom kernel using upstream's recommended settings for server
210 deployments, while still using the NixOS module:
211 <programlisting>
212 nixpkgs.config.packageOverrides = super: {
213 linux_grsec_nixos = super.linux_grsec_nixos.override {
214 extraConfig = ''
215 GRKERNSEC_CONFIG_AUTO y
216 GRKERNSEC_CONFIG_SERVER y
217 GRKERNSEC_CONFIG_SECURITY y
218 '';
219 };
220 };
221 </programlisting>
222 </para>
223
224 <para>
225 The grsecurity/PaX wikibook provides an exhaustive listing of
226 <link xlink:href="https://en.wikibooks.org/wiki/Grsecurity/Appendix/Grsecurity_and_PaX_Configuration_Options">kernel configuration options</link>.
227 </para>
228
229 <para>
230 The NixOS module makes several assumptions about the kernel and so
231 may be incompatible with your customised kernel. Currently, the only way
232 to work around these incompatibilities is to eschew the NixOS
233 module.
234 </para>
235
236 <para>
237 If not using the NixOS module, a custom grsecurity package set can
238 be specified inline instead, as in
239 <programlisting>
240 boot.kernelPackages =
241 let
242 kernel = pkgs.linux_grsec_nixos.override {
243 extraConfig = /* as above */;
244 };
245 self = pkgs.linuxPackagesFor kernel self;
246 in self;
247 </programlisting>
248 </para>
249
250 </sect1>
251
252 <sect1 xml:id="sec-grsec-pax-flags"><title>Per-executable PaX flags</title>
253
254 <para>
255 Manual tuning of per-file PaX flags for executables in the Nix store is
256 impossible on a properly configured system. If a package in Nixpkgs fails
257 due to PaX, that is a bug in the package recipe and should be reported to
258 the maintainer (including relevant <command>dmesg</command> output).
259 </para>
260
261 <para>
262 For executables installed outside of the Nix store, PaX flags can be set
263 using the <command>paxctl</command> utility:
264 <programlisting>
265 paxctl -czem <replaceable>foo</replaceable>
266 </programlisting>
267
268 <warning>
269 <para><command>paxctl</command> overwrites files in-place.</para>
270 </warning>
271
272 Equivalently, on file systems that support extended attributes:
273 <programlisting>
274 setfattr -n user.pax.flags -v em <replaceable>foo</replaceable>
275 </programlisting>
276
277 <!-- TODO: PaX flags via RBAC policy -->
278 </para>
279
280 </sect1>
281
282 <sect1 xml:id="sec-grsec-issues"><title>Issues and work-arounds</title>
283
284 <itemizedlist>
285 <listitem><para>User namespaces require <literal>CAP_SYS_ADMIN</literal>:
286 consequently, unprivileged namespaces are unsupported. Applications that
287 rely on namespaces for sandboxing must use a privileged helper. For chromium
288 there is <option>security.chromiumSuidSandbox.enable</option>.</para></listitem>
289
290 <listitem><para>Access to EFI runtime services is disabled by default:
291 this plugs a potential code injection attack vector; use
292 <option>security.grsecurity.disableEfiRuntimeServices</option> to override
293 this behavior.</para></listitem>
294
295 <listitem><para>User initiated autoloading of modules (e.g., when
296 using fuse or loop devices) is disallowed; either load requisite modules
297 as root or add them to <option>boot.kernelModules</option>.</para></listitem>
298
299 <listitem><para>Virtualization: KVM is the preferred virtualization
300 solution. Xen, Virtualbox, and VMWare are
301 <emphasis>unsupported</emphasis> and most likely require a custom kernel.
302 </para></listitem>
303
304 <listitem><para>
305 Attaching <command>gdb</command> to a running process is disallowed by
306 default: unprivileged users can only ptrace processes that are children of
307 the ptracing process. To relax this restriction, set
308 <programlisting>
309 boot.kernel.sysctl."kernel.grsecurity.harden_ptrace" = 0;
310 </programlisting>
311 </para></listitem>
312
313 <listitem><para>
314 Overflows in boot critical code (e.g., the root filesystem module) can
315 render the system unbootable. Work around by setting
316 <programlisting>
317 boot.kernelParams = [ "pax_size_overflow_report_only" ];
318 </programlisting>
319 </para></listitem>
320
321 <listitem><para>
322 The <citerefentry><refentrytitle>modify_ldt
323 </refentrytitle><manvolnum>2</manvolnum></citerefentry> syscall is disabled
324 by default. This restriction can interfere with programs designed to run
325 legacy 16-bit or segmented 32-bit code. To support applications that rely
326 on this syscall, set
327 <programlisting>
328 boot.kernel.sysctl."kernel.modify_ldt" = 1;
329 </programlisting>
330 </para></listitem>
331
332 <listitem><para>
333 The gitlab service (<xref linkend="module-services-gitlab" />)
334 requires a variant of the <literal>ruby</literal> interpreter
335 built without `mprotect()` hardening, as in
336 <programlisting>
337 services.gitlab.packages.gitlab = pkgs.gitlab.override {
338 ruby = pkgs.ruby.overrideAttrs (attrs: {
339 postFixup = "paxmark m $out/bin/ruby";
340 });
341 };
342 </programlisting>
343 </para></listitem>
344
345 </itemizedlist>
346
347 </sect1>
348
349 <sect1 xml:id="sec-grsec-kernel-params"><title>Grsecurity/PaX kernel parameters</title>
350
351 <para>
352 The NixOS kernel supports the following kernel command line parameters:
353 <itemizedlist>
354 <listitem><para>
355 <literal>pax_nouderef</literal>: disable UDEREF (separate kernel and
356 user address spaces).
357 </para></listitem>
358
359 <listitem><para>
360 <literal>pax_weakuderef</literal>: enable a faster but
361 weaker variant of UDEREF on 64-bit processors with PCID support
362 (check <code>grep pcid /proc/cpuinfo</code>).
363 </para></listitem>
364
365 <listitem><para>
366 <literal>pax_sanitize_slab={off|fast|full}</literal>: control kernel
367 slab object sanitization. Defaults to <literal>fast</literal>
368 </para></listitem>
369
370 <listitem><para>
371 <literal>pax_size_overflow_report_only</literal>: log size overflow
372 violations but leave the violating task running
373 </para></listitem>
374
375 <listitem><para>
376 <literal>grsec_sysfs_restrict=[0|1]</literal>: toggle sysfs
377 restrictions. The NixOS module sets this to <literal>0</literal>
378 for systemd compatibility
379 </para></listitem>
380 </itemizedlist>
381 </para>
382
383 </sect1>
384
385</chapter>