OSDN Git Service

Add a checksum to jmp_buf on AArch64.
authorJosh Gao <jmgao@google.com>
Thu, 3 Mar 2016 03:45:29 +0000 (19:45 -0800)
committerJosh Gao <jmgao@google.com>
Thu, 3 Mar 2016 23:05:38 +0000 (15:05 -0800)
Bug: http://b/27417786
Change-Id: I17c22dc28a46dd6b678b449b506b0da978f3793e
(cherry picked from commit 0c3655a864f33080ebbec1248c27a7ead87d6a28)

libc/arch-arm64/bionic/setjmp.S

index c06a671..2550134 100644 (file)
 // NOTE: All the registers saved here will have 64 bit vales.
 //       AAPCS mandates that the higher part of q registers do not need to
 //       be saved by the callee.
+//
+// The internal structure of a jmp_buf is totally private.
+// Current layout (changes from release to release):
+//
+// word   name            description
+// 0      sigflag/cookie  setjmp cookie in top 31 bits, signal mask flag in low bit
+// 1      sigmask         signal mask (not used with _setjmp / _longjmp)
+// 2      core_base       base of core registers (x19-x30, sp)
+// 15     float_base      base of float registers (d8-d15)
+// 23     checksum        checksum of core registers
+// 24     reserved        reserved entries (room to grow)
+// 32
 
 #define _JB_SIGFLAG     0
 #define _JB_SIGMASK     (_JB_SIGFLAG + 1)
 #define _JB_D12_D13     (_JB_D14_D15 + 2)
 #define _JB_D10_D11     (_JB_D12_D13 + 2)
 #define _JB_D8_D9       (_JB_D10_D11 + 2)
+#define _JB_CHECKSUM    (_JB_D8_D9 + 2)
 
 #define MANGLE_REGISTERS 1
+#define USE_CHECKSUM 1
+
 .macro m_mangle_registers reg, sp_reg
 #if MANGLE_REGISTERS
   eor x19, x19, \reg
 #endif
 .endm
 
+.macro m_calculate_checksum dst, src, scratch
+  mov \dst, #0
+  .irp i,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22
+    ldr \scratch, [\src, #(\i * 8)]
+    eor \dst, \dst, \scratch
+  .endr
+.endm
+
 .macro m_unmangle_registers reg, sp_reg
   m_mangle_registers \reg, sp_reg=\sp_reg
 .endm
@@ -143,12 +166,27 @@ ENTRY(sigsetjmp)
   stp d10, d11, [x0, #(_JB_D10_D11 * 8)]
   stp d8,  d9,  [x0, #(_JB_D8_D9   * 8)]
 
+#if USE_CHECKSUM
+  // Calculate the checksum.
+  m_calculate_checksum x12, x0, x2
+  str x12, [x0, #(_JB_CHECKSUM * 8)]
+#endif
+
   mov w0, #0
   ret
 END(sigsetjmp)
 
 // void siglongjmp(sigjmp_buf env, int value);
 ENTRY(siglongjmp)
+#if USE_CHECKSUM
+  // Check the checksum before doing anything.
+  m_calculate_checksum x12, x0, x2
+  ldr x2, [x0, #(_JB_CHECKSUM * 8)]
+
+  cmp x2, x12
+  bne __bionic_setjmp_checksum_mismatch
+#endif
+
   // Do we need to restore the signal mask?
   ldr x2, [x0, #(_JB_SIGFLAG * 8)]
   tbz w2, #0, 1f