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?

Ajedi32
  • 4,637
  • 2
  • 26
  • 60
MR.X_XD
  • 501
  • 1
  • 4
  • 5
  • 32
    Pedantic note: a "byte" is always exactly one byte in size. ;-) – 5gon12eder Jan 23 '17 at 00:24
  • 2
    That means it's a trick question. – Michael Hampton Jan 23 '17 at 06: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... – curiousdannii Jan 23 '17 at 12:05
  • 6
    [For anyone wondering what is a _canary byte_](https://en.wikipedia.org/wiki/Buffer_overflow_protection#Canaries), they are used to protect against buffer overflow. – TonioElGringo Jan 23 '17 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 '17 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. – Mindwin Jan 23 '17 at 14:54
  • 2
    @Ajedi32 Normally I'd reject an edit as big as that... but it removes the fluff and replaces it with a minimum of research. Voted to Approve the edit. Especially since it's in HNQ, better to show casual visitors the kind of question that we actually _want_ to see. – S.L. Barth Jan 23 '17 at 14:58
  • @S.L.Barth Yeah, I wasn't sure it'd be approved since I ended up having to pretty much rewrite the entire question in my own words. I think the end result is a definite improvement though, and the relevant part of the OP's original question (which was just a single sentence) _is_ still there. – Ajedi32 Jan 23 '17 at 16:00

3 Answers3

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.

5gon12eder
  • 810
  • 5
  • 10
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.

async3
  • 121
  • 1