Why does "stack smashing detected" not appear immediately after smashing?
Asked Answered
S

2

5

I understand what is meant by "stack smashing detected". There are already a lot of questions here regarding this. But I didn't find an answer to the following question. Take the C code

int main(int argc, char **args) {
   char puffer[5];
   strcpy(puffer, *++args);
   printf("%s\n",puffer);
   return EXIT_SUCCESS;
}

When I compile with gcc 4.8.1 in Ubuntu 13.10 ./buffer 123456789 raises the expected error stack smashing detected. But why does ./buffer 12345678 raise no error? I would expect that every string with more than 5 chars should raise the error.

Shupe answered 27/3, 2014 at 20:6 Comment(1)
You might actually want -fmudflap or Valgrind.Scyphus
C
5

Theoretically you are right and that is how it should behave. The moment your program uses more than 5 bytes, this could lead to undefined behaviour. But often the stack pointer is aligned to certain boundaries for various performance reasons. Alignment varies from architecture to architecture. Hence you do not see this problem for every input which is larger than 5.

The disassembly of your program is displayed below. Check out the sub $0x20,%rsp instruction, which allocates 16 bytes of memory on the stack for this function.

(gdb) disassemble main
Dump of assembler code for function main(int, char**):
   0x00000000004008b0 <+0>: push   %rbp
   0x00000000004008b1 <+1>: mov    %rsp,%rbp
=> 0x00000000004008b4 <+4>: sub    $0x20,%rsp
   0x00000000004008b8 <+8>: mov    %edi,-0x14(%rbp)
   0x00000000004008bb <+11>:    mov    %rsi,-0x20(%rbp) 
  0x00000000004008bf <+15>: mov    %fs:0x28,%rax
   0x00000000004008c8 <+24>:    mov    %rax,-0x8(%rbp)
   0x00000000004008cc <+28>:    xor    %eax,%eax
   0x00000000004008ce <+30>:    addq   $0x8,-0x20(%rbp)
   0x00000000004008d3 <+35>:    mov    -0x20(%rbp),%rax
   0x00000000004008d7 <+39>:    mov    (%rax),%rdx
   0x00000000004008da <+42>:    lea    -0x10(%rbp),%rax
   0x00000000004008de <+46>:    mov    %rdx,%rsi
   0x00000000004008e1 <+49>:    mov    %rax,%rdi
   0x00000000004008e4 <+52>:    callq  0x400770 <strcpy@plt>
   0x00000000004008e9 <+57>:    lea    -0x10(%rbp),%rax
   0x00000000004008ed <+61>:    mov    %rax,%rdi
   0x00000000004008f0 <+64>:    callq  0x400710 <puts@plt>
   0x00000000004008f5 <+69>:    mov    $0x0,%eax
   0x00000000004008fa <+74>:    mov    -0x8(%rbp),%rcx
   0x00000000004008fe <+78>:    xor    %fs:0x28,%rcx
   0x0000000000400907 <+87>:    je     0x400918 <main(int, char**)+104>
   0x0000000000400909 <+89>:    jmp    0x400913 <main(int, char**)+99>
   0x000000000040090b <+91>:    mov    %rax,%rdi
   0x000000000040090e <+94>:    callq  0x400790 <_Unwind_Resume@plt>
   0x0000000000400913 <+99>:    callq  0x400760 <__stack_chk_fail@plt>
   0x0000000000400918 <+104>:   leaveq 
   0x0000000000400919 <+105>:   retq   
Chan answered 27/3, 2014 at 20:15 Comment(1)
Yes, 16 byte stack alignment for SSE2 instructions.Tightlipped
C
2

There are different stack smashing protections implemented by compilers but usually to prevent a stack overflow exploitation a canary is put right before the saved frame pointer and the return address. The canary is here to protect the overwriting of the saved frame pointer and the return address. Here basically there is some padding inserted by the compiler between the end of the buffer and the frame pointer / return address.

Credential answered 27/3, 2014 at 20:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.