C语言 使用金丝雀进行 BSS 或数据部分来检测溢出/粉碎有用吗?



在我们基于 GCC 的 C 嵌入式系统中,我们使用-ffunction-sections-fdata-sections选项来允许链接器在链接最终可执行文件时删除未使用(未引用(的部分。多年来,这很有效。

在同一系统中,大多数数据结构和缓冲区都是静态分配的(通常在文件范围内作为static变量(。

当然,我们有一些错误,有时是令人讨厌的错误,我们希望快速排除缓冲区溢出的可能性。

我们的一个想法是将金丝雀放在每个 bss-部分和数据部分之间 - 每个金丝雀只呈现一个符号(因为-fdata-sections(。就像编译器在激活堆栈粉碎和堆栈保护时对函数堆栈所做的那样。检查这些金丝雀可以通过"不时"读取金丝雀地址从主机完成。

似乎修改链接器脚本(手动放置该部分并在两者之间添加一个金丝雀词(似乎是可行的,但这有意义吗?

野外有项目或文章吗?使用我的关键字,我找不到任何东西。

Canary 对堆栈最有用,因为它的扩展和折叠超出了程序员的直接控制范围。您在数据/bss 上拥有的东西不会那样表现。它们要么是静态变量,要么如果它们是缓冲区,它们应该保持在固定大小内,这应该通过算法的防御性编程进行检查,而不是非正统的技巧。

此外,堆栈金丝雀专门用于基于 RAM 的类似 PC 的系统,这些系统不知道更好的方法。在嵌入式系统中,它们不是很有意义。您可以改为执行一些有用的操作:

  • 内存映射堆栈,使其增长到内存区域,写入将产生硬件异常。例如,如果您的MCU能够将可执行存储器与数据存储器分开,并且如果您尝试在数据区域中执行代码或写入可执行区域,则会产生异常。
  • 确保程序中处理缓冲区的所有内容都执行其错误检查,而不是越界写入。静态分析工具通常可以很好地发现越界错误。甚至一些编译器也可以做到这一点。
  • 使用静态断言添加大量防御性编程。在编译时检查结构、缓冲区等的大小,它是免费的。
  • 运行时防御性编程。例如,if(x==good) {...} else if(x == bad) {... }缺少elseswitch(x) case A: { ... }缺少一个default."但理论上它不能去那里!"不,但在实践中,当您得到由错误(很可能(、闪存的数据保留(100% 可能(或 EMI 对 RAM 的影响(不太可能(引起的失控代码时。
  • 等等。

相关内容

  • 没有找到相关文章

最新更新