From d5323f6a707e376aab20ebe7864a78fc38fcedaa Mon Sep 17 00:00:00 2001 From: Mikhail Maltsev Date: Mon, 17 Jun 2019 11:00:21 +0000 Subject: [PATCH] [libunwind][AArch64] Fix libunwind::Registers_arm64::jumpto Summary: The AArch64 version of the libunwind function which restores the CPU state and resumes execution is not interrupt-safe. It restores the target value of SP before loading the floating-point registers from the context struct, but that struct is allocated on the stack which is being deallocated. This means that if an interrupt occurs during this function, and uses a lot of stack space, it could overwrite the values about to be loaded into the floating-point registers. This patch fixes the issue. Patch by Oliver Stannard. Reviewers: phosek, chill Reviewed By: chill Subscribers: chill, javed.absar, kristof.beyls, christof, LukeCheeseman, pbarrio, olista01, libcxx-commits Tags: #libc Differential Revision: https://reviews.llvm.org/D63006 llvm-svn: 363545 --- libunwind/src/UnwindRegistersRestore.S | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libunwind/src/UnwindRegistersRestore.S b/libunwind/src/UnwindRegistersRestore.S index 01113565e8e003..8122bf3e1b2ea5 100644 --- a/libunwind/src/UnwindRegistersRestore.S +++ b/libunwind/src/UnwindRegistersRestore.S @@ -575,7 +575,8 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv) ldp x10,x11, [x0, #0x050] ldp x12,x13, [x0, #0x060] ldp x14,x15, [x0, #0x070] - ldp x16,x17, [x0, #0x080] + // x16 and x17 were clobbered by the call into the unwinder, so no point in + // restoring them. ldp x18,x19, [x0, #0x090] ldp x20,x21, [x0, #0x0A0] ldp x22,x23, [x0, #0x0B0] @@ -583,8 +584,6 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv) ldp x26,x27, [x0, #0x0D0] ldp x28,x29, [x0, #0x0E0] ldr x30, [x0, #0x100] // restore pc into lr - ldr x1, [x0, #0x0F8] - mov sp,x1 // restore sp ldp d0, d1, [x0, #0x110] ldp d2, d3, [x0, #0x120] @@ -604,7 +603,13 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv) ldr d30, [x0, #0x200] ldr d31, [x0, #0x208] + // Finally, restore sp. This must be done after the 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 x16, [x0, #0x0F8] ldp x0, x1, [x0, #0x000] // restore x0,x1 + mov sp,x16 // restore sp ret x30 // jump to pc #elif defined(__arm__) && !defined(__APPLE__)