Buffer overflows

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
nullify

Buffer overflows

Post by nullify »

This is just a thought on buffer overflows after reading the recent article on Slashdot/OSNews about the x86-64 'executable' bit preventing non-code pages from being executed.

If the stack were to grow upwards instead of downwards, buffer overflows would not be able to overwrite the return address of the stack (since any overflowing data gets written upwards, although the return address would be below the stack pointer). Since buffer overflows cannot overwrite the return address, no malicious code would be jumped to in the event of your typical buffer overflow exploit.

The only implication I can think of would be that the optimal organization of program memory like this:

[ code ] [ data ] --> free space <-- [ stack ]

would no longer be possible. What do you think of this? I have a feeling that I'm overlooking an important factor here, but I can't discern what it could be...
mystran

Re:Buffer overflows

Post by mystran »

nullify wrote:
The only implication I can think of would be that the optimal organization of program memory like this:
Just a wild idea, why not make it work this way instead:

Code: Select all

 <code> <stack> --> freespace <-- <data> 
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Buffer overflows

Post by Pype.Clicker »

it's not practical to change the direction of the stack's expansion because it is defined by the CPU instructions like Push/Pop Call/Ret Enter/Leave, etc.

The same way, having an expand-down heap isn't practical either because none of the realloc() calls are likely to succeed ...

The way you can protect against buffer overflow on a IA-32 architecture is to keep the code segment as small as your .text section is ... The protection isn't perfect though: there's no real need to write *code* to invoke "exec("sh")": you just have to replace the return address by the address of exec() and the word before that return address (thus the last argument of the function) with the pointer to the 'sh' string ...

Note also that the relocation information shipped in your executable lists all the 'regular' calls to library functions, so for 'sensible' functions calls (like exec), it could be theorically possible to cross-check that the 'return address' for that call comes from something that was foreseen at compile-time ...
Curufir

Re:Buffer overflows

Post by Curufir »

I still don't see why people are so incredibly set against levering the segmentation mechanism since, if using paging, they are already using it.

Split code, data, stack into three segments with appropriate permissions and individual ranges in the address space (With tweaking of segment base address it can look like a flat address space anyway). There is no extra overhead because you have to switch segments anyway in a context switch, and if using paging then you're already going through the segmentation translation step.

Ok, so it's not portable, but the chances of you being able to take your Mem Manager and dump it unchanged onto a different architecture are slim anyway. So long as you set things up so that everything else believes the address space is flat you limit the bits that aren't portable anyway.
nullify

Re:Buffer overflows

Post by nullify »

Pype.Clicker wrote:it's not practical to change the direction of the stack's expansion because it is defined by the CPU instructions like Push/Pop Call/Ret Enter/Leave, etc.
Yes, this is the big problem. Had Intel considered the implications of this beforehand, would a "stack expanding upwards" implementation have done the trick to minimize damage of buffer overflows on today's x86 systems?

On the other hand, I suppose Intel would be expecting OS writers to make use of its segmentation's executable flag to protect against arbitrary memory executed as code (as Curufir states).
Curufir wrote:Split code, data, stack into three segments with appropriate permissions and individual ranges in the address space (With tweaking of segment base address it can look like a flat address space anyway).
This is an interesting idea, although I don't see how the address space could be made to look flat without segments spanning the entire 4GB. Perhaps you could elaborate on this?
Curufir

Re:Buffer overflows

Post by Curufir »

nullify wrote: This is an interesting idea, although I don't see how the address space could be made to look flat without segments spanning the entire 4GB. Perhaps you could elaborate on this?
Eg

Code segment size 1Gb, Base 0
Data segment size 1Gb, Base 1gb
Stack segment size 1Gb, Base 2gb

Then the segmentation hardware handles logical -> linear address translation (Eg 0x100 in the data segment would produce a linear address of 1Gb+0x100 in the above example) then you head through paging for the linear -> physical translation. Admittedly in the example scheme the 4Gb address space has effectively been reduced to 1Gb (I left 1Gb for the kernel), but as far as anything outside the kernel knows the address space is just a flat 1Gb space. Doing this increases complexity in page management etc, but ensures absolutely that code/data is never going to be at risk from stack operations.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Buffer overflows

Post by Pype.Clicker »

if you want to execute a C program, you *must* have DS.base == SS.base.

Just consider how

Code: Select all

myFunction()
{
     structure *on_the_heap=malloc(sizeof(structure));
     structure on_the_stack;

      do_something(on_the_heap, &on_the_stack);
      do_something(&on_the_stack,on_the_heap);
}

do_something(structure *x, structure *y)
{
    x->field=y->field;
    y->otherfield=x->otherfield;
}
would be assembled: in do_something, the compiler has no clue about what's on the stack and what's on the heap. so the same referencing code should work for both ...


Also, having CS.base == DS.base is not a problem for security, as long as the pages that hold the code are read-only...
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Buffer overflows

Post by Solar »

And all this because coders are too lazy / dumb / unconcerned to use the "n" variants of functions... snprintf() instead of sprintf(), strncmp() instead of strcmp()... 8)
Every good solution is obvious once you've found it.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Buffer overflows

Post by Pype.Clicker »

fortunately enough, dumb programmers can now code in sandboxed environments ;D
Post Reply