Avoid stack/heap executable memory

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Avoid stack/heap executable memory

Demi Obenour
mmap() is the only (reasonably) portable and secure way to get
executable memory.  An executable stack or heap makes exploiting
vulnerabilities much easier.

How difficult would this be to implement?
Reply | Threaded
Open this post in threaded view
|

Re: Avoid stack/heap executable memory

Richard Henderson-2
On 05/03/2016 11:28 AM, Demi Obenour wrote:
> mmap() is the only (reasonably) portable and secure way to get
> executable memory.  An executable stack or heap makes exploiting
> vulnerabilities much easier.
>
> How difficult would this be to implement?

Please check out an old idea I had for gcc's own trampolines:

   https://github.com/rth7680/tramp.git

The Idea is that we mmap two sequential pages.  The first, the "code page", is
mmaped execute-only from the executable file.  The second, the "data page", is
anonymous read-write.  The code page is PIC and reads from the data page, which
contains the specifics of the closure.  The code page would be re-mapped from
the same source as many times as necessary to handle all of the closures.

Incidentally, this also means that Issues such as #228 (__clear_cache broken on
qnx) go away because we no longer need to ever clear the icache.  The kernel
will do that for us as needed during the mmap.

The end result would look a lot like FFI_EXEC_TRAMPOLINE_TABLE, making it easy
to fold that back as the common (and only) case.

Of course, this will change the ABI, but I think we can work around that (at
least for ELF with symbol versioning), and also preserve the API.  Of course,
there's a *lot* that can be cleaned up if we're willing to change the API...


r~
Reply | Threaded
Open this post in threaded view
|

Re: Avoid stack/heap executable memory

Andrew Haley
On 05/04/2016 12:32 AM, Richard Henderson wrote:
> Of course, this will change the ABI, but I think we can work around that (at
> least for ELF with symbol versioning), and also preserve the API.  Of course,
> there's a *lot* that can be cleaned up if we're willing to change the API...

For a long while now I've wanted to go in the opposite direction: to
use a small JIT compiler to generate efficient code for invocations in
both directions.  It doesn't have to be very complicated, and once
you've generated code for any particular set of arguments that shim
can be cached for use by any function with the same argument types.
This could either use an existing JIT library or a custom JIT created
just for libffi.  It would often be way more efficient than what we do
at present.

But it would keep bumping up against the "no executable and writable
memory!" meme.  Of course security is important, but I can't help
thinking that by being rigid about this we're performing a DOS attack
on ourselves.

Andrew.
Reply | Threaded
Open this post in threaded view
|

Re: Avoid stack/heap executable memory

Anthony Green
Can't there be special kernel support for this kind of situation?
Like https://pax.grsecurity.net/docs/emutramp.txt

(resent because original was bounced by sourceware)

AG

On Wed, May 4, 2016 at 6:17 AM, Andrew Haley <[hidden email]> wrote:

> On 05/04/2016 12:32 AM, Richard Henderson wrote:
>> Of course, this will change the ABI, but I think we can work around that (at
>> least for ELF with symbol versioning), and also preserve the API.  Of course,
>> there's a *lot* that can be cleaned up if we're willing to change the API...
>
> For a long while now I've wanted to go in the opposite direction: to
> use a small JIT compiler to generate efficient code for invocations in
> both directions.  It doesn't have to be very complicated, and once
> you've generated code for any particular set of arguments that shim
> can be cached for use by any function with the same argument types.
> This could either use an existing JIT library or a custom JIT created
> just for libffi.  It would often be way more efficient than what we do
> at present.
>
> But it would keep bumping up against the "no executable and writable
> memory!" meme.  Of course security is important, but I can't help
> thinking that by being rigid about this we're performing a DOS attack
> on ourselves.
>
> Andrew.
Reply | Threaded
Open this post in threaded view
|

Re: Avoid stack/heap executable memory

Jay K-3
That is quite slow, incurring no-execute traps.

 - Jay

On May 4, 2016, at 5:42 AM, Anthony Green <[hidden email]> wrote:

> Can't there be special kernel support for this kind of situation?
> Like https://pax.grsecurity.net/docs/emutramp.txt
>
> (resent because original was bounced by sourceware)
>
> AG
>
> On Wed, May 4, 2016 at 6:17 AM, Andrew Haley <[hidden email]> wrote:
>> On 05/04/2016 12:32 AM, Richard Henderson wrote:
>>> Of course, this will change the ABI, but I think we can work around that (at
>>> least for ELF with symbol versioning), and also preserve the API.  Of course,
>>> there's a *lot* that can be cleaned up if we're willing to change the API...
>>
>> For a long while now I've wanted to go in the opposite direction: to
>> use a small JIT compiler to generate efficient code for invocations in
>> both directions.  It doesn't have to be very complicated, and once
>> you've generated code for any particular set of arguments that shim
>> can be cached for use by any function with the same argument types.
>> This could either use an existing JIT library or a custom JIT created
>> just for libffi.  It would often be way more efficient than what we do
>> at present.
>>
>> But it would keep bumping up against the "no executable and writable
>> memory!" meme.  Of course security is important, but I can't help
>> thinking that by being rigid about this we're performing a DOS attack
>> on ourselves.
>>
>> Andrew.