Hello,

It's nice to see a more security-minded release of gcc with v4.
Variables are moved around to reduce chances for exploitation,
-fstack-protector, etc. Great!

Why are local variables once-again adjacent to the saved frame pointer
though? gcc v 2 called and wants one of its "features" back.

func(char *b){
char buf[512];
if( strlen(b) > sizeof buf) return;
strcpy(buf, b);
}

0x080483a7 <func+3>:    sub    $0x208,%esp
0x080483ad <func+9>:    mov    0x8(%ebp),%eax
0x080483b0 <func+12>:   mov    %eax,0x4(%esp)
0x080483b4 <func+16>:   lea    0xfffffe00(%ebp),%eax
0x080483ba <func+22>:   mov    %eax,(%esp)
0x080483bd <func+25>:   call   0x80482e8 <[EMAIL PROTECTED]>
0x080483c2 <func+30>:   leave
0x080483c3 <func+31>:   ret

0x208 = 520 bytes; alright padding can be useful
0xfffffe00(%ebp) = -512 + ebp.

OOPS! In effect the padding is no longer in between the saved frame
pointer and the local vars.

I've seen this in various versions of gcc 4.

Gcc 3 would have placed this padding between the saved frame pointer
and the local vars. Here's the result from gcc 3.4:
0x08048367 <func+3>:    sub    $0x218,%esp
...
0x08048374 <func+16>:   lea    0xfffffdf8(%ebp),%eax

Thats -520+ebp. It also takes a little bit more padding.


Any good reason NOT to pad between the local vars and control data?


P.S. check out this cute rendition from gcc 4.1.1:

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]){
   char buf[512];
   if(strlen(argv[1]) <= sizeof buf)   strcpy(buf, argv[1]);
}

Dump of assembler code for function main:
0x080483a4 <main+0>:    lea    0x4(%esp),%ecx
0x080483a8 <main+4>:    and    $0xfffffff0,%esp
0x080483ab <main+7>:    pushl  0xfffffffc(%ecx)
0x080483ae <main+10>:   push   %ebp
0x080483af <main+11>:   mov    %esp,%ebp
0x080483b1 <main+13>:   push   %edi
0x080483b2 <main+14>:   push   %ecx
0x080483b3 <main+15>:   sub    $0x210,%esp
0x080483b9 <main+21>:   mov    %ecx,0xfffffdf4(%ebp)
0x080483bf <main+27>:   mov    0xfffffdf4(%ebp),%edx
0x080483c5 <main+33>:   mov    0x4(%edx),%eax
0x080483c8 <main+36>:   add    $0x4,%eax
0x080483cb <main+39>:   mov    (%eax),%eax
0x080483cd <main+41>:   mov    $0xffffffff,%ecx
0x080483d2 <main+46>:   mov    %eax,0xfffffdf0(%ebp)
0x080483d8 <main+52>:   mov    $0x0,%al
0x080483da <main+54>:   cld
0x080483db <main+55>:   mov    0xfffffdf0(%ebp),%edi
0x080483e1 <main+61>:   repnz scas %es:(%edi),%al
0x080483e3 <main+63>:   mov    %ecx,%eax
0x080483e5 <main+65>:   not    %eax
0x080483e7 <main+67>:   dec    %eax
0x080483e8 <main+68>:   cmp    $0x200,%eax
0x080483ed <main+73>:   ja     0x804840f <main+107>
0x080483ef <main+75>:   mov    0xfffffdf4(%ebp),%edx
0x080483f5 <main+81>:   mov    0x4(%edx),%eax
0x080483f8 <main+84>:   add    $0x4,%eax
0x080483fb <main+87>:   mov    (%eax),%eax
0x080483fd <main+89>:   mov    %eax,0x4(%esp)
0x08048401 <main+93>:   lea    0xfffffdf8(%ebp),%eax
0x08048407 <main+99>:   mov    %eax,(%esp)
0x0804840a <main+102>:  call   0x80482e8 <[EMAIL PROTECTED]>
0x0804840f <main+107>:  add    $0x210,%esp
0x08048415 <main+113>:  pop    %ecx <----immediate control
0x08048416 <main+114>:  pop    %edi                   |
0x08048417 <main+115>:  pop    %ebp                 V
0x08048418 <main+116>:  lea    0xfffffffc(%ecx),%esp
0x0804841b <main+119>:  ret
0x0804841c <main+120>:  nop


esp can be controlled controlled right away before the "ret"
instruction. This new prologue/epilogue opened up a fun new
possibility for an off-by-one in main().

One final question, what is the purpose of this new prologue and
epilogue for main?
Why re-align the stack and push the saved ret to a new place [pushl
0xfffffffc(%ecx)]  if you're going to just use the old one anyway [
lea    0xfffffffc(%ecx),%esp] ???


have phuN!

Reply via email to