1. Introduction

Security in FreeBSD is based primarily in policy-based technologies. Existing tools such as jails, Capsicum, vnet/vimage, and the MAC framework, can make FreeBSD-based systems quite resilient against attacks. FreeBSD lacks basic low-level exploit mitigation, such as Address Space Layout Randomization (ASLR)[1]. ASLR randomizes the address space layout of an application, making exploitation difficult for an attacker. This paper and the associated implementation aim to provide a secure, robust, extensible, and easily-managed form of ASLR fit for production use within FreeBSD.

2. History

On 14 May 2013, Oliver Pinter published to GitHub an initial patch[2]. His work was inspired by Elad Efrat's work in NetBSD. The patch was submitted to FreeBSD as a bug report on 24 Aug 2013[3]. Independently of Oliver's work, on 30 Jun 2014, Shawn Webb posted on his tech blog that he was interested in implementing ASLR for FreeBSD[4]. Oliver found the post and suggested that he and Shawn work together. On 08 Jun 2014, preparatory work was committed to FreeBSD, adding Position-Independent Executable (PIE) support in base[5]. On 07 Apr 2014, SoldierX[6] agreed to sponsor the project and donated a sparc64 box and a beaglebone black to Shawn Webb. This hardware is used for testing and debugging ASLR on those platforms.

3. General Overview

ASLR is enabled by default for all architectures and controlled by the PAX_ASLR kernel option. This means ASLR will be applied to all supported applications. If a user wishes to disable ASLR for a given application, the user must force that application to opt-out (detailed later).

Another kernel option, PAX_SYSCTLS, exposes additional tunables (via sysctl), allowing ASLR behavior control without requiring a reboot. By default, the sysctl security.pax.aslr.status can only be changed at boot time via /boot/loader.conf. Enabling the PAX_SYSCTLS kernel option allows a root user to modify security.pax.aslr.status. See Appendix B for a list of the tunables.

ASLR tunables are per-jail and each jail inherits its parent jail's settings. Having per-jail tunables allows more flexibility in shared-hosting environments. This structure also allows a user to selectively disable ASLR for applications that misbehave. ASLR-disabled applications will still have policy-based security applied to it by virtue of being jailed.

4. Implementation Details

A new sysinit subroutine ID, SI_SUB_PAX, initializes all ASLR system variables. Upon system boot, tunables from /boot/loader.conf are checked for validity. Any invalid values, generate a warning message to the console and the tunable is set to a sensible default.

For the sake of performance, the ASLR system relies on per-process deltas rather than calling arc4random(3) for each mapping. When a process calls execve(2), the ASLR system is initialized. Deltas are randomly generated for the execution base, mmap(2), and stack addresses. Only the execution base of applications compiled as PIEs are randomized. The execution base of non-PIE applications are not modified. The mappings of shared objects are randomized for both PIE and non-PIE applications.

The deltas are used as a hint to the Virtual Memory (VM) system. The VM system may modify the hint to make a better fit for superpages and other alignment constraints.

The delta applied to the PIE execbase is different than the delta applied to the base address of shared objects. In the Executable and Linkable File (ELF) image handler, the execution base of PIE applications is randomized by adding the delta controlled by security.pax.aslr.exec_len tunable to et_dyn_addr, which is initialized to be ET_DYN_LOAD_ADDR (an architecture-dependent macro). The base address of shared objects loaded by the runtime linker are randomized by applying the delta controlled by the security.pax.aslr.mmap_len tunable in sys_mmap().

Stack randomization is implemented using a stack gap[7]. On executable image activation, the stack delta is computed and then subtracted from the top of the stack.

5. Further Enhancements

The existing gap-based stack randomization is not optimal. Mapping-base stack randomization is more robust, but hard-coded kernel structures and addresses, especially PS_STRINGS, will need to be modified. The required changes to PS_STRINGS are major and will likely touch userland along with the kernel.

The original PaX implementation, from which the FreeBSD implementation is inspired, uses a special ELF process header which requires modification of executable files. The authors of the FreeBSD implementation have deliberately chosen to go a different route based on the MAC framework. This feature, however, is only supported on HardenedBSD. Support for filesystem extended attributes will be added at a later time.

FreeBSD's virtual Dynamic Shared Object (vDSO) implementation, an efficient technique for calling kernel code from userland, uses hardcoded, non-randomized addresses. The vDSO implementation should be reworked to be at a randomized address, providing the address as an auxiliary vector passed to the image via the stack.

6. Known Issues

No known issues or bugs at this time.

Appendix A - References









Appendix B - ASLR Tunables

NOTE: All tunables can only be changed during boot-time via /boot/loader.conf unless the kernel has been compiled with PAX_SYSCTLS.

security.pax.aslr.status (integer):

security.pax.aslr.debug (integer):

security.pax.aslr.mmap_len (integer):

security.pax.aslr.stack_len (integer):

security.pax.aslr.exec_len (integer):


rtld so load order randomization

shared page (vdso) randomization

AddressSpaceLayoutRandomization (last edited 2015-01-18 00:07:06 by ShawnWebb)