[PATCH] Add the disable_aslr option that will disable the address space layout randomization under AddressSanitizer on 10.6

+llvmdev

Question to MacOS gurus: is there a way to disable ASLR (address space layout randomization) on Darwin at link time
instead of doing setenv(“DYLD_NO_PIE”, “1”, 1); and reexec?

Thanks,

–kcc

Options when creating a main executable
-pie This makes a special kind of main executable that is position
independent (PIE). On Mac OS X 10.5 and later, the OS the OS
will load a PIE at a random address each time it is executed.
You cannot create a PIE from .o files compiled with -mdy-
namic-no-pic. That means the codegen is less optimal, but
the address randomization adds some security. When targeting
Mac OS X 10.7 or later PIE is the default for main executa-
bles.

-no_pie Do not make a position independent executable (PIE). This is
the default, when targeting 10.6 and earlier.

Yes, we have no ASRL with -no_pie.
Can we disable ASRL even with -pie?
On linux we can do it with “setarch x86_64 -R”.

Another question: if asan would require -no_pie on Mac, will this be a serious limitation?

Thanks,

–kcc

Yes, we have no ASRL with -no_pie.
Can we disable ASRL even with -pie?
On linux we can do it with "setarch x86_64 -R".

You asked about link time. Now it sounds like you're talking about runtime?

Another question: if asan would require -no_pie on Mac, will this be a serious limitation?

If asan required no pie on Linux, would it be a serious limitation?

-eric

Yes, we have no ASRL with -no_pie.
Can we disable ASRL even with -pie?
On linux we can do it with “setarch x86_64 -R”.

You asked about link time. Now it sounds like you’re talking about runtime?

Link time is of course better.
But if there is a syscall (like the one used by setarch) we could call it and reexec.
Using setenv(“DYLD_NO_PIE”)+reexec looks gross to me.

Another question: if asan would require -no_pie on Mac, will this be a serious limitation?

If asan required no pie on Linux, would it be a serious limitation?

For Linux, I don’t think this will be too bad, but may cause some users a bit of pain to rework their build files.
Luckily, asan and -pie work together on Linux quite well.
I don’t know how important is “-pie” on Mac.

–kcc

Yes, we have no ASRL with -no_pie.
Can we disable ASRL even with -pie?
On linux we can do it with “setarch x86_64 -R”.

You asked about link time. Now it sounds like you’re talking about runtime?

Link time is of course better.
But if there is a syscall (like the one used by setarch) we could call it and reexec.
Using setenv(“DYLD_NO_PIE”)+reexec looks gross to me.

Not sure honestly.

Another question: if asan would require -no_pie on Mac, will this be a serious limitation?

If asan required no pie on Linux, would it be a serious limitation?

For Linux, I don’t think this will be too bad, but may cause some users a bit of pain to rework their build files.
Luckily, asan and -pie work together on Linux quite well.
I don’t know how important is “-pie” on Mac.

Just as important as it is on Linux.

-eric

Yes, we have no ASRL with -no_pie.
Can we disable ASRL even with -pie?
On linux we can do it with “setarch x86_64 -R”.

You asked about link time. Now it sounds like you’re talking about runtime?

Link time is of course better.
But if there is a syscall (like the one used by setarch) we could call it and reexec.
Using setenv(“DYLD_NO_PIE”)+reexec looks gross to me.

Not sure honestly.

Thanks. If anyone knows, please jump in.

As for the patch, I really don’t like

  1. 3 different cases for 3 different flavors of MacOS. How are we goring to support it?
  2. doing setenv+reexec. This will be a debugging nightmare for us and for users.

I would prefer just to print a descriptive warning message and exit:
==123== ERROR: AddressSanitizer on MacOS requires to disable ASRL for the executable.
==123== ERROR: You can do it this way:
==123== ERROR:
==123== ABORTING

–kcc

Link time is of course better.
But if there is a syscall (like the one used by setarch) we could call it
and reexec.
Using setenv("DYLD_NO_PIE")+reexec looks gross to me.

There's posix_spawnattr_setflags() that can do the job
(http://reverse.put.as/2011/08/11/how-gdb-disables-aslr-in-mac-os-x-lion/),
but the necessary flag appeared only in Lion.

To the best of my knowledge, there's no link-time option that disables
ASLR but keeps PIE on Snow Leopard or Lion.
At the moment we're using DYLD_NO_PIE with Chromium binaries to
disable ASLR at runtime.

As for the patch, I really don't like
1. 3 different cases for 3 different flavors of MacOS. How are we goring
to support it?

The first is Leopard, which we don't want to support at all. Maybe we
should check that in some other place.
The second is Snow Leopard, where ASLR is controlled by the
DYLD_NO_PIE env var, which is read by the dynamic loader.
The third is Lion, which does not support DYLD_NO_PIE, but instead
supports a flag I've mentioned above. I suppose further Mac OS
releases will support only this way.

There also is the MH_PIE bit in the Mach-O header, which we can flip
to disable ASLR. But I'm not sure whether it won't disable the PIE
behavior at all.
Also, we'll need some special tool for that.

2. doing setenv+reexec. This will be a debugging nightmare for us and for
users.

One can avoid setenv+exec by setting disable_aslr to 0. In this case
we can print the big warning (if someone wants to run the binary under
GDB, ASLR will anyway be disabled).

I would prefer just to print a descriptive warning message and exit:
==123== ERROR: AddressSanitizer on MacOS requires to disable ASRL for the
executable.
==123== ERROR: You can do it this way:
==123== ERROR: <how to disable ASLR>
==123== ABORTING

"pass the no_pie to your linker"
We can do this in the Clang driver, but a proper fix will involve
removing all the instances of -pie from the arg list.
I've recently posted a question about that to cfe-dev, but
unfortunately nobody responded.

BTW, have you given up the idea of having zero offset for the shadow?
We'll need PIE for that.

One bit that may make sense is to support the newest (Lion) style and give
a descriptive error message for the other two cases? I.e. if we notice that
MH_PIE is set in the executable, but we're not on Lion and we don't have
DYLD_NO_PIE set in the environment give an error?

Or some combination of this.

-eric

Link time is of course better.
But if there is a syscall (like the one used by setarch) we could call it
and reexec.
Using setenv(“DYLD_NO_PIE”)+reexec looks gross to me.
There’s posix_spawnattr_setflags() that can do the job
(http://reverse.put.as/2011/08/11/how-gdb-disables-aslr-in-mac-os-x-lion/),
but the necessary flag appeared only in Lion.

To the best of my knowledge, there’s no link-time option that disables
ASLR but keeps PIE on Snow Leopard or Lion.
At the moment we’re using DYLD_NO_PIE with Chromium binaries to
disable ASLR at runtime.

One bit that may make sense is to support the newest (Lion) style and give
a descriptive error message for the other two cases? I.e. if we notice that
MH_PIE is set in the executable, but we’re not on Lion and we don’t have
DYLD_NO_PIE set in the environment give an error?

Or some combination of this.

Yea, something like this will be simpler to maintain.

–kcc

The zero offset (which speeds up asan by ~6%) requires PIE, but also requires no ASLR.

–kcc

Am I understanding right -- you suggest to check for MH_PIE, and, if it is set:
  -- on Snow Leopard, check for DYLD_NO_PIE and exit with the error
message, if it is not set
  -- on Lion, set the flag disabling ASLR, fork and exec

I'm ok with such a suggestion

The zero offset (which speeds up asan by ~6%) requires PIE, but also
requires no ASLR.

Well, we already know at least one reliable way to disable ASLR on each OS.