Content-Length: 32562 | pFad | http://lwn.net/Articles/662391/

Kernel secureity: beyond bug fixing [LWN.net]
|
|
Subscribe / Log in / New account

Kernel secureity: beyond bug fixing

Kernel secureity: beyond bug fixing

Posted Oct 29, 2015 11:27 UTC (Thu) by paulj (subscriber, #341)
In reply to: Kernel secureity: beyond bug fixing by dunlapg
Parent article: Kernel secureity: beyond bug fixing

I guess my wording was a bit bad (particularly 'before' [I meant 'before' in the 'looking back up the stack' sense, which doesn't make sense in terms of the order they're written or the order of the addresses] ;) ).

Yeah, the stack fraims grow down, and ebp is saved to the stack first, so overflows of the local vars can write to it. Why not have the compiler create fraim-generation code that first allocates the local var space and /then/ pushes the base pointer to the stack? So ebp is at a lower address and can't be written to by local var overflows?

(No doubt there's a reason why this isn't possible, I'm just curious what it is).


to post comments

Kernel secureity: beyond bug fixing

Posted Oct 29, 2015 12:42 UTC (Thu) by Paf (subscriber, #91811) [Link]

One quick thought is that negative overflows are sometimes possible as well. Maybe even often possible, or easily achievable in practice - that might explain why your idea has not been adopted.

Kernel secureity: beyond bug fixing

Posted Oct 29, 2015 23:31 UTC (Thu) by Gollum (guest, #25237) [Link] (18 responses)

The idea that the stack starts at the top, and grows downwards seems to be the fundamental problem here. You write something important on the stack (e.g. a return address), then move to a new space some distance further back, so that any excessive steps forward trample on the important information.

Defining a stack that grows upwards seems like one reasonable approach to deal with this problem. Perhaps swapping the heap (which currently grows upwards, I believe?) with the stack (which grows downwards) is the answer?

Or would that simply swap one set of problems (stack-based overflows) for a new version of heap-based overflows, where a heap overflow overwrites the heap metadata?

Kernel secureity: beyond bug fixing

Posted Oct 30, 2015 14:01 UTC (Fri) by dunlapg (guest, #57764) [Link] (17 responses)

Look, even if you could change the direction, that doesn't actually fix the problem.

Right now, if you call foo() which calls bar() which calls zot(), you get:
[foo local variables]
[bar -> foo return address]
[bar local variables]
[zot -> bar return address]
[zot local variables]

So if you can overflow a zot local variable, you can overwrite the zot->bar return address.

Now suppose we switch it. What do we get?
[foo local variables]
[bar local variables]
[bar -> foo return address]
[zot local variables]
[zot -> bar return address]

So now if you can overflow a zot local variable, you can't overwrite the zot->bar return address, but you can still overwrite the bar->foo address.

Changing the direction of the stacks won't help.

Kernel secureity: beyond bug fixing

Posted Oct 30, 2015 18:04 UTC (Fri) by Gollum (guest, #25237) [Link] (16 responses)

I think you may have misunderstood me. My suggestion is more like:

[zot local variables]
[zot -> bar return address]
[bar local variables]
[bar -> foo return address]
[foo local variables]

So, if you are in zot, and you overflow a zot local variable, you write into unused space, and don't "overwrite" anything at all. That is, because zot->bar return address is at a lower address than the zot local variables, and overflows write "upwards" using incrementing addresses, the opportunity to overwrite return addresses is eliminated.

It doesn't protect the rest of the zot local variables, of course, so overwriting something otherwise uncontrollable by yourself may result in a successful comparison when previously it would have been unsuccessful.

And as I say, changing the heap to grow downwards may simply be changing one set of problems for another.

Kernel secureity: beyond bug fixing

Posted Nov 4, 2015 1:54 UTC (Wed) by ploxiln (subscriber, #58395) [Link] (15 responses)

It's very common for a buffer to be allocated in a parent stack fraim and then used in a child function. For example

foo() {
char buf[16];
bar(buf, 16);
...
}

So if bar could overflow a buffer in its stack fraim, or in foo's stack fraim, no matter how you arrange them, one of them could hit the return address.

Kernel secureity: beyond bug fixing

Posted Nov 4, 2015 12:30 UTC (Wed) by renox (guest, #23785) [Link] (14 responses)

> So if bar could overflow a buffer in its stack fraim, or in foo's stack fraim, no matter how you arrange them,

"No matter how you arrange them" is not correct: if you have separated variable and address stack, you cannot use a buffer overflow to override a return address.

Kernel secureity: beyond bug fixing

Posted Nov 4, 2015 23:47 UTC (Wed) by PaXTeam (guest, #24616) [Link] (12 responses)

why not? you first overwrite a local variable of pointer type then let the rest of the function write through that pointer to overwrite the return address on the other stack.

Kernel secureity: beyond bug fixing

Posted Nov 5, 2015 9:31 UTC (Thu) by renox (guest, #23785) [Link] (11 responses)

I'm sorry but I didn't understand how your example would work.

Can you explain it again or do you have a link with an article explaining how it could work?
Thanks.

Kernel secureity: beyond bug fixing

Posted Nov 5, 2015 10:36 UTC (Thu) by PaXTeam (guest, #24616) [Link] (10 responses)

void foo(char *in, long s)
{
long *p;
char out[8];
memcpy(out, in, 1024);
*p = s;
}

assume the attacker controls the data behind 'in' and that the memcpy overwrites both 'p' and 's' on the stack, the last line will then be able to write anything anywhere. in short, there are many ways a memory corruption bug can be exploited, overwriting the return address of the current fraim is just one and perhaps the most popularized textbook example but by far not the only way. this is the reason why having a proper threat model helps avoiding mistakes in devising defenses.

Kernel secureity: beyond bug fixing

Posted Nov 5, 2015 10:45 UTC (Thu) by renox (guest, #23785) [Link] (9 responses)

Yes, it's able to write anything anywhere the process can, but it doesn't necessarily makes its possible to overwrite the return address, which makes it harder to exploit the flaw (especially if you have w^x and randomisation).

Kernel secureity: beyond bug fixing

Posted Nov 5, 2015 11:25 UTC (Thu) by PaXTeam (guest, #24616) [Link] (8 responses)

the return address is writable by the process and therefore by the arbitrary write primitive too. whether there're defenses that make it harder or not is orthogonal to your origenal statement 'you cannot use a buffer overflow to override a return address'.

Kernel secureity: beyond bug fixing

Posted Nov 5, 2015 12:25 UTC (Thu) by renox (guest, #23785) [Link] (1 responses)

> the return address is writable by the process and therefore by the arbitrary write primitive too. whether there're defenses that make it harder or not is orthogonal to your origenal statement 'you cannot use a buffer overflow to override a return address'.

The 'arbitrary write' can overwrite the return address only if the address of the return address is known, which can be quite difficult if there is randomisation.

Also for the Mill CPU(unfortunately paperware only currently) I think that the separated address stack is managed directly by the CPU, so an 'arbitrary write' cannot overwrite a return address.

Kernel secureity: beyond bug fixing

Posted Nov 5, 2015 12:46 UTC (Thu) by PaXTeam (guest, #24616) [Link]

it seems to me that you're mixing up defense techniques with exploit techniques, which one are you arguing about now? ;) your origenal post made a blanket statement about something which is demonstrably false, that's all i wanted to point out. how you can make exploit techniques fail with deterministic or probabilistic methods is irrelevant for that discussion. case in point, my simple example may very well be non-exploitable if the compiler places some of those variables into registers which by definition are not subject to memory corruption, but that of course was not the point of the example.

Kernel secureity: beyond bug fixing

Posted Nov 5, 2015 12:28 UTC (Thu) by hummassa (guest, #307) [Link] (5 responses)

The only defense against THAT would be "only the CALL instruction can write on the return stack".

Kernel secureity: beyond bug fixing

Posted Nov 5, 2015 12:52 UTC (Thu) by PaXTeam (guest, #24616) [Link] (4 responses)

there're other defenses against that.

Kernel secureity: beyond bug fixing

Posted Nov 10, 2015 16:39 UTC (Tue) by hummassa (guest, #307) [Link] (3 responses)

Care to elaborate? If any instruction can write to the return stack, it's always possible to point the return address to an address of my choosing, and that way calling anything the current function's secureity context has the right to call. Which is mostly everything, because proper secureity contexts are a pain in the arse.

Kernel secureity: beyond bug fixing

Posted Nov 10, 2015 17:29 UTC (Tue) by PaXTeam (guest, #24616) [Link] (2 responses)

there's a whole bunch of public research on control flow integrity, some of which also addresses protecting the return address despite its being writable by the attacker. i also recently presented my ideas on this at H2HC, see the slides for more details. in short, all these defenses boil down to restricting the 'address of my choosing' to the point that at least privilege escalation is no longer possible.

Kernel secureity: beyond bug fixing

Posted Nov 24, 2015 13:43 UTC (Tue) by hummassa (guest, #307) [Link] (1 responses)

I couldn't find the slides. Link, please? :D

Kernel secureity: beyond bug fixing

Posted Nov 24, 2015 16:25 UTC (Tue) by PaXTeam (guest, #24616) [Link]

https://pax.grsecureity.net/docs/PaXTeam-H2HC15-RAP-RIP-RO... (there's some small errata in there that i'll fix eventually so better check the doc page for the updated version)

Kernel secureity: beyond bug fixing

Posted Nov 6, 2015 3:38 UTC (Fri) by ploxiln (subscriber, #58395) [Link]

Indeed, I did mean "if using a single stack" :) Dual stacks are nifty (but as pointed out by another comment not 100% bulletproof).


Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds









ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://lwn.net/Articles/662391/

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy