<aside>
💡 简单来看就是几条指令(pac*
, aut*
, xpac*
), 这些指令可以在CPU内部对地址做签名和验签(还有其他的,可以在文档找)
</aside>
paciasp
autiasp
pacia lr, sp
autia lr, sp
<aside>
💡 pac*
签名, aut*
验签, xpac*
将地址还原
</aside>
<aside> 💡 有了这些指令 ROP protection 就变得很简单:进入函数时增加一条指令对返回地址签名,ret 前对返回地址验签; 如果返回地址被修改则不会继续执行
</aside>
// ROP protection example
paciasp
stp fp, lr, [sp, #-FRAME_SIZE]!
mov fp, sp
< function body >
ldp fp, lr, [sp], #FRAME_SIZE
autiasp
ret
<aside>
💡 PAC(Pointer Authentication Code) 是对地址签名的结果,由指令(pac*
)生成,除了待签名的地址,还需要一个 128bit key 和一个 64 bit 的 context value; 其中 key 保存在系统寄存器中,context value 由具体的指令决定,比如 pacia x30, sp
就是将 sp
寄存器的值作为 context value 对x30
的值签名
</aside>
<aside> 💡 PAC 直接保存到被签名的地址中; 有两种方式: with tagging, 不破坏原来的地址(48-bit va 和 高位的 tag),把PAC保存在 reserved bits; without tagging 会破坏原来的地址,导致其不可直接访问;具体使用哪种取决于 PCA 长度(越长越安全)等具体的需要
</aside>