================
@@ -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
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to