【问题标题】:GCC's stack protection feature with optimization levels具有优化级别的 GCC 堆栈保护功能
【发布时间】:2019-08-11 05:40:05
【问题描述】:

我正在对 GCC 的堆栈保护功能进行一些实验以更好地理解它。基本上我指的是this post on stackoverflow

以下是我的代码。

test.c

#include <stdio.h>

void write_at_index(char *arr, unsigned int idx, char val)
{
    arr[idx] = val;
    printf("\n%s %d arr[%u]=%d\n", __func__, __LINE__,
        idx, arr[idx]);
}

void test_stack_overflow()
{
    char a[16] = {0}; //Array of 16 bytes.

    write_at_index(a, 30/*idx*/, 10/*val*/); //Ask the other function to access 30th index.

    printf("\n%s %d Exiting a[0] %d\n", __func__, __LINE__, a[0]);
}

int main()
{
    test_stack_overflow();
    return 0;
}

以下是我的makefile。

生成文件

CC=gcc

BIN=./test.out

SRCS=./test.c

all: $(BIN)

OBJ = ${SRCS:.c=.o}

CFLAGS=-O0 -fstack-protector -fstack-protector-all

$(OBJ): %.o: %.c
    $(CC) $(CFLAGS) $(INCLUDES) -c $*.c -o $*.o

$(BIN): $(OBJ)
    $(CC) -o $@ $<
    rm -rf ./*.o

clean:
    rm -rf ./*.out
    rm -rf ./*.o

我正在使用 gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0

当我构建并运行 test.out 时,我得到“检测到堆栈粉碎”的崩溃。

但是,如果我将优化级别更改为 O3,(CFLAGS=-O3 -fstack-protector -fstack-protector-all) 并构建并执行 test.out,我不会观察到崩溃。

所以我的问题是,启用优化时编译器是否会删除“-fstack-protector”选项?还是我在这里遗漏了一些其他设置?

【问题讨论】:

  • 行为是未定义。由于实际上不需要任何数组写入,因此可以优化数组并且不需要发生堆栈粉碎。
  • 优化足够好,可以去掉导致栈崩溃的汇编代码。
  • 函数前缀static,使用Godbolt探索
  • @AnttiHaapala:只是为了理解 - 我在 write_at_index() 中打印数组 [index]。所以需要写数组对吧?
  • 您的代码可以替换为puts("\nwrite_at_index 6 arr[30]=10\n\ntest_stack_overflow 16 Exiting a[0] 0"),没有人会注意到任何区别。

标签: c gcc stack


【解决方案1】:

在更高的优化级别,write_at_index 内联到test_stack_overflow,并且 GCC 检测到整个数组 a 没有以任何有意义的方式使用,并将其消除。结果,存储到数组中和相关的缓冲区溢出都消失了。您必须添加一个编译器屏障来防止这种情况发生。

此外,单字节溢出只有在设法命中金丝雀(或返回地址)时才会触发堆栈保护器崩溃。所以它们不是练习堆栈溢出检测代码的好方法。

【讨论】:

    猜你喜欢
    • 2015-01-16
    • 2010-12-19
    • 1970-01-01
    • 2010-11-23
    • 1970-01-01
    • 1970-01-01
    • 2020-12-03
    • 1970-01-01
    相关资源
    最近更新 更多