gcc canaries:对__stack_chk_guard的未定义引用

时间:2014-12-04 09:12:07

标签: c gcc compilation

我正在尝试启用gcc的canary'代,但我得到了一个未定义的__stack_chk_guard引用。

来自gcc的关于金丝雀的人:

-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.

我已经完成了这个测试程序:

#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;
}

正如gcc的男人所说,我的编译行是:

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

但是我收到以下错误:

/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

如何删除此错误?

编辑:

  • OS:ubuntu 14.10 utopic
  • 架构:x86-64
  • 环境:64位

4 个答案:

答案 0 :(得分:3)

-mstack-protector-guard选项似乎只是为了向后兼容堆栈保护器过去的工作方式。在过去,金丝雀是一个全球变量。后来它被改为TLS。您使用的操作系统/ libc似乎已被删除或从未支持全局变量canary,因此只有TLS可以工作。

请勿触摸-mstack-protector-guard选项,一切正常。使用-fstack-protector-all时,默认值应该没问题。

答案 1 :(得分:1)

有两种方法可以消除此错误:1。从编译器选项中禁用(注释掉)&#34;堆栈保护&#34;。

  1. 在您的c文件中定义__stack_chk_guard。
  2. 定义__stack_chk_guard时,请确保为其提供随机值。要提供随机值,您需要将其作为参数传递给随机函数。

    有关更多详细信息,请参阅编译器手册。

答案 2 :(得分:1)

对于那些使用自定义链接程序脚本在裸机软件开发中遇到此错误的用户,请确保通过选项-nostdlib

gcc -nostdlib

例如,因为Ubuntu 16.04默认在编译器上启用堆栈保护。 man gcc说:

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也为我解决了此问题,但您可能应该告诉您的编译器您正在做裸机操作,以防止发生其他此类问题。

我猜这是因为如果未提供链接描述文件,该功能依赖于通常定义的符号?但是TODO通过转储默认的链接描述文件并没有发现这些符号:

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

所以我不确定。

我提取了GCC 6.4.0源代码,它表明该符号来自libgcc2.c处的gcc/doc/tm.texi

  

此挂钩的默认版本会创建一个名为   @samp {__ stack_chk_guard},通常在@file {libgcc2.c}中定义。

答案 3 :(得分:0)

__stack_chk_guard中为c文件提供一个随机值,避免使用诸如全零或FF之类的常规值,因为堆栈可以在任何内存操作期间轻松获得这些值。 Wiki关于提供幻数实现。 __stack_chk_guard将放置在堆栈的顶部和底部,在每次访问堆栈时都会对其进行检查。值的任何更改都表示堆栈已损坏,并以提供堆栈保护的错误返回。

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