A canary word is a sequence of bits placed at the boundary between a buffer (such as a stack) and control data in a program, as a way of detecting and reacting to buffer overflows.
How many bits long are these canaries on Linux, usually?
A canary word is a sequence of bits placed at the boundary between a buffer (such as a stack) and control data in a program, as a way of detecting and reacting to buffer overflows.
How many bits long are these canaries on Linux, usually?
Let's try it out! Here is a very simple example program.
int test(int a)
{
return a;
}
Compile it with GCC and intercept the compilation at the assembly stage. (The -S
flag will do this.) Rename the assembly file (so it won't be overwritten) and compile again, this time also adding the -fstack-protector-all
and -mstack-protector-guard=global
flags. The first flag enables stack canaries for all functions, the second selects a global canary instead of a thread-local one. (The thread-local default is probably more useful in practice but the assembly for the global version is easier to understand.)
Comparing the two generated assembly files, we spot the following addition (comments are mine).
movl %edi, -20(%rbp) ; save function parameter onto stack (unrelated to canary)
movq __stack_chk_guard(%rip), %rax ; load magic value into RAX register
movq %rax, -8(%rbp) ; save RAX register onto stack (place the canary)
movl -20(%rbp), %eax ; load function parameter into EAX register for return (unrelated to canary)
movq -8(%rbp), %rcx ; load canary value into RCX register
movq __stack_chk_guard(%rip), %rdx ; load magic value into RDX register
cmpq %rdx, %rcx ; compare canary value to expected value
je .L3 ; if they are the same, jump to label .L3 (continue)
call __stack_chk_fail ; otherwise (stack corruption detected), call the handler
.L3:
leave
We can see that the canary is handled in the RAX, RCX and RDX registers which are all 64 bit wide. (Their 32 bit counterparts would be named EAX, EBX and EDX. The 16 bit versions are named AX, BX and CX. The 8 bit variants AL, BL and CL.) Another clue is that the operations to store, load and compare the canary (MOVQ and CMPQ) have a 'Q' suffix which identifies a 64 bit instruction. (32 bit instructions have an 'L' suffix, 16 bit instructions a 'W' and 8 bit versions a 'B'.)
Hence, we conclude that the canary is a 64 bit value, which makes sense on a 64 bit architecture (x86_64 GNU/Linux in my case). I expect that they'll always use the native word size as it makes the most sense to me. You can try the same experiment on your machines and see what you'll get.
As i can read in this page: Stack Smashing Protector
The stack canary is native word sized and if chosen randomly, an attacker will have to guess the right value among 2^32 or 2^64 combinations
The number of bits used must equal the Word size of the processor. So if you have a 32 bits processor, its Word size is 32, hence the canary word is 32 bits long.