summary refs log tree commit diff
path: root/nixos/modules/security/grsecurity.xml
blob: ef0aab4a3f134276938ddeb599515eb0fc803a7d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
<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.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>