[RFC] ASLR Whitepaper and Candidate Final Patch

Shawn Webb lattera at gmail.com
Fri Jul 11 23:29:18 UTC 2014

Hey All,

Oliver Pinter and I have been working hard on our ASLR implementation.
We're now in the final stages of development and would like to get
feedback from the community. I've attached to this email a small
whitepaper that details our implementation and the accompanying patch.

There is one part of the patch that I wrote that is quite an ugly hack
and would like to get some feedback on. I added a little hack to
sys_mmap() to apply ASLR to calls to mmap(2) when MAP_32BIT is
specified. I'd like to remove that ugly hack to something a bit more
beautiful, so if anyone has any suggestions, I'm all ears.

Other than that ugly hack, the code adheres to FreeBSD's style(9)
standards. I believe we have an awesome implementation, one I've
personally been using without issue for months.

I'm looking forward to your comments and questions. I've CC'd the PaX
team. Please keep them CC'd in your replies.

Thank you very much,

Shawn Webb
CC: PaX Team
CC: Oliver Pinter
CC: des at freebsd.org
CC: alc at rice.edu
CC: bdrewery at freebsd.org

PS - Sorry for the duplicate emails. I hit the wrong key and didn't CC
-------------- next part --------------
Introducing ASLR For FreeBSD
Shawn Webb <lattera at gmail.com>
Oliver Pinter <oliver.pntr at gmail.com>
10 July 2014

[ 1. Introduction ]
Security in FreeBSD's 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.

The mac_bsdextended(4) MAC module and its corresponding ugidfw(8) application
have been modified to allow a user to enable or disable ASLR for specific
applications. The filesys object specification has been modified to pass the
inode along with the filesystem id when the new paxflags option is specified.
The paxflags option is optionally placed at the end of the rule. An upper-case
"A" argument to the option signifies ASLR is enabled for the application and a
lower-case "a" signifies ASLR is disabled for the application. Sample ugidfw(8)
rules are in Appendix C.

[ 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

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

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 mac_bsdextended(4)/ugidfw(8). 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 ]

ASLR does not function properly on 32bit ARM. When a process fork(2)s and calls
execve(2) and the child process exits, the parent process crashes upon
receiving the SIGCHLD signal. No matter which application crashed, the pc
register ends up being 0xc0000000. The ktrace(1) facility proved that the
application crashed upon receiving the SIGCHLD signal.

[ Appendix A - References ]
[1]: http://pax.grsecurity.net/docs/aslr.txt
[2]: https://github.com/opntr/freebsd-patches-2013-tavasz/blob/master/r249952%2BASLR/0001-PaX-ASLR-mmap-and-basic-stack-randomization.patch
[3]: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=181497
[4]: http://0xfeedface.org/blog/lattera/2013-06-29/long-term-plans
[5]: http://svnweb.freebsd.org/base?view=revision&revision=267233
[6]: https://www.soldierx.com/
[7]: http://www.openbsd.org/papers/auug04/mgp00005.html

[ 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):
		Toggle system-wide ASLR protection.
		0 - ASLR disabled system-wide. Individual applications may NOT opt in.
		1 - ASLR disabled by default. Individual applications may opt in.
		2 - ASLR enabled by default. Individual applications may opt out.
		3 - ASLR enabled system-wide. Individual applications may NOT opt out.
	Default: 2

security.pax.aslr.debug (integer):
		Toggle debugging output.
		0 - Debug output disabled.
		1 - Basic debug output enabled.
		2 - Verbose debug output enabled.
	Default: 0

security.pax.aslr.mmap_len (integer):
		Set the number of bits to be randomized for mmap(2) calls.
		For 32bit systems, minimum of 8, maximum of 16.
		For 64bit systems, minimum of 16, maximum of 32.
		For 32bit systems, 8.
		For 64bit systems, 21.

security.pax.aslr.stack_len (integer):
		Set the number of bits to be randomized for the stack.
		For 32bit systems, minimum of 6, maximum of 12.
		For 64bit systems, minimum of 12, maximum of 21.
		For 32bit systems, 6.
		For 64bit systems, 16.

security.pax.aslr.exec_len (integer):
		Set the number of bits to be randomized for the PIE exec base.
		For 32bit systems, minimum of 6, maximum of 12.
		For 64bit systems, minimum of 12, maximum of 21.
		For 32bit systems, 6.
		For 64bit systems, 21.

[ Appendix C - Sample ugidfw(8) rules ]

When security.pax.aslr.status is set to 2 (require applications to opt-out):

ugidfw add subject uid shawn object filesys /bin/ls mode rx paxflags a
   - This adds a rule to disable ASLR for /bin/ls for the user shawn.

ugidfw add subject uid 0:65535 object filesys /bin/ls mode rx paxflags a
   - This adds a rule to disable ASLR for /bin/ls for all users.

When security.pax.aslr.status is set to 1 (require applications to opt-in):

ugidfw add subject uid shawn object filesys /bin/ls mode rx paxflags A
   - This adds a rule to enable ASLR for /bin/ls for the user shawn.

ugidfw add subject uid 0:65535 object filesys /bin/ls mode rx paxflags A
   - This adds a rule to enable ASLR for /bin/ls for all users.

[ Appendix D - Files Modified/Created in 11-CURRENT ]
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 2014-07-10_aslr.patch
Type: text/x-diff
Size: 92912 bytes
Desc: not available
URL: <http://lists.freebsd.org/pipermail/freebsd-arch/attachments/20140711/fa127354/attachment-0001.patch>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.freebsd.org/pipermail/freebsd-arch/attachments/20140711/fa127354/attachment-0001.sig>

More information about the freebsd-arch mailing list