Clang does not compile with stack cookies by default.



Just a bit of warning about clang. By the default state the clang compiler does not install stack cookie checks to its function calls.

Given a simple function that managers buffers:

int inner(char * input) {
    char buf[8];
    strcpy(buf, input);
    return(-0);
}
 
int main(int argc, char * argv[]) {
    inner(argv[1]);
    return(-0);
}

a binary compiled with gcc (gccbin) and clang (clangbin) have been generated.

$ ./gccbin `python -c 'print "A"*40'`
*** stack smashing detected ***: ./gccbin terminated
Segmentation fault

$ ./clangbin `python -c 'print "A"*40'`
Segmentation fault

Examining the binaries show that gcc places extra instructions in to do a stack cookie check by default:

0000000000400564 :
  400564:       55                      push   rbp
  400565:       48 89 e5                mov    rbp,rsp
  400568:       48 83 ec 20             sub    rsp,0x20
  40056c:       48 89 7d e8             mov    QWORD PTR [rbp-0x18],rdi
  400570:       64 48 8b 04 25 28 00    mov    rax,QWORD PTR fs:0x28
  400577:       00 00 
  400579:       48 89 45 f8             mov    QWORD PTR [rbp-0x8],rax
  40057d:       31 c0                   xor    eax,eax
  40057f:       48 8b 55 e8             mov    rdx,QWORD PTR [rbp-0x18]
  400583:       48 8d 45 f0             lea    rax,[rbp-0x10]
  400587:       48 89 d6                mov    rsi,rdx
  40058a:       48 89 c7                mov    rdi,rax
  40058d:       e8 be fe ff ff          call   400450 
  400592:       b8 00 00 00 00          mov    eax,0x0
  400597:       48 8b 55 f8             mov    rdx,QWORD PTR [rbp-0x8]
  40059b:       64 48 33 14 25 28 00    xor    rdx,QWORD PTR fs:0x28
  4005a2:       00 00 
  4005a4:       74 05                   je     4005ab 
  4005a6:       e8 b5 fe ff ff          call   400460 
  4005ab:       c9                      leave  
  4005ac:       c3                      ret   

But clang does not by default:

0000000000400500 :
  400500:       55                      push   rbp
  400501:       48 89 e5                mov    rbp,rsp
  400504:       48 83 ec 20             sub    rsp,0x20
  400508:       48 8d 45 f0             lea    rax,[rbp-0x10]
  40050c:       48 89 7d f8             mov    QWORD PTR [rbp-0x8],rdi
  400510:       48 8b 75 f8             mov    rsi,QWORD PTR [rbp-0x8]
  400514:       48 89 c7                mov    rdi,rax
  400517:       e8 d4 fe ff ff          call   4003f0 
  40051c:       b9 00 00 00 00          mov    ecx,0x0
  400521:       48 89 45 e8             mov    QWORD PTR [rbp-0x18],rax
  400525:       89 c8                   mov    eax,ecx
  400527:       48 83 c4 20             add    rsp,0x20
  40052b:       5d                      pop    rbp
  40052c:       c3                      ret    
  40052d:       0f 1f 00                nop    DWORD PTR [rax]

In order for clang to emit stack cookies, it must be compiled with the -fstack-protector flag:

$ clang -g -Wall -fstack-protector -o clangwithstackcookiebin main.c

$ ./clangwithstackcookiebin `python -c 'print "A"*40'`
*** stack smashing detected ***: ./clangwithstackcookiebin terminated
Segmentation fault

And as we can see from the disassembly, the stack cookie value (taken from fs:0x28 on intel 64 bit) is used as a stack cookie.

0000000000000000 :
   0:   55                      push   rbp
   1:   48 89 e5                mov    rbp,rsp
   4:   48 83 ec 30             sub    rsp,0x30
   8:   64 48 8b 04 25 28 00    mov    rax,QWORD PTR fs:0x28
   f:   00 00 
  11:   48 89 45 f8             mov    QWORD PTR [rbp-0x8],rax
  15:   48 89 7d f0             mov    QWORD PTR [rbp-0x10],rdi
  19:   48 8d 45 e8             lea    rax,[rbp-0x18]
  1d:   48 89 7d e0             mov    QWORD PTR [rbp-0x20],rdi
  21:   48 89 c7                mov    rdi,rax
  24:   48 8b 75 e0             mov    rsi,QWORD PTR [rbp-0x20]
  28:   e8 00 00 00 00          call   2d 
  2d:   64 48 8b 34 25 28 00    mov    rsi,QWORD PTR fs:0x28
  34:   00 00 
  36:   48 8b 7d f8             mov    rdi,QWORD PTR [rbp-0x8]
  3a:   48 39 fe                cmp    rsi,rdi
  3d:   48 89 45 d8             mov    QWORD PTR [rbp-0x28],rax
  41:   0f 85 0b 00 00 00       jne    52 
  47:   b8 00 00 00 00          mov    eax,0x0
  4c:   48 83 c4 30             add    rsp,0x30
  50:   5d                      pop    rbp
  51:   c3                      ret    
  52:   e8 00 00 00 00          call   57 
  57:   66 0f 1f 84 00 00 00    nop    WORD PTR [rax+rax*1+0x0]
  5e:   00 00 

This may be relevant for people replacing gcc in their make scripts with clang (e.g. replacing CXX=gcc with CXX=clang). By default the stack cookie protection on gcc is built in, on clang it is not.