39

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?

8
  • 32
    Pedantic note: a "byte" is always exactly one byte in size. ;-)
    – 5gon12eder
    Jan 23, 2017 at 0:24
  • 13
    What's a "canary" byte? This is now the top result in Google, but it doesn't explain anything! Some appropriate tags would probably help too... Jan 23, 2017 at 12:05
  • 6
    For anyone wondering what is a canary byte, they are used to protect against buffer overflow. Jan 23, 2017 at 13:43
  • 5
    I'm actually amazed this question in its current form managed to get 11 upvotes. It's a one-line question, the question itself contains incorrect terminology (canary byte, whereas the correct term is canary word), and the question body consists of nothing but extraneous details (the only relevant detail being it "has something to do with stackoverflow[s]", which was information already contained in the question's tags anyway). Since it did get this much attention though... time for some edits I guess.
    – Ajedi32
    Jan 23, 2017 at 14:20
  • 6
    @Ajedi32 once a question hits HNQ, all bets are off. The traffic it gets is not from site regulars, and their criteria for the votes cause what you are seeing here. Jan 23, 2017 at 14:54

3 Answers 3

59

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.

4
  • 9
    It's not (just) the x suffix that makes them 64-bit wide. eax is 32-bit. It's the fact that it uses the r prefix and the x suffix. Jan 23, 2017 at 8:41
  • 3
    @Angew Actually it is not even that (e.g. rdi is 64-bit, movzx can load a byte into a 64-bit reg, etc.). It is the movq :) Jan 23, 2017 at 11:42
  • @MargaretBloom Sure, talking about the x suffix applies only to registers for which the x suffix exists. Jan 23, 2017 at 11:55
  • @Angew You are right, thanks. (And I've also messed up the comments added to the assembly.) I have corrected the answer now.
    – 5gon12eder
    Jan 23, 2017 at 15:44
25

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

2

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.

1
  • 4
    this is already covered by the other answers
    – schroeder
    Jan 23, 2017 at 17:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .