Documented way to disable ASLR on OS X?

aslr, macos, osx-mavericks

Solution

Actually, there still is a `-no_pie` linker flag, but you might have thought it is actually called `--no-pie`.

Lets have a small test program:

#include <stdio.h>

const char *test = "test";

int main() {
  printf("%p\n", (void*)test);
  return 0;
}

And compile as usual first:

cc -o test-pie test-pie.c

And check the flags

$ otool -hv test-pie
test-pie:
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
MH_MAGIC_64  X86_64        ALL LIB64     EXECUTE    16       1376   NOUNDEFS DYLDLINK TWOLEVEL PIE

Alright there is a `PIE` flag in there, let's verify

$ for x in $(seq 1 5); do echo -n "$x "; ./test-pie; done
1 0x10a447f96
2 0x10e3cbf96
3 0x1005daf96
4 0x10df50f96
5 0x104e63f96

That looks random enough.

Now, lets tell the linker we don't want `PIE` using `-Wl,-no_pie`:

cc -o test-nopie test-pie.c -Wl,-no_pie

Sure enough the `PIE` flag is gone:

$ otool -hv test-nopie
test-pie:
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
MH_MAGIC_64  X86_64        ALL LIB64     EXECUTE    16       1376   NOUNDEFS DYLDLINK TWOLEVEL

And test:

$ for x in $(seq 1 5); do echo -n "$x "; ./test-nopie; done
1 0x100000f96
2 0x100000f96
3 0x100000f96
4 0x100000f96
5 0x100000f96

So we make the linker not add the `PIE` flag, and my Mavericks system seems to still abide by it.

FWIW, the `PIE` flag is defined and documented in `/usr/include/mach-o/loader.h` as `MH_PIE`.

There are tools all over the Internet to clear the PIE flag from existing binaries, e.g. http://src.chromium.org/svn/trunk/src/build/mac/change_mach_o_flags.py

While I cannot offer you a documented way to start a `PIE`-flagged binary without ASLR, since you want to test code, presumably your own, just linking your test programs with `-no_pie` or removing the `PIE` flag afterwards from your test binaries should suffice?

Problem

On OS X 10.9 (Mavericks), it's possible to disable address space layout randomization for a single process if you launch the process by calling `posix_spawn()` and passing the undocumented attribute `0x100`. Like this: ``` extern char **environ; pid_t pid; posix_spawnattr_t attr; posix_spawnattr_init(&attr); posix_spawnattr_setflags(&attr, 0x100); posix_spawn(&pid, argv[0], NULL, &attr, argv, environ); ``` (This is reverse-engineered from Apple's GDB sources.) The trouble with undocumented features like this is that they tend to disappear without notice. According to this Stack Overflow answer the dynamic linker `dyld` used to consult the environment variable `DYLD_NO_PIE`, but this does not work in 10.9; similarly the static linker apparently used to take a `--no-pie` option, but this is no longer the case. So is there a documented way to disable ASLR? (The reason why I need to disable ASLR is to ensure repeatability, when testing and debugging, of code whose behaviour depends on the addresses of objects, for example address-based hash tables and BIBOP-based memory managers.)

Original source