my gcc version is 4.8.2 and operating system is ubuntu 14.04 (64 bit). I found that sometimes gcc auto generate the canary to do buffer overflow protection sometimes not, why?
case to generate canary: when SIZE is multiple of four
#include<stdio.h>
#define SIZE 4
int main()
{
char s[SIZE];
scanf("%s", s);
return 0;
}
asm after gcc -c -g -Wa,-a,-ad
...
4:a.c **** int main()
5:a.c **** {
13 .loc 1 5 0
14 .cfi_startproc
15 0000 55 pushq %rbp
16 .cfi_def_cfa_offset 16
17 .cfi_offset 6, -16
18 0001 4889E5 movq %rsp, %rbp
19 .cfi_def_cfa_register 6
20 0004 4883EC10 subq $16, %rsp
21 .loc 1 5 0
22 0008 64488B04 movq %fs:40, %rax
22 25280000
22 00
23 0011 488945F8 movq %rax, -8(%rbp)
24 0015 31C0 xorl %eax, %eax
6:a.c **** char s[SIZE];
7:a.c **** scanf("%s", s);
...
case not to generate canary : not the multiple of four
#include<stdio.h>
#define SIZE 2
int main()
{
char s[SIZE];
scanf("%s", s);
return 0;
}
asm after gcc -c -g -Wa,-a,-ad
...
4:a.c **** int main()
5:a.c **** {
13 .loc 1 5 0
14 .cfi_startproc
15 0000 55 pushq %rbp
16 .cfi_def_cfa_offset 16
17 .cfi_offset 6, -16
18 0001 4889E5 movq %rsp, %rbp
19 .cfi_def_cfa_register 6
20 0004 4883EC10 subq $16, %rsp
6:a.c **** char s[SIZE];
7:a.c **** scanf("%s", s);
...
OK, I guess we know the answer from comments, so I'll post it here to state it explicitly.
Putting canaries in a lot of functions can result in performance degradation. That's why there are several ways to tell GCC we want to use them, which are described well here. Main ideas:
-fstack-protector
flag: add canaries for functions that use alloca
or local buffers larger than 8
bytes (by default).ssp-buffer-size
parameter: --param ssp-buffer-size=4
.Apparently Ubuntu ships version of GCC with size of buffer changed to 4
, so buffers less than that don't trigger generation of a canary. I confirm (and anyone else should be able to repeat) that by compiling two examples with --param ssp-buffer-size=4
, which produces assembly with canaries for only one of them.