我遇到了 clang 编译器标志的奇怪行为
-mbranch-protection=pac-ret+bti
。通过查看文档,预期行为似乎会生成 PAC (paciasp)
以及 BTI
指令。使用 paciasp
编译时,我在程序集中看到 BTI
指令,但没有看到 -mbranch-protection=pac-ret+bti
指令。
使用
-mbranch-protection=bti
进行编译时,会在函数开头生成 BTI
指令,标记函数中的有效入口点。
这似乎有点不寻常。
PAC
可防止 ROP 攻击,而 BTI
可防止 JOP 攻击。这是实施中的错误吗?任何进一步的澄清将不胜感激。
请注意,从
BTI
开始支持 armv8.5-a
,从 PAC
开始支持 armv8.3-a
。编译器将为之前的架构生成 nop
。测试使用的是Clang 12.0版本。
简单代码示例(test.c):
#include<stdio.h>
int main(int argc, char** argv){
printf("%s", "Hello Main!");
}
PAC+BTI编译:
$ clang -S -mbranch-protection=pac-ret+bti -arch arm64e -march=armv8.7-a -o test.s test.c
输出:
main:
paciasp
-----
-----
-----
retaa
注意:这种情况下不会生成 BTI 指令。
与BTI编译:
clang -S -mbranch-protection=bti -arch arm64e -march=armv8.7-a -o test.s test.c
输出:
main:
bti c
-----
-----
-----
当使用 BTI 激活 PAC 时,paciasp 指令也充当着陆垫(类似 BTI)。这是 ARM 为节省一条额外指令而进行的优化。没有错误。