[compiler-rt] [libcxxabi] [libunwind] [runtimes][PAC] Harden unwinding when possible (#138571) (PR #143230)
Oliver Hunt via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 18 01:14:41 PDT 2025
================
@@ -1845,10 +1871,53 @@ class _LIBUNWIND_HIDDEN Registers_arm64 {
uint64_t getSP() const { return _registers.__sp; }
void setSP(uint64_t value) { _registers.__sp = value; }
- uint64_t getIP() const { return _registers.__pc; }
- void setIP(uint64_t value) { _registers.__pc = value; }
- uint64_t getFP() const { return _registers.__fp; }
- void setFP(uint64_t value) { _registers.__fp = value; }
+ uint64_t getIP() const {
+ uint64_t value = _registers.__pc;
+#if __has_feature(ptrauth_calls)
+ // Note the value of the PC was signed to its address in the register state
+ // but everyone else expects it to be sign by the SP, so convert on return.
+ value = (uint64_t)ptrauth_auth_and_resign(
+ (void *)_registers.__pc, ptrauth_key_return_address, &_registers.__pc,
+ ptrauth_key_return_address, getSP());
+#endif
+ return value;
+ }
+ void setIP(uint64_t value) {
+#if __has_feature(ptrauth_calls)
+ // Note the value which was set should have been signed with the SP.
+ // We then resign with the slot we are being stored in to so that both SP
+ // and LR can't be spoofed at the same time.
+ value = (uint64_t)ptrauth_auth_and_resign(
+ (void *)value, ptrauth_key_return_address, getSP(),
+ ptrauth_key_return_address, &_registers.__pc);
+#endif
+ _registers.__pc = value;
+ }
+ uint64_t getFP() const { return _registers.__fp; }
+ void setFP(uint64_t value) { _registers.__fp = value; }
+
+ typedef uint64_t reg_t;
+ typedef uint64_t
+ __LIBUNWIND_PTRAUTH_RI_PDC("Registers_arm64::link_reg_t") link_reg_t;
+ void
+ loadAndAuthenticateLinkRegister(reg_t inplaceAuthedLinkRegister,
+ link_reg_t *referenceAuthedLinkRegister) {
----------------
ojhunt wrote:
I vastly prefer using pointers for out parameters as it makes it much clearer at the call site that it's an out parameter.
Ideally we'd just return the pointer but the problem is we can't have ptrauth-qualified return values and as a result it's a foot gun for an oracle.
Alternatively I could create a struct wrapper to force the authentication, but the problem there is that I think the design would want to construct a dependent ptrauth qualifier and we don't yet support that.
Or I guess we could just make a
```cpp
template <class T> PointerAuthQualifierPointer = is_pointer<T> && (!ptrauth_available || ptrauth_schema_query_has_pointer_auth(T));
template < PointerAuthQualifierPointer T> struct PtrauthQualifiedPointer {
T thePointer;
...
}
```
To use for parameters and return values we consider important enough to require constant protection.
https://github.com/llvm/llvm-project/pull/143230
More information about the llvm-commits
mailing list