Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <64befac3-af89-611a-70d1-9838c91097b3@intel.com>
Date: Mon, 26 Sep 2016 23:05:06 -0700
From: "LeMay, Michael" <michael.lemay@...el.com>
To: Rich Felker <dalias@...c.org>
Cc: "musl@...ts.openwall.com" <musl@...ts.openwall.com>
Subject: Re: [RFC] Support for segmentation-hardened SafeStack



On 9/26/2016 11:08, Rich Felker wrote:
> On Mon, Sep 26, 2016 at 10:28:40AM -0700, LeMay, Michael wrote:
...
>> A salient requirement is that all code that runs while restricted
>> segment limits are in effect for DS and ES must use appropriate
>> segment override prefixes.  This is to direct safe stack accesses to
>> SS and thus avoid violating the segment limits on DS and ES.  It is
>> still possible to call code that does not satisfy that requirement
>> (I will refer to such functions as "standard functions", in contrast
>> to "segmentation-aware functions") in the same program, but the
>> segment registers would need to be reverted to contain flat segment
>> descriptors before calling such code.  Otherwise, a segment limit
>> violation would occur if a standard function attempted to access
>> data on the stack using DS or ES.  Of course, reverting to flat
>> segment descriptors would leave the safe stacks unprotected.
> In short, non-safestack code called from safestack code would try to
> store data on the safe stack, which doesn't/can't work.
>
> This could probably be avoided by a different approach that avoids
> call/ret and instead uses manual pushes/pops to the safe stack and
> jumps in place of call/ret. Then %ss could point to the non-safe stack
> so that calling non-safestack code would work fine (but would be
> unprotected as usual).
>
> I suspect this is sufficiently costly to implement (either in
> performance or implementation complexity or both) that you're not
> interested in doing it that way, but I mention it for completeness.

That's an interesting idea that could offer some benefits as you 
described, but it would indeed also have drawbacks.  One example that 
comes to mind is that to protect the safe stacks, only instructions that 
require access to the safe stacks should be able to use the segment that 
grants such access.  Thus, many instructions that access data sections 
and the heap would need to have segment override prefixes to direct 
their memory accesses to SS.  Using EBP as the base address for some of 
those accesses could reduce the need for segment override prefixes, but 
I don't know to what extent that would help.  A more fundamental 
challenge is that not adhering to the longstanding assumption that the 
stack resides in SS would probably necessitate major compiler 
revisions.  Another challenge is that standard functions would expect 
parameters to be passed on the stack pointed to by ESP, whereas some 
other register would be used as the safe stack pointer in this case.

...
>> However, there are instances where such writes are
>> necessary.  For example, the va_list object used to support variadic
>> arguments stores a pointer to the safe stack.
> Are your "safe stack pointers" just implementation-details like
> va_list state? In that case I think they're valid since they can only
> be accessed via va_arg. But I'm wondering why the argument list is on
> the unsafe stack at all. This mandates that you copy incoming
> (non-variadic) arguments rather than using them in-place, which is
> very expensive for (moderately-)large aggregate-type arguments.

Arguments, whether variadic or not, are still passed on the main (safe) 
stack like usual, and they can be used in-place.

>> I implemented other
>> compiler patches to emit the SS segment override prefix when
>> accessing variadic arguments, so storing the safe stack pointer into
>> the va_list object should be allowed.  The intraprocedural analysis
>> attempts to detect this type of write, but it currently has
>> limitations on the complexity of pointer computations that it can
>> handle.  Thus, I added compiler command line options to selectively
>> override this analysis for certain files and allow safe stack
>> pointers to be written to memory even when the compiler cannot
>> verify that they are being written to va_list objects.
> I don't think they should even be able to _arise_ except as
> variadic-argument pointers. If they can't arise you don't need to
> analyze where they're written.

I refreshed my memory on what allocations the SafeStack pass moves to 
the unsafe stack, and I think you're right.  If a pointer to the safe 
stack would be written to memory (e.g. into a structure passed to 
another function or into a global variable), then the SafeStack pass 
moves the allocation to the unsafe stack.  Sorry to have forgotten that 
when I wrote my previous message.  I found just a couple of exceptions 
to that rule.  Variadic argument handling is one and register spills are 
another.  Additional exceptions exist for certain function calls when 
segmentation-based hardening is disabled, but that's out of scope for 
this discussion.  So, I agree that the verification that I described 
above is unnecessary. However, I still need to track pointers to the 
safe stack in registers when they get spilled and filled so that I can 
emit the proper segment override prefixes.

>
>> Note that manipulating safe stack addresses in registers within a
>> single function is no problem.  For example, traverses_stack_p in
>> expand_heap.c compares a safe stack address to other addresses.
>> Actually, traverses_stack_p is interesting in other ways, since it
>> assumes  that libc.auxv is on the main-thread stack.  My revised
>> patches move auxv to the main-thread unsafe stack.  What checks
>> should be performed in traverses_stack_p when multiple types of
>> stacks are defined?
> It can be omitted completely for safestack. It's just a fail-safe
> workaround for buggy kernels that let you grow the brk across the
> stack which presumably you don't have on x86 systems.

I'll revise my patches to reflect this.

Thanks,
Michael

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.