This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: RFC: stack/heap collision vulnerability and mitigation with GCC


On 06/20/2017 02:16 AM, Eric Botcazou wrote:
> 
> Right, because the Linux kernel for x86/x86-64 is the only OS flavor that 
> doesn't let you probe the stack ahead of the stack pointer.  All other 
> combinations of OS and architecture we tried (and it's quite a lot) do.
But what you end up depending on is undocumented behavior of a
particular kernel implementation.  That seems rather unwise.


> 
>> After much poking around I concluded that we really need to implement
>> allocation and probing via a "moving sp" strategy.   Probing into
>> unallocated areas runs afoul of valgrind, so that's a non-starter.
> 
> The reason why you cannot use this strategy on a global basis for stack 
> checking is that some ABIs specify that you cannot update the stack pointer 
> more than once to establish a frame; others don't explicitly care but...
Which ABIs have that property?  I'll be the first to admit that I've
purged much of my weird ABI memories.

Supporting ABIs which force us into a probe, then allocate strategy is
actually easy.  We can use the existing -fstack-check code, but use the
value 0 for STACK_CHECK_PROTECT.

Just replace all uses of STACK_CHECK_PROTECT with calls to a wrapper.

The wrapper looks like

if (magic_flag)
  return STACK_CHECK_PROTECT;
else
  return 0;

That's precisely what we were planning to do prior to bumping against
the valgrind issues.  That indirection makes it easy to ensure we didn't
change the behavior of the existing stack-check for Ada, but also allows
us to change the behavior for the new stack checking option.


> 
>> Allocating stack space, then probing the pages within the space is
>> vulnerable to async signal delivery between the allocation point and the
>> probe point.  If that occurs the signal handler could end up running on
>> a stack that has collided with the heap.
> 
> ...yes, there are difficulties with the "moving sp" strategy.
> 
>> Finally, we need not ensure the ability to handle a signal at stack
>> overflow.  It is fine for the kernel to halt the process immediately if
>> it detects a reference to the guard page.
> 
> In Ada it's the opposite and we use an alternate signal stack in this case.
Ah, so if you're running on an alternate stack, then why probe ahead of
need?  I thought the whole point of probing a couple pages ahead as to
ensure you could take the signal the Ada.

I've also wondered if a 2 page guard would solve some of these problems.
 In the event of stack overflow, the kernel maps in one of the two pages
for use by the signal handler.   But changing things at this point may
not be worth the effort.

> 
>> Michael Matz has suggested some generic support so that we don't have to
>> write target specific code for each and every target we support.  THe
>> idea is to have a helper function which allocates and probes stack
>> space.  THe port can then call that helper function from within its
>> prologue generator.  I  think this is wise -- I wouldn't want to go
>> through this exercise on every port.
> 
> Interesting.  We never convinced ourselves that this was worthwhile.
The idea is not to have to write probing code for all those embedded
targets.  I doubt anyone really wants to write probes for the mn103,
rl78, mep, etc etc.

With Matz's little helper routine, they just have to pick the right
point in their prologue code to call the helper.  At least that's the
theory.

Jeff



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]