================
@@ -1877,49 +1877,179 @@ class _LIBUNWIND_HIDDEN Registers_arm64 {
 
   uint64_t  getSP() const         { return _registers.__sp; }
   void      setSP(uint64_t value) { _registers.__sp = value; }
+
   uint64_t  getIP() const {
     uint64_t value = _registers.__pc;
-#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
+
+    if (!isReturnAddressSigned())
+      return value;
+
+#if !defined(_LIBUNWIND_IS_NATIVE_ONLY)
+    abortCrossRASigning();
+#else
     // 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());
+    register uint64_t x17 __asm("x17") = value;
+    register uint64_t x16 __asm("x16") =
+        reinterpret_cast<uint64_t>(&_registers.__pc);
+    register uint64_t x14 __asm("x14") = getSP();
+    if (isReturnAddressSignedWithPC()) {
+      register uint64_t x15 __asm("x15") =
+          _registers.__ra_sign.__second_modifier;
+      if (isReturnAddressSignedWithBKey()) {
+        asm("hint 0xe    \n\t" // autib1716
+            "mov x16, x14\n\t"
+            "hint 0x27   \n\t" // pacm
+            "hint 0xa        " // pacib1716
+            : "+r"(x17)
+            : "r"(x16), "r"(x15), "r"(x14));
+      } else {
+        asm("hint 0xc    \n\t" // autia1716
+            "mov x16, x14\n\t"
+            "hint 0x27   \n\t" // pacm
+            "hint 0x8        " // pacia1716
+            : "+r"(x17)
+            : "r"(x16), "r"(x15), "r"(x14));
+      }
+    } else {
+      if (isReturnAddressSignedWithBKey()) {
+        asm("hint 0xe    \n\t" // autib1716
+            "mov x16, x14\n\t"
+            "hint 0xa        " // pacib1716
+            : "+r"(x17)
+            : "r"(x16), "r"(x14));
+      } else {
+        asm("hint 0xc    \n\t" // autia1716
+            "mov x16, x14\n\t"
+            "hint 0x8        " // pacia1716
+            : "+r"(x17)
+            : "r"(x16), "r"(x14));
+      }
+    }
+    return x17;
 #endif
-    return value;
   }
+
   void      setIP(uint64_t value) {
-#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
+    if (!isReturnAddressSigned()) {
+      _registers.__pc = value;
+      return;
+    }
+
+#if !defined(_LIBUNWIND_IS_NATIVE_ONLY)
+    abortCrossRASigning();
+#else
     // 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);
+    register uint64_t x17 __asm("x17") = value;
+    register uint64_t x16 __asm("x16") = getSP();
+    register uint64_t x14 __asm("x14") =
+        reinterpret_cast<uint64_t>(&_registers.__pc);
+    if (isReturnAddressSignedWithPC()) {
+      register uint64_t x15 __asm("x15") =
+          _registers.__ra_sign.__second_modifier;
+      if (isReturnAddressSignedWithBKey()) {
+        asm("hint 0x27   \n\t" // pacm
+            "hint 0xe    \n\t" // autib1716
+            "mov x16, x14\n\t"
+            "hint 0xa        " // pacib1716
+            : "+r"(x17)
+            : "r"(x16), "r"(x15), "r"(x14));
+      } else {
+        asm("hint 0x27   \n\t" // pacm
+            "hint 0xc    \n\t" // autia1716
+            "mov x16, x14\n\t"
+            "hint 0x8        " // pacia1716
+            : "+r"(x17)
+            : "r"(x16), "r"(x15), "r"(x14));
+      }
+    } else {
+      if (isReturnAddressSignedWithBKey()) {
+        asm("hint 0xe    \n\t" // autib1716
+            "mov x16, x14\n\t"
+            "hint 0xa        " // pacib1716
+            : "+r"(x17)
+            : "r"(x16), "r"(x14));
+      } else {
+        asm("hint 0xc    \n\t" // autia1716
+            "mov x16, x14\n\t"
+            "hint 0x8        " // pacia1716
+            : "+r"(x17)
+            : "r"(x16), "r"(x14));
+      }
+    }
+    _registers.__pc = x17;
 #endif
-    _registers.__pc = value;
   }
+
   uint64_t getFP() const { return _registers.__fp; }
   void setFP(uint64_t value) { _registers.__fp = value; }
 
-#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
+  // NOTE: For full-fledged PAuth ABIs like Apple's arm64e and Linux's
+  // pauthtest link_reg_t is __ptrauth-qualified. So, LR is re-signed with
+  // link_reg_t signing scheme after it is authenticated with this function.
+  // When just pac-ret is used, link_reg_t is not __ptrauth-qualified and LR
+  // remains unsigned after authentication.
+  // TODO: avoid exposing unsigned LR in absence of full-fledged PAuth ABI.
   void
   loadAndAuthenticateLinkRegister(reg_t inplaceAuthedLinkRegister,
                                   link_reg_t *referenceAuthedLinkRegister) {
-    // If we are in an arm64/arm64e frame, then the PC should have been signed
-    // with the SP
-    *referenceAuthedLinkRegister =
-      (uint64_t)ptrauth_auth_data((void *)inplaceAuthedLinkRegister,
-                                  ptrauth_key_return_address,
-                                  _registers.__sp);
-  }
+    if (!isReturnAddressSigned()) {
+      *referenceAuthedLinkRegister = inplaceAuthedLinkRegister;
+      return;
+    }
+
+#if !defined(_LIBUNWIND_IS_NATIVE_ONLY)
+    abortCrossRASigning();
+#else
+    register reg_t x17 __asm("x17") = inplaceAuthedLinkRegister;
+    register reg_t x16 __asm("x16") = getSP();
+    if (isReturnAddressSignedWithPC()) {
+      register reg_t x15 __asm("x15") = _registers.__ra_sign.__second_modifier;
+      if (isReturnAddressSignedWithBKey()) {
+        asm("hint 0x27\n\t" // pacm
+            "hint 0xe     " // autib1716
+            : "+r"(x17)
+            : "r"(x16), "r"(x15));
+      } else {
+        asm("hint 0x27\n\t" // pacm
+            "hint 0xc     " // autia1716
+            : "+r"(x17)
+            : "r"(x16), "r"(x15));
+      }
+    } else {
+      if (isReturnAddressSignedWithBKey()) {
+        asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716
+      } else {
+        asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716
+      }
+    }
+    *referenceAuthedLinkRegister = x17;
 #endif
+  }
+
+  bool isReturnAddressSigned() const {
+    return _registers.__ra_sign.__state & 1;
+  }
+  bool isReturnAddressSignedWithPC() const {
+    return _registers.__ra_sign.__state & 2;
+  }
+  bool isReturnAddressSignedWithBKey() const {
+    return _registers.__ra_sign.__use_b_key;
+  }
----------------
kovdan01 wrote:

Yeah, I'm currently working on verifying the integrity of these values by 
computing and comparing an authentication code with `pacga` instruction. I 
believe this should address your concern

https://github.com/llvm/llvm-project/pull/171717
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to