# Grsecurity/PaX

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 features render entire classes of exploits inert without additional efforts on the part of the adversary.

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 grsecurity wikibook and the Arch Linux wiki page on grsecurity.

grsecurity/PaX is only available for the latest linux -stable kernel; patches against older kernels are available from upstream only for a fee.

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.

.

## Enabling grsecurity/PaX

To make use of grsecurity/PaX on NixOS, add the following to your `configuration.nix`:

          security.grsecurity.enable = true;

followed by

          # nixos-rebuild boot
          # reboot

For most users, further configuration should be unnecessary. All users are encouraged to look over before using the system, however. If you experience problems, please refer to .

Once booted into the new system, you can optionally use `paxtest` to exercise various PaX features:

        # nix-shell -p paxtest --command 'paxtest blackhat'
        Executable anonymous mapping             : Killed
        Executable bss                           : Killed
        # ... remaining output truncated for brevity

## Declarative tuning

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 `boot.kernelParams` (see ) and `boot.kernel.sysctl."kernel.grsecurity.*"` (the wikibook contains an exhaustive listing of grsecurity sysctl tunables).

## Manual tuning

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 `sysctl` utility.

To lock all grsecurity tunables until the next boot, do:

          # systemctl start grsec-lock

## Security considerations

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.

There may be additional problems not covered here!

.

- The following hardening features are disabled in the NixOS kernel:

  - Kernel symbol hiding: rendered useless by redistributing kernel objects.

  - Randomization of kernel structures: rendered useless by redistributing kernel objects.

  - 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 and also manage to initiate a TCP simultaneous OPEN on that port before the connection is actually established.

  - `/sys` hardening: breaks systemd.

  - Trusted path execution: a desirable feature, but requires some more work to operate smoothly on NixOS.

- The NixOS module conditionally weakens `chroot` restrictions to accommodate NixOS lightweight containers and sandboxed Nix builds. This is problematic if the deployment also runs a privileged network facing process that relies on `chroot` 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., `modprobe`. 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.

- The following features are disabled because they overlap with vanilla kernel mechanisms:

  - `/proc` hardening: use `security.hideProcessInformation` instead. This trades weaker protection for greater compatibility.

  - `dmesg` restrictions: use `boot.kernel.sysctl."kernel.dmesg_restrict"` instead

## Using a custom grsecurity/PaX kernel

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 use a custom kernel with upstream's recommended settings for server deployments:

          boot.kernelPackages =
            let
              kernel = pkgs.linux_grsec_nixos.override {
                extraConfig = ''
                  GRKERNSEC y
                  PAX y
                  GRKERNSEC_CONFIG_AUTO y
                  GRKERNSEC_CONFIG_SERVER y
                  GRKERNSEC_CONFIG_SECURITY y
                '';
              };
              self = pkgs.linuxPackagesFor kernel self;
            in self;

The wikibook provides an exhaustive listing of kernel configuration options.

The NixOS module makes several assumptions about the kernel and so may be incompatible with your customised kernel. Most of these assumptions are encoded as assertions — mismatches should ideally result in a build failure. Currently, the only way to work around incompatibilities is to eschew the NixOS module and do all configuration yourself.

## Per-executable PaX flags

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 `dmesg` output).

For executables installed outside of the Nix store, PaX flags can be set using the `paxctl` utility:

          paxctl -czem foo

`paxctl` overwrites files in-place.

Equivalently, on file systems that support extended attributes:

          setfattr -n user.pax.flags -v em foo

## Issues and work-arounds

- Access to EFI runtime services is disabled by default: this plugs a potential code injection attack vector; use `security.grsecurity.disableEfiRuntimeServices` to override this behavior.

- Virtualization: KVM is the preferred virtualization solution. Xen, Virtualbox, and VMWare are unsupported and most likely require a custom kernel.

- Attaching `gdb` 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.kernel.kernelParams = [ "pax_size_overflow_report_only" ];

- The modify_ldt 2 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

              boot.kernel.sysctl."kernel.modify_ldt" = 1;

## Grsecurity/PaX kernel parameters

The NixOS kernel supports the following kernel command line parameters:

- `pax_nouderef`: disable UDEREF (separate kernel and user address spaces).

- `pax_weakuderef`: enable a faster but weaker variant of UDEREF on 64-bit processors with PCID support (check `grep pcid /proc/cpuinfo`).

- `pax_sanitize_slab={off|fast|full}`: control kernel slab object sanitization

- `pax_size_overflow_report_only`: log size overflow violations but leave the violating task running