Merge changes I81408ef0,Id0eb8d06

* changes:
  Implement setjmp cookies on AArch64.
  Implement setjmp cookies on ARM.
diff --git a/libc/Android.mk b/libc/Android.mk
index a8c66fa..175fbb4 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -250,10 +250,11 @@
 # dereferences.
 libc_bionic_src_files += bionic/getauxval.cpp
 
-# These three require getauxval, which isn't available on older platforms.
+# These four require getauxval, which isn't available on older platforms.
 libc_bionic_src_files += bionic/getentropy_linux.c
 libc_bionic_src_files += bionic/sysconf.cpp
 libc_bionic_src_files += bionic/vdso.cpp
+libc_bionic_src_files += bionic/setjmp_cookie.cpp
 
 libc_cxa_src_files := \
     bionic/__cxa_guard.cpp \
@@ -347,7 +348,7 @@
     $(libc_upstream_openbsd_gdtoa_src_files) \
     upstream-openbsd/lib/libc/gdtoa/strtorQ.c \
 
-# These two depend on getentropy_linux.cpp, which isn't in libc_ndk.a.
+# These two depend on getentropy_linux.c, which isn't in libc_ndk.a.
 libc_upstream_openbsd_src_files := \
     upstream-openbsd/lib/libc/crypt/arc4random.c \
     upstream-openbsd/lib/libc/crypt/arc4random_uniform.c \
diff --git a/libc/arch-arm/bionic/setjmp.S b/libc/arch-arm/bionic/setjmp.S
index 8220c08..a119529 100644
--- a/libc/arch-arm/bionic/setjmp.S
+++ b/libc/arch-arm/bionic/setjmp.S
@@ -51,13 +51,13 @@
 // The internal structure of a jmp_buf is totally private.
 // Current layout (may change in the future):
 //
-// word   name         description
-// 0      magic        magic number
-// 1      sigmask      signal mask (not used with _setjmp / _longjmp)
-// 2      float_base   base of float registers (d8 to d15)
-// 18     float_state  floating-point status and control register
-// 19     core_base    base of core registers (r4 to r14)
-// 30     reserved     reserved entries (room to grow)
+// 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      float_base      base of float registers (d8 to d15)
+// 18     float_state     floating-point status and control register
+// 19     core_base       base of core registers (r4 to r14)
+// 30     reserved        reserved entries (room to grow)
 // 64
 //
 // NOTE: float_base must be at an even word index, since the
@@ -80,33 +80,79 @@
   b sigsetjmp
 END(_setjmp)
 
+#define MANGLE_REGISTERS 1
+.macro m_mangle_registers reg
+#if MANGLE_REGISTERS
+  eor r4, r4, \reg
+  eor r5, r5, \reg
+  eor r6, r6, \reg
+  eor r7, r7, \reg
+  eor r8, r8, \reg
+  eor r9, r9, \reg
+  eor r10, r10, \reg
+  eor r11, r11, \reg
+  eor r12, r12, \reg
+  eor r13, r13, \reg
+  eor r14, r14, \reg
+#endif
+.endm
+
+.macro m_unmangle_registers reg
+  m_mangle_registers \reg
+.endm
+
 // int sigsetjmp(sigjmp_buf env, int save_signal_mask);
 ENTRY(sigsetjmp)
-  // Record whether or not we're saving the signal mask.
+  stmfd sp!, {r0, lr}
+  .cfi_def_cfa_offset 8
+  .cfi_rel_offset r0, 0
+  .cfi_rel_offset lr, 4
+
+  mov r0, r1
+  bl __bionic_setjmp_cookie_get
+  mov r1, r0
+
+  ldmfd sp, {r0}
+
+  // Save the setjmp cookie for later.
+  bic r2, r1, #1
+  stmfd sp!, {r2}
+  .cfi_adjust_cfa_offset 4
+
+  // Record the setjmp cookie and whether or not we're saving the signal mask.
   str r1, [r0, #(_JB_SIGFLAG * 4)]
 
   // Do we need to save the signal mask?
-  teq r1, #0
+  tst r1, #1
   beq 1f
 
-  // Get current signal mask.
-  stmfd sp!, {r0, r14}
-  .cfi_def_cfa_offset 8
-  .cfi_rel_offset r0, 0
-  .cfi_rel_offset r14, 4
-  mov r0, #0
-  bl sigblock
-  mov r1, r0
-  ldmfd sp!, {r0, r14}
-  .cfi_def_cfa_offset 0
+  // Align the stack.
+  sub sp, #4
+  .cfi_adjust_cfa_offset 4
 
-  // Save the signal mask.
-  str r1, [r0, #(_JB_SIGMASK * 4)]
+  // Save the current signal mask.
+  add r2, r0, #(_JB_SIGMASK * 4)
+  mov r0, #2 // SIG_SETMASK
+  mov r1, #0
+  bl sigprocmask
+
+  // Unalign the stack.
+  add sp, #4
+  .cfi_adjust_cfa_offset -4
 
 1:
+  ldmfd sp!, {r2}
+  .cfi_adjust_cfa_offset -4
+  ldmfd sp!, {r0, lr}
+  .cfi_adjust_cfa_offset -8
+  .cfi_restore r0
+  .cfi_restore lr
+
   // Save core registers.
   add r1, r0, #(_JB_CORE_BASE * 4)
+  m_mangle_registers r2
   stmia r1, {r4-r14}
+  m_unmangle_registers r2
 
   // Save floating-point registers.
   add r1, r0, #(_JB_FLOAT_BASE * 4)
@@ -122,29 +168,30 @@
 
 // void siglongjmp(sigjmp_buf env, int value);
 ENTRY(siglongjmp)
-  // Do we need to restore the signal mask?
-  ldr r2, [r0, #(_JB_SIGFLAG * 4)]
-  teq r2, #0
-  beq 1f
-
-  // Restore the signal mask.
-  stmfd sp!, {r0, r1, r14}
+  stmfd sp!, {r0, r1, lr}
   .cfi_def_cfa_offset 12
   .cfi_rel_offset r0, 0
   .cfi_rel_offset r1, 4
-  .cfi_rel_offset r14, 8
-  sub sp, sp, #4 // Align the stack.
-  .cfi_adjust_cfa_offset 4
+  .cfi_rel_offset lr, 8
 
+  // Fetch the signal flag.
+  ldr r1, [r0, #(_JB_SIGFLAG * 4)]
+
+  // Do we need to restore the signal mask?
+  ands r1, r1, #1
+  beq 1f
+
+  // Restore the signal mask.
   ldr r0, [r0, #(_JB_SIGMASK * 4)]
   bl sigsetmask
 
-  add sp, sp, #4 // Unalign the stack.
-  .cfi_adjust_cfa_offset -4
-  ldmfd sp!, {r0, r1, r14}
-  .cfi_def_cfa_offset 0
-
 1:
+  ldmfd sp!, {r0, r1, lr}
+  .cfi_adjust_cfa_offset -12
+  .cfi_restore r0
+  .cfi_restore r1
+  .cfi_restore lr
+
   // Restore floating-point registers.
   add r2, r0, #(_JB_FLOAT_BASE * 4)
   vldmia r2, {d8-d15}
@@ -154,16 +201,24 @@
   fmxr fpscr, r2
 
   // Restore core registers.
+  ldr r3, [r0, #(_JB_SIGFLAG * 4)]
+  bic r3, r3, #1
   add r2, r0, #(_JB_CORE_BASE * 4)
   ldmia r2, {r4-r14}
+  m_unmangle_registers r3
 
-  // Validate sp and r14.
-  teq sp, #0
-  teqne r14, #0
-  bleq longjmperror
+  // Save the return value/address and check the setjmp cookie.
+  stmfd sp!, {r1, lr}
+  .cfi_adjust_cfa_offset 8
+  .cfi_rel_offset lr, 4
+  mov r0, r3
+  bl __bionic_setjmp_cookie_check
 
-  // Set return value.
-  mov r0, r1
+  // Restore return value/address.
+  ldmfd sp!, {r0, lr}
+  .cfi_adjust_cfa_offset -8
+  .cfi_restore lr
+
   teq r0, #0
   moveq r0, #1
   bx lr
diff --git a/libc/arch-arm64/bionic/setjmp.S b/libc/arch-arm64/bionic/setjmp.S
index ba0a226..c06a671 100644
--- a/libc/arch-arm64/bionic/setjmp.S
+++ b/libc/arch-arm64/bionic/setjmp.S
@@ -52,6 +52,29 @@
 #define _JB_D10_D11     (_JB_D12_D13 + 2)
 #define _JB_D8_D9       (_JB_D10_D11 + 2)
 
+#define MANGLE_REGISTERS 1
+.macro m_mangle_registers reg, sp_reg
+#if MANGLE_REGISTERS
+  eor x19, x19, \reg
+  eor x20, x20, \reg
+  eor x21, x21, \reg
+  eor x22, x22, \reg
+  eor x23, x23, \reg
+  eor x24, x24, \reg
+  eor x25, x25, \reg
+  eor x26, x26, \reg
+  eor x27, x27, \reg
+  eor x28, x28, \reg
+  eor x29, x29, \reg
+  eor x30, x30, \reg
+  eor \sp_reg, \sp_reg, \reg
+#endif
+.endm
+
+.macro m_unmangle_registers reg, sp_reg
+  m_mangle_registers \reg, sp_reg=\sp_reg
+.endm
+
 ENTRY(setjmp)
   mov w1, #1
   b sigsetjmp
@@ -64,23 +87,47 @@
 
 // int sigsetjmp(sigjmp_buf env, int save_signal_mask);
 ENTRY(sigsetjmp)
-  // Record whether or not we're saving the signal mask.
-  str w1, [x0, #(_JB_SIGFLAG * 8)]
+  stp x0, x30, [sp, #-16]!
+  .cfi_def_cfa_offset 16
+  .cfi_rel_offset x0, 0
+  .cfi_rel_offset x30, 8
+
+  // Get the cookie and store it along with the signal flag.
+  mov x0, x1
+  bl __bionic_setjmp_cookie_get
+  mov x1, x0
+  ldr x0, [sp, #0]
+  str x1, [x0, #(_JB_SIGFLAG * 8)]
 
   // Do we need to save the signal mask?
-  cbz w1, 1f
+  tbz w1, #0, 1f
+
+  // Save the cookie for later.
+  stp x1, xzr, [sp, #-16]!
+  .cfi_adjust_cfa_offset 16
 
   // Save current signal mask.
-  stp x0, x30, [sp, #-16]!
   // The 'how' argument is ignored if new_mask is NULL.
   mov x1, #0 // NULL.
   add x2, x0, #(_JB_SIGMASK * 8) // old_mask.
   bl sigprocmask
-  ldp x0, x30, [sp], #16
+
+  ldp x1, xzr, [sp], #16
+  .cfi_adjust_cfa_offset -16
 
 1:
+  // Restore original x0 and lr.
+  ldp x0, x30, [sp], #16
+  .cfi_adjust_cfa_offset -16
+  .cfi_restore x0
+  .cfi_restore x30
+
+  // Mask off the signal flag bit.
+  bic x1, x1, #1
+
   // Save core registers.
   mov x10, sp
+  m_mangle_registers x1, sp_reg=x10
   stp x30, x10, [x0, #(_JB_X30_SP  * 8)]
   stp x28, x29, [x0, #(_JB_X28_X29 * 8)]
   stp x26, x27, [x0, #(_JB_X26_X27 * 8)]
@@ -88,6 +135,7 @@
   stp x22, x23, [x0, #(_JB_X22_X23 * 8)]
   stp x20, x21, [x0, #(_JB_X20_X21 * 8)]
   str x19,      [x0, #(_JB_X19     * 8)]
+  m_unmangle_registers x1, sp_reg=x10
 
   // Save floating point registers.
   stp d14, d15, [x0, #(_JB_D14_D15 * 8)]
@@ -102,30 +150,60 @@
 // void siglongjmp(sigjmp_buf env, int value);
 ENTRY(siglongjmp)
   // Do we need to restore the signal mask?
-  ldr w9, [x0, #(_JB_SIGFLAG * 8)]
-  cbz w9, 1f
+  ldr x2, [x0, #(_JB_SIGFLAG * 8)]
+  tbz w2, #0, 1f
+
+  stp x0, x30, [sp, #-16]!
+  .cfi_adjust_cfa_offset 16
+  .cfi_rel_offset x0, 0
+  .cfi_rel_offset x30, 8
 
   // Restore signal mask.
-  stp x0, x30, [sp, #-16]!
   mov x19, x1 // Save 'value'.
+
   mov x2, x0
   mov x0, #2 // SIG_SETMASK
   add x1, x2, #(_JB_SIGMASK * 8) // new_mask.
   mov x2, #0 // NULL.
   bl sigprocmask
   mov x1, x19 // Restore 'value'.
-  ldp x0, x30, [sp], #16
 
+  // Restore original x0 and lr.
+  ldp x0, x30, [sp], #16
+  .cfi_adjust_cfa_offset -16
+  .cfi_restore x0
+  .cfi_restore x30
+
+  ldr x2, [x0, #(_JB_SIGFLAG * 8)]
 1:
   // Restore core registers.
+  bic x2, x2, #1
   ldp x30, x10, [x0, #(_JB_X30_SP  * 8)]
-  mov sp, x10
   ldp x28, x29, [x0, #(_JB_X28_X29 * 8)]
   ldp x26, x27, [x0, #(_JB_X26_X27 * 8)]
   ldp x24, x25, [x0, #(_JB_X24_X25 * 8)]
   ldp x22, x23, [x0, #(_JB_X22_X23 * 8)]
   ldp x20, x21, [x0, #(_JB_X20_X21 * 8)]
   ldr x19,      [x0, #(_JB_X19     * 8)]
+  m_unmangle_registers x2, sp_reg=x10
+  mov sp, x10
+
+  stp x0, x1, [sp, #-16]!
+  .cfi_adjust_cfa_offset 16
+  .cfi_rel_offset x0, 0
+  .cfi_rel_offset x1, 8
+  stp x30, xzr, [sp, #-16]!
+  .cfi_adjust_cfa_offset 16
+  .cfi_rel_offset x30, 0
+  ldr x0, [x0, #(_JB_SIGFLAG * 8)]
+  bl __bionic_setjmp_cookie_check
+  ldp x30, xzr, [sp], #16
+  .cfi_adjust_cfa_offset -16
+  .cfi_restore x30
+  ldp x0, x1, [sp], #16
+  .cfi_adjust_cfa_offset -16
+  .cfi_restore x0
+  .cfi_restore x1
 
   // Restore floating point registers.
   ldp d14, d15, [x0, #(_JB_D14_D15 * 8)]
@@ -133,13 +211,6 @@
   ldp d10, d11, [x0, #(_JB_D10_D11 * 8)]
   ldp d8,  d9,  [x0, #(_JB_D8_D9   * 8)]
 
-  // Validate sp (sp mod 16 = 0) and lr (lr mod 4 = 0).
-  tst x30, #3
-  b.ne longjmperror
-  mov x10, sp
-  tst x10, #15
-  b.ne longjmperror
-
   // Set return value.
   cmp w1, wzr
   csinc w0, w1, wzr, ne
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index 3ca6c0d..f59fa67 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -49,6 +49,7 @@
 #include "pthread_internal.h"
 
 extern "C" abort_msg_t** __abort_message_ptr;
+extern "C" void __bionic_setjmp_cookie_init(void);
 extern "C" int __system_properties_init(void);
 extern "C" int __set_tls(void* ptr);
 extern "C" int __set_tid_address(int* tid_address);
@@ -121,6 +122,7 @@
 
   __system_properties_init(); // Requires 'environ'.
 
+  __bionic_setjmp_cookie_init();
   __libc_init_vdso();
 }
 
diff --git a/libc/bionic/setjmp_cookie.cpp b/libc/bionic/setjmp_cookie.cpp
new file mode 100644
index 0000000..cf79e83
--- /dev/null
+++ b/libc/bionic/setjmp_cookie.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/auxv.h>
+#include <sys/cdefs.h>
+
+#include "private/libc_logging.h"
+
+extern "C" __LIBC_HIDDEN__ int getentropy(void*, size_t);
+static long __bionic_setjmp_cookie;
+
+extern "C" void __bionic_setjmp_cookie_init() {
+  char* random_data = reinterpret_cast<char*>(getauxval(AT_RANDOM));
+  long value = *reinterpret_cast<long*>(random_data + 8);
+
+  // Mask off the last bit to store the signal flag.
+  __bionic_setjmp_cookie = value & ~1;
+}
+
+extern "C" long __bionic_setjmp_cookie_get(long sigflag) {
+  if (sigflag & ~1) {
+    __libc_fatal("unexpected sigflag value: %ld", sigflag);
+  }
+
+  return __bionic_setjmp_cookie | sigflag;
+}
+
+// Aborts if cookie doesn't match, returns the signal flag otherwise.
+extern "C" long __bionic_setjmp_cookie_check(long cookie) {
+  if (__bionic_setjmp_cookie != (cookie & ~1)) {
+    __libc_fatal("setjmp cookie mismatch");
+  }
+
+  return cookie & 1;
+}
diff --git a/tests/setjmp_test.cpp b/tests/setjmp_test.cpp
index a3b5885..944dac8 100644
--- a/tests/setjmp_test.cpp
+++ b/tests/setjmp_test.cpp
@@ -212,3 +212,30 @@
     CHECK_FREGS;
   }
 }
+
+#if defined(__arm__)
+#define __JB_SIGFLAG 0
+#elif defined(__aarch64__)
+#define __JB_SIGFLAG 0
+#elif defined(__i386__)
+#define __JB_SIGFLAG 7
+#elif defined(__x86_64)
+#define __JB_SIGFLAG 8
+#endif
+
+TEST(setjmp, setjmp_cookie) {
+#if !defined(__mips__)
+  jmp_buf jb;
+  int value = setjmp(jb);
+  ASSERT_EQ(0, value);
+
+  long* sigflag = reinterpret_cast<long*>(jb) + __JB_SIGFLAG;
+
+  // Make sure there's actually a cookie.
+  EXPECT_NE(0, *sigflag & ~1);
+
+  // Wipe it out
+  *sigflag &= 1;
+  EXPECT_DEATH(longjmp(jb, 0), "");
+#endif
+}