[arch-dev-public] Proposal: enabling full ASLR on x86_64 via hardening-wrapper

Daniel Micay danielmicay at gmail.com
Thu Dec 18 23:31:57 UTC 2014


Arch's single biggest security weakness is that it's not benefiting from
address space layout randomization (ASLR). Fixing this issue would be a
major step towards being a leader in this area. Many distributions enable
ASLR, stack protector, etc. for a chosen set of "security critical" stuff
but very few enable them across the board.

Executable permissions on memory (NX bit) prevent an attacker from directly
injecting code via memory corruption vulnerabilities. It's only truly useful
in combination with ASLR because if the existing code is in a known location
it can be reused by the attacker.[1]

[1] https://en.wikipedia.org/wiki/Return-oriented_programming

The cost of ASLR is that it requires position independent (relocatable) code
(PIC), as is already required for all code in dynamic libraries.

On i686, PIC has a significant cost (up to 30% or more). The vanilla kernel
also lacks emulation of the NX bit and has no brute force protection to make
up for the smaller 32-bit address space. Only the subset of users using
grsecurity / PaX would truly benefit. I don't care about i686 anyway.

On x86_64, there's hardware support for position independent code so it's
essentially free. It does currently cost ~1% due to linker and compiler
limitations (indirection to access globals) but this has been fixed in the
binutils/gcc master branches. It's much cheaper than the
-fstack-protector-strong switch which we're already using, and the security
value is higher.

The only real barrier to enabling it is the lack of support in GCC for
simply flipping it on by default. Library code is already built with -fPIC
and is then linked with -shared. Full ASLR requires building the executable
code with -fPIE (or -fPIC, which isn't as cheap) and then linking with -pie.
There are two approaches to this:

1) Patching the toolchain's spec files (Hardened Gentoo)
2) Wrapper scripts for clang/gcc/ld.bfd/ld.gold (Debian, Fedora, Ubuntu)

Upstream hasn't accepted various forms of the first option, so I don't think
it's a suitable approach for us. The hardening-wrapper package implements
the second option and also enforces our existing hardening flags for build
systems ignoring CFLAGS/CXXFLAGS/LDFLAGS.

All it would take is either adding hardening-wrapper to the default devtools
packages list or making it part of base-devel.

Here's an example with a small C program:

strcat at thinktank i ~ master % cat test.c 
#include <stdio.h>

static void foo() {}
static int bar = 5;

int main(void) {
    int baz = 5;
    printf("function: %p, data: %p, stack: %p\n", foo, &bar, &baz);
    return 0;
}

Without the hardening-wrapper package installed:

strcat at thinktank i ~ master % gcc test.c -o test
strcat at thinktank i ~ master % checksec --file test
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FILE
No RELRO        No canary found   NX enabled    No PIE          No RPATH   No RUNPATH   test
strcat at thinktank i ~ master % ./test 
function: 0x400506, data: 0x600980, stack: 0x7fff12ba3a7c
strcat at thinktank i ~ master % ./test
function: 0x400506, data: 0x600980, stack: 0x7fffa47958fc

With the hardening-wrapper package installed:

strcat at thinktank i ~ master % gcc test.c -o test              
strcat at thinktank i ~ master % checksec --file test
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FILE
Partial RELRO   Canary found      NX enabled    PIE enabled     No RPATH   No RUNPATH   test
strcat at thinktank i ~ master % ./test
function: 0x7f267e569800, data: 0x7f267e76a050, stack: 0x7fff3ee5ea14
strcat at thinktank i ~ master % ./test 
function: 0x7f6a06b3e790, data: 0x7f6a06d3f048, stack: 0x7fff76a891bc

The defaults in /etc/hardening-wrapper.conf can be overridden via env variables:

strcat at thinktank i ~ master % HARDENING_STACK_PROTECTOR=0 gcc test.c -o test
strcat at thinktank i ~ master % checksec --file test
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FILE
Partial RELRO   No canary found   NX enabled    PIE enabled     No RPATH   No RUNPATH   test

The need to use wrapper scripts is a bit ugly, but I think it's a nicer
approach than tracking down and patching dozens of build systems to respect
CFLAGS/LDFLAGS and it's the only realistic way to enable PIE. The only
alternative short of patching GCC spec files is manually specifying the
flags in thousands of executable-only packages, and patching any build
system producing both binaries and libraries (yikes!).

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <https://lists.archlinux.org/pipermail/arch-dev-public/attachments/20141218/1f702ab3/attachment.bin>


More information about the arch-dev-public mailing list