Merge changes I81408ef0,Id0eb8d06
* changes: Implement setjmp cookies on AArch64. Implement setjmp cookies on ARM.
This commit is contained in:
commit
823cff847b
@ -250,10 +250,11 @@ libc_bionic_src_files += bionic/fork.cpp
|
||||
# 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_64 := \
|
||||
$(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 \
|
||||
|
@ -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 @@ ENTRY(_setjmp)
|
||||
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 @@ END(sigsetjmp)
|
||||
|
||||
// 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 @@ ENTRY(siglongjmp)
|
||||
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
|
||||
|
||||
// Restore return value/address.
|
||||
ldmfd sp!, {r0, lr}
|
||||
.cfi_adjust_cfa_offset -8
|
||||
.cfi_restore lr
|
||||
|
||||
// Set return value.
|
||||
mov r0, r1
|
||||
teq r0, #0
|
||||
moveq r0, #1
|
||||
bx lr
|
||||
|
@ -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 @@ END(_setjmp)
|
||||
|
||||
// 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 @@ ENTRY(sigsetjmp)
|
||||
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 @@ END(sigsetjmp)
|
||||
// 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 @@ ENTRY(siglongjmp)
|
||||
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
|
||||
|
@ -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 @@ void __libc_init_common(KernelArgumentBlock& args) {
|
||||
|
||||
__system_properties_init(); // Requires 'environ'.
|
||||
|
||||
__bionic_setjmp_cookie_init();
|
||||
__libc_init_vdso();
|
||||
}
|
||||
|
||||
|
65
libc/bionic/setjmp_cookie.cpp
Normal file
65
libc/bionic/setjmp_cookie.cpp
Normal file
@ -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;
|
||||
}
|
@ -212,3 +212,30 @@ TEST(setjmp, setjmp_fp_registers) {
|
||||
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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user