gcc canaries : undefined reference to __stack_chk_guard

21,983

Solution 1

It would appear that the -mstack-protector-guard option is only for backwards compatibility with how the stack protector worked in the past. In the past the canary was in a global variable. Later it was switched to TLS. It would appear that the operating system / libc you use either removed or never had support for the global variable canary, so only TLS works.

Don't touch the -mstack-protector-guard option and everything should work. The default should be fine when you use -fstack-protector-all.

Solution 2

Provide __stack_chk_guard with a random value in c file, avoid using regular values like all zero's or FF's because the stack can easily get these values during any memory operation. Wiki on providing magic number implementation. This __stack_chk_guard will be placed at the top and bottom of the stack, which will be checked during every stack access. Any change in the value implies a corrupted stack and returns with error providing the stack protection.

unsigned long __stack_chk_guard;
void __stack_chk_guard_setup(void)
{
     __stack_chk_guard = 0xBAAAAAAD;//provide some magic numbers
}

void __stack_chk_fail(void)                         
{
 /* Error message */                                 
}// will be called when guard variable is corrupted 

Solution 3

There are two ways to remove this error: 1. From the compiler option disable(comment out) the "stack guard".

  1. Define __stack_chk_guard in you c file.

When you define __stack_chk_guard make sure you provide random value to it. For providing random value you need to pass as an argument to the random function.

For any further detail you can refer to the compiler manual.

Solution 4

For those that get this error in bare metal software development with a custom linker script, make sure to pass the option -nostdlib option:

gcc -nostdlib

since Ubuntu 16.04 for example enables the stack protection by default on the compiler. man gcc says:

NOTE: In Ubuntu 14.10 and later versions, -fstack-protector-strong is enabled by default for C, C++, ObjC, ObjC++, if none of -fno-stack-protector, -nostdlib, nor -ffreestanding are found.

-fno-stack-protector also solved it for me, but you should likely tell your poor compiler that you are doing baremetal stuff to prevent other such problems.

I'm guessing this is because the feature relies on symbols which are normally defined if a linker script is not given? But TODO I found no mention of those symbols by dumping the default linker script with:

aarch64-linux-gnu-gcc -Wl,-verbose main.c

so I'm not sure.

I grepped GCC 6.4.0 source code and it suggests that the symbol comes from libgcc2.c at gcc/doc/tm.texi:

The default version of this hook creates a variable called @samp{__stack_chk_guard}, which is normally defined in @file{libgcc2.c}.

Share:
21,983

Related videos on Youtube

Jérémy Pouyet
Author by

Jérémy Pouyet

Updated on July 29, 2022

Comments

  • Jérémy Pouyet
    Jérémy Pouyet almost 2 years

    I'm trying to enable gcc' s canaries' generation but I get an undefined reference to __stack_chk_guard.

    From gcc's man about canaries :

    -mstack-protector-guard=guard
           Generate stack protection code using canary at guard.  Supported locations are global for
           global canary or tls for per-thread canary in the TLS block (the default).  This option
           has effect only when -fstack-protector or -fstack-protector-all is specified.
    
       These -m switches are supported in addition to the above on x86-64 processors in 64-bit
       environments.
    

    I've done this test program :

    #define VALUE 2048
    int    main()
    {
      char arr[VALUE];
      int  i;
    
      for (i = 0; i < VALUE + 15; i++) // "i < VALUE + 15" is to test if canaries works but the code doesn't compile anymore with "i < 10" 
        arr[i] = '0';
      return 0;
    }
    

    As said in gcc's man, my compilation line is :

    gcc main.c -fstack-protector-all -mstack-protector-guard=global
    

    But I get the following error :

    /tmp/ccXxxxVd.o: In function `main':
    main.c:(.text+0xe): undefined reference to `__stack_chk_guard'
    main.c:(.text+0x51): undefined reference to `__stack_chk_guard'
    collect2: error: ld returned 1 exit status
    

    How can I remove this error ?

    EDIT:

    • OS: ubuntu 14.10 utopic
    • architecture: x86-64
    • environments: 64-bit
  • Peter Cordes
    Peter Cordes about 3 years
    Don't use a constant; that would be easily defeated by buffer overflows. (Especially in 32-bit build where long is 32-bit, so none of the bytes are 00, so the whole 32-bit constant can simply be part of a the exploit string for a strcpy buffer overflow. Other kinds of buffer overflows have other bytes that need to be avoided.) You want this to be initialized to a different random value every run, so attackers won't know ahead of time what it is even if they have the same build of the binary. Definitely not a recognizable Magic Number!
  • Peter Cordes
    Peter Cordes about 3 years
    That's why there's a setup function, instead of just providing a static initializer like long foo = 0x1234;. I think __stack_chk_guard_setup gets called by init functions before main runs, so you don't need a static initializer to get it initialized before any functions use it as a stack cookie. (If you did change it after a function used it, on return it would false-positive detect stack smashing.)

Related