================
@@ -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