================
@@ -683,42 +684,143 @@ 
DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)
   ldp    x28,x29, [x0, #0x0E0]
 
 #if defined(__ARM_FP) && __ARM_FP != 0
-  ldp    d0, d1,  [x0, #0x110]
-  ldp    d2, d3,  [x0, #0x120]
-  ldp    d4, d5,  [x0, #0x130]
-  ldp    d6, d7,  [x0, #0x140]
-  ldp    d8, d9,  [x0, #0x150]
-  ldp    d10,d11, [x0, #0x160]
-  ldp    d12,d13, [x0, #0x170]
-  ldp    d14,d15, [x0, #0x180]
-  ldp    d16,d17, [x0, #0x190]
-  ldp    d18,d19, [x0, #0x1A0]
-  ldp    d20,d21, [x0, #0x1B0]
-  ldp    d22,d23, [x0, #0x1C0]
-  ldp    d24,d25, [x0, #0x1D0]
-  ldp    d26,d27, [x0, #0x1E0]
-  ldp    d28,d29, [x0, #0x1F0]
-  ldr    d30,     [x0, #0x200]
-  ldr    d31,     [x0, #0x208]
+  ldp    d0, d1,  [x0, #0x120]
+  ldp    d2, d3,  [x0, #0x130]
+  ldp    d4, d5,  [x0, #0x140]
+  ldp    d6, d7,  [x0, #0x150]
+  ldp    d8, d9,  [x0, #0x160]
+  ldp    d10,d11, [x0, #0x170]
+  ldp    d12,d13, [x0, #0x180]
+  ldp    d14,d15, [x0, #0x190]
+  ldp    d16,d17, [x0, #0x1A0]
+  ldp    d18,d19, [x0, #0x1B0]
+  ldp    d20,d21, [x0, #0x1C0]
+  ldp    d22,d23, [x0, #0x1D0]
+  ldp    d24,d25, [x0, #0x1E0]
+  ldp    d26,d27, [x0, #0x1F0]
+  ldr    d28,     [x0, #0x200]
+  ldr    d29,     [x0, #0x208]
+  ldr    d30,     [x0, #0x210]
+  ldr    d31,     [x0, #0x218]
 #endif
+
+  // The lr value stored in __pc might be signed with IA/IB key (as described
+  // by __ra_sign.__use_b_key field) and &__pc address as a modifier.
+  // If the lr value is signed, re-sign that with the corresponding key
+  // and initial signing scheme using __sp as a modifier and potentially
+  // involving a second modifier (as described by (__ra_sign.__state & 2)).
+
+  ldr    x14,     [x0, #0x0F8]  // x14 = __sp
+  ldr    x15,     [x0, #0x110]  // x15 = __ra_sign.__second_modifier
+  add    x16, x0, #0x100        // x16 = &__pc
+  ldr    x17,     [x0, #0x100]  // x17 = __pc
+
+  ldr    x1,      [x0, #0x108]  // x1 = __ra_sign.__state
+  and    x1, x1, #1
+  cbz    x1, .Lresign_end
+
+  // lr needs resign
+  ldr    x1,      [x0, #0x108]  // x1 = __ra_sign.__state
+  and    x1, x1, #2
+  cbnz   x1, .Lresign_with_pc
+
+  // lr needs resign without pc as a second modifier
+  ldr    x1,      [x0, #0x118]  // x1 = __ra_sign.__use_b_key
+  cbnz   x1, .Lresign_with_b_key
+
+  // lr needs resign with A key and without pc as a second modifier
+  hint   0xc                    // autia1716
+  mov    x16, x14               // x16 = __sp
+  hint   0x8                    // pacia1716
+  b .Lresign_end
+
+.Lresign_with_b_key:
+  // lr needs resign with B key and without pc as a second modifier
+  hint   0xe                    // autib1716
+  mov    x16, x14               // x16 = __sp
+  hint   0xa                    // pacib1716
+  b .Lresign_end
+
+.Lresign_with_pc:
+  // lr needs resign with pc as a second modifier
+  ldr    x1,      [x0, #0x118]  // x1 = __ra_sign.__use_b_key
+  cbnz   x1, .Lresign_with_pc_b_key
+
+  // lr needs resign with A key and pc as a second modifier
+  hint   0xc                    // autia1716
+  mov    x16, x14               // x16 = __sp
+  hint   0x27                   // pacm
+  hint   0x8                    // pacia1716
+  b .Lresign_end
+
+.Lresign_with_pc_b_key:
+  // lr needs resign with B key and pc as a second modifier
+  hint   0xe                    // autib1716
+  mov    x16, x14               // x16 = __sp
+  hint   0x27                   // pacm
+  hint   0xa                    // pacib1716
+  b .Lresign_end
+
+.Lresign_end:
+  mov    lr, x17                // assign final lr value
+  ldp    x14,x15, [x0, #0x070]  // restore x14,x15
+  ldr    x16,     [x0, #0x110]  // second modifier for auti{a|b}sp with PACM
+
   // Finally, restore sp. This must be done after the last read from the
   // context struct, because it is allocated on the stack, and an exception
   // could clobber the de-allocated portion of the stack after sp has been
   // restored.
+  ldr    x17,     [x0, #0x0F8]  // load sp into scratch
 
-  ldr    x16,     [x0, #0x0F8]  // load sp into scratch
-  ldr    lr,      [x0, #0x100]  // restore pc into lr
+  ldr    x1,      [x0, #0x108]  // x1 = __ra_sign.__state
+  and    x1, x1, #1
+  cbz    x1, .Lauth_end
 
-#if __has_feature(ptrauth_calls)
-  // The LR is signed with its address inside the register state.  Time
-  // to resign to be a regular ROP protected signed pointer
-  add    x1, x0, #0x100
-  autib  lr, x1
-  pacib  lr, x16  // signed the scratch register for sp
-#endif
+  // lr is signed
+  ldr    x1,      [x0, #0x108]  // x1 = __ra_sign.__state
+  and    x1, x1, #2
+  cbnz   x1, .Lauth_with_pc
+
+  // lr is signed without pc as a second modifier
+  ldr    x1,      [x0, #0x118]  // x1 = __ra_sign.__use_b_key
+  cbnz   x1, .Lauth_with_b_key
----------------
kovdan01 wrote:

> between two different signing schemes

Between 4 signing schemes actually :)

> nonetheless you should really make the schema flag be authenticated as well

Hmm, this makes sense, but it should probably be more complex than 
authenticating just these flags stored in the context structure. We obtain 
these values from parsing Dwarf expressions, so if we want the flags to be 
signed, they need to be also signed in Dwarf-related structures as well. And I 
suppose that it would be not trivial.

Do you see any harm from security perspective (compared to current state of 
things) if we keep the schema flags unsigned? From my point of view, even 
though the schema flags are now unsigned, things become strictly more secure 
for pac-ret and remain unchanged for arm64e. Or am I missing smth?

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