setjmp/longjmp: avoid invalid values in the stack pointer.
arm64 was already being careful, but x86/x86-64 and 32-bit ARM could be
caught by a signal in a state where the stack pointer was mangled.
For 32-bit ARM I've taken care with the link register too, to avoid
potential issues with unwinding.
Bug: http://b/152210274
Test: treehugger
Change-Id: I1ce285b017a633c732dbe04743368f4cae27af85
diff --git a/libc/arch-x86_64/bionic/setjmp.S b/libc/arch-x86_64/bionic/setjmp.S
index 1d34561..ba3f05f 100644
--- a/libc/arch-x86_64/bionic/setjmp.S
+++ b/libc/arch-x86_64/bionic/setjmp.S
@@ -64,25 +64,6 @@
#define _JB_SIGMASK 9
#define _JB_CHECKSUM 10
-#define MANGLE_REGISTERS 1
-
-.macro m_mangle_registers reg
-#if MANGLE_REGISTERS
- xorq \reg,%rbx
- xorq \reg,%rbp
- xorq \reg,%r12
- xorq \reg,%r13
- xorq \reg,%r14
- xorq \reg,%r15
- xorq \reg,%rsp
- xorq \reg,%r11
-#endif
-.endm
-
-.macro m_unmangle_registers reg
- m_mangle_registers \reg
-.endm
-
.macro m_calculate_checksum dst, src
movq $0, \dst
.irp i,0,1,2,3,4,5,6,7
@@ -127,20 +108,26 @@
popq %rdi // Pop 'env'.
2:
- // Save the callee-save registers.
+ // Fetch the setjmp cookie and clear the signal flag bit.
popq %rax
andq $-2,%rax
movq (%rsp),%r11
- m_mangle_registers %rax
- movq %rbx,(_JB_RBX * 8)(%rdi)
- movq %rbp,(_JB_RBP * 8)(%rdi)
- movq %r12,(_JB_R12 * 8)(%rdi)
- movq %r13,(_JB_R13 * 8)(%rdi)
- movq %r14,(_JB_R14 * 8)(%rdi)
- movq %r15,(_JB_R15 * 8)(%rdi)
- movq %rsp,(_JB_RSP * 8)(%rdi)
- movq %r11,(_JB_PC * 8)(%rdi)
- m_unmangle_registers %rax
+
+ // Save the callee-save registers.
+
+.macro m_mangle_register reg, offset
+ movq \reg, (\offset * 8)(%rdi)
+ xorq %rax, (\offset * 8)(%rdi) // %rax contains the cookie.
+.endm
+
+ m_mangle_register %rbx, _JB_RBX
+ m_mangle_register %rbp, _JB_RBP
+ m_mangle_register %r12, _JB_R12
+ m_mangle_register %r13, _JB_R13
+ m_mangle_register %r14, _JB_R14
+ m_mangle_register %r15, _JB_R15
+ m_mangle_register %rsp, _JB_RSP
+ m_mangle_register %r11, _JB_PC
m_calculate_checksum %rax, %rdi
movq %rax, (_JB_CHECKSUM * 8)(%rdi)
@@ -179,15 +166,22 @@
popq %rax // Pop 'value'.
// Restore the callee-save registers.
- movq (_JB_RBX * 8)(%r12),%rbx
- movq (_JB_RBP * 8)(%r12),%rbp
- movq (_JB_R13 * 8)(%r12),%r13
- movq (_JB_R14 * 8)(%r12),%r14
- movq (_JB_R15 * 8)(%r12),%r15
- movq (_JB_RSP * 8)(%r12),%rsp
- movq (_JB_PC * 8)(%r12),%r11
- movq (_JB_R12 * 8)(%r12),%r12
- m_unmangle_registers %rcx
+
+.macro m_unmangle_register reg, offset
+ movq (\offset * 8)(%r12), %rdx // Clobbers rdx.
+ xorq %rcx, %rdx // %rcx contains the cookie.
+ // Now it's safe to overwrite the register (http://b/152210274).
+ movq %rdx, \reg
+.endm
+
+ m_unmangle_register %rbx, _JB_RBX
+ m_unmangle_register %rbp, _JB_RBP
+ m_unmangle_register %r13, _JB_R13
+ m_unmangle_register %r14, _JB_R14
+ m_unmangle_register %r15, _JB_R15
+ m_unmangle_register %rsp, _JB_RSP
+ m_unmangle_register %r11, _JB_PC
+ m_unmangle_register %r12, _JB_R12
// Check the cookie.
pushq %rax