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