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

Lukas Jirkovsky l.jirkovsky at gmail.com
Fri Dec 19 08:50:24 UTC 2014


On 19 December 2014 at 00:31, Daniel Micay <danielmicay at gmail.com> wrote:
> 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!).
>

No matter how much I like the idea of making Arch more secure, there
is one thing that makes compiling the whole system with ASLR one big
no-go for me (please correct me if I'm wrong). As far as I know, the
ASLR makes core dumps completely useless, and also makes it impossible
to make any sense from addresses in backtrace (assume that you get a
backtrace from an application without debugging symbols). I guess the
same thing would happen with valgrind, too.

I would be OK with building things from core with ASLR, as they should
very stable, but not whole Arch.

Lukas


More information about the arch-dev-public mailing list