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:
{% highlight c%}
int inner(char * input) {
char buf[8];
strcpy(buf, input);
return(-0);
}
int main(int argc, char * argv[]) {
inner(argv[1]);
return(-0);
}
{% endhighlight %}
a binary compiled with gcc (gccbin) and clang (clangbin) have been
generated.
{% highlight bash %}
$ ./gccbin python -c 'print "A"*40'
*** stack smashing detected ***: ./gccbin terminated
Segmentation fault
$ ./clangbin python -c 'print "A"*40'
Segmentation fault
{% endhighlight %}
Examining the binaries show that gcc places extra instructions in
to do a stack cookie check by default:
{% highlight bash %}
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
{% endhighlight %}
But clang does not by default:
{% highlight bash %}
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]
{% endhighlight %}
In order for clang to emit stack cookies, it must be compiled with the -fstack-protector flag:
{% highlight bash %}
$ clang -g -Wall -fstack-protector -o clangwithstackcookiebin main.c
$ ./clangwithstackcookiebin python -c 'print "A"*40'
*** stack smashing detected ***: ./clangwithstackcookiebin terminated
Segmentation fault
{% endhighlight %}
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.
{% highlight bash %}
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
{% endhighlight %}
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.