我按照 AAPCS64 调用约定编写了一些 arm64 汇编代码。
现在我想将此代码集成到启用了 PAC 和 BTI 的 C/C++ 项目中。当链接器告诉我缺少以下GNU_PROPERTY_AARCH64_FEATURE_1_BTI
属性时,我第一次注意到麻烦:
ld: error: md5block_arm64.o: -z bti-report: file does not have GNU_PROPERTY_AARCH64_FEATURE_1_BTI property
虽然设置此属性很简单,但我知道我可能需要更改部分代码以使其能够识别 PAC/BTI。为此需要进行哪些更改?我对可以用作调整任何代码指南的一般答案感兴趣,因此这个问题中缺少需要调整的代码。
BTI 非常简单,并且不依赖于软件 ABI(除了首先启用 BTI)。在手册
K.a
的当前版本 ()中,该行为记录在“D8.4.5.3 PSTATE.BTYPE”一节中。本质上:前向边缘分支指令分为两类:
br
,braa
,braaz
,brab
和brabz
blr
,,,,,blraa
blraaz
blrab
blrabz
我将使用
br
和blr
作为这些类别的简写。有三条新指令:
bti c
、bti j
和bti jc
。blr
分支必须落在bti c
或bti jc
指令上。br
x16
使用除and之外的寄存器x17
作为目标地址的分支必须落在bti j
orbti jc
指令上。br
使用x16
或x17
作为目标地址的分支可以落在任何bti
指令上。paciasp
并pacibsp
充当bti c
或bti jc
基于SCTLR_ELn
相关翻译机制中的一些位 - 只是假设bti c
是安全的。因此为了与 BTI 代码兼容,您必须:
paciasp
,pacibsp
或前缀bti c
。br
调用实际函数的调用和导入)使用x16
或x17
。bti j
到 switch-style 的所有可能目标br
。PAC 完全不同。这取决于堆栈中所有内容
gnu
的确切 ABI - vsmusl
、C vs C++、__attribute__
头文件中的说明符……AAPCS64规范根本没有定义指针认证 ABI。PAUTHELF64对于如何以 ELF 文件格式对内容进行编码有一些定义,但关键的是,它没有定义如何选择这些内容。
基本上,任何代码指针合成、任何间接分支、甚至潜在的内存加载都可能需要 PAC 指令 - 完全由实现定义。
现在,幸运的是,您
-mbranch-protection=standard
似乎几乎不用 PAC。从标志的文档中可以看出:基本上,这仅使用 PAC 来保护堆栈框架,这根本不会影响不同编译单元之间的 ABI。如果您想维护选项的安全属性,那么所有溢出的函数在溢出之前
x30
都需要一个,在重新加载和之间需要一个。(如果您的代码不需要在没有 PAC 支持的硬件上运行,您可以将 + 组合成一个)。paciasp
autiasp
ret
autiasp
ret
retaa