diff options
author | Will Newton <will.newton@linaro.org> | 2013-12-10 16:26:38 +0000 |
---|---|---|
committer | Will Newton <will.newton@linaro.org> | 2014-01-14 14:02:34 +0000 |
commit | 2f10c4d6901e7a4c4ad294cc5bb8ece6547f4f62 (patch) | |
tree | 9694325d2c26b777f46a0e6b68eedc818b731896 | |
parent | 497b1e69f9ad6d11341735d81b7c9181d168df90 (diff) | |
download | glibc-2f10c4d6901e7a4c4ad294cc5bb8ece6547f4f62.tar.gz glibc-2f10c4d6901e7a4c4ad294cc5bb8ece6547f4f62.tar.xz glibc-2f10c4d6901e7a4c4ad294cc5bb8ece6547f4f62.zip |
ARM: Don't apply pointer encryption to the frame pointer
The frame pointer register is rarely used for that purpose on ARM and applications that look at the contents of the jmp_buf may be relying on reading an unencrypted value. For example, Ruby uses the contents of jmp_buf to find the root set for garbage collection so relies on this pointer value being unencrypted. Without this patch the Ruby testsuite fails with a segmentation fault. ports/ChangeLog.arm: 2013-01-14 Will Newton <will.newton@linaro.org> * sysdeps/arm/__longjmp.S: Don't apply pointer encryption to fp register. * sysdeps/arm/setjmp.S: Likewise. * sysdeps/arm/include/bits/setjmp.h (JMP_BUF_REGLIST): Add fp to register list, remove a4. * sysdeps/unix/sysv/linux/arm/sysdep.h (PTR_MANGLE_LOAD): New macro.
-rw-r--r-- | ports/ChangeLog.arm | 10 | ||||
-rw-r--r-- | ports/sysdeps/arm/__longjmp.S | 4 | ||||
-rw-r--r-- | ports/sysdeps/arm/include/bits/setjmp.h | 5 | ||||
-rw-r--r-- | ports/sysdeps/arm/setjmp.S | 4 | ||||
-rw-r--r-- | ports/sysdeps/unix/sysv/linux/arm/sysdep.h | 8 |
5 files changed, 20 insertions, 11 deletions
diff --git a/ports/ChangeLog.arm b/ports/ChangeLog.arm index 353c3d6444..4371b3ccfb 100644 --- a/ports/ChangeLog.arm +++ b/ports/ChangeLog.arm @@ -1,3 +1,13 @@ +2014-01-14 Will Newton <will.newton@linaro.org> + + * sysdeps/arm/__longjmp.S: Don't apply pointer encryption + to fp register. + * sysdeps/arm/setjmp.S: Likewise. + * sysdeps/arm/include/bits/setjmp.h (JMP_BUF_REGLIST): Add + fp to register list, remove a4. + * sysdeps/unix/sysv/linux/arm/sysdep.h (PTR_MANGLE_LOAD): + New macro. + 2014-01-10 Roland McGrath <roland@hack.frob.com> * sysdeps/arm/arm-mcount.S: diff --git a/ports/sysdeps/arm/__longjmp.S b/ports/sysdeps/arm/__longjmp.S index 1503923aaa..27c57a12df 100644 --- a/ports/sysdeps/arm/__longjmp.S +++ b/ports/sysdeps/arm/__longjmp.S @@ -41,14 +41,12 @@ ENTRY (__longjmp) sfi_sp sfi_breg ip, \ ldmia \B!, JMP_BUF_REGLIST #ifdef PTR_DEMANGLE - PTR_DEMANGLE (fp, a4, a3, a2) ldr a4, [ip], #4 - PTR_DEMANGLE2 (a4, a4, a3) + PTR_DEMANGLE (a4, a4, a3, a2) mov sp, a4 ldr a4, [ip], #4 PTR_DEMANGLE2 (lr, a4, a3) #else - mov fp, a4 ldr sp, [ip], #4 ldr lr, [ip], #4 #endif diff --git a/ports/sysdeps/arm/include/bits/setjmp.h b/ports/sysdeps/arm/include/bits/setjmp.h index 2f502457d8..220dfe8d96 100644 --- a/ports/sysdeps/arm/include/bits/setjmp.h +++ b/ports/sysdeps/arm/include/bits/setjmp.h @@ -26,9 +26,8 @@ #ifndef _ISOMAC /* Register list for a ldm/stm instruction to load/store - the general registers from a __jmp_buf. The a4 register - contains fp at this point. */ -# define JMP_BUF_REGLIST {a4, v1-v6, sl} + the general registers from a __jmp_buf. */ +# define JMP_BUF_REGLIST {v1-v6, sl, fp} /* Index of __jmp_buf where the sp register resides. */ # define __JMP_BUF_SP 8 diff --git a/ports/sysdeps/arm/setjmp.S b/ports/sysdeps/arm/setjmp.S index 96657071dd..b0b45ed8da 100644 --- a/ports/sysdeps/arm/setjmp.S +++ b/ports/sysdeps/arm/setjmp.S @@ -23,9 +23,7 @@ ENTRY (__sigsetjmp) #ifdef PTR_MANGLE - PTR_MANGLE (a4, fp, a3, ip) -#else - mov a4, fp + PTR_MANGLE_LOAD (a3, ip) #endif mov ip, r0 diff --git a/ports/sysdeps/unix/sysv/linux/arm/sysdep.h b/ports/sysdeps/unix/sysv/linux/arm/sysdep.h index 11d0a1146e..dcd99198cc 100644 --- a/ports/sysdeps/unix/sysv/linux/arm/sysdep.h +++ b/ports/sysdeps/unix/sysv/linux/arm/sysdep.h @@ -439,8 +439,10 @@ __local_syscall_error: \ #if (defined NOT_IN_libc && defined IS_IN_rtld) || \ (!defined SHARED && (!defined NOT_IN_libc || defined IS_IN_libpthread)) # ifdef __ASSEMBLER__ +# define PTR_MANGLE_LOAD(guard, tmp) \ + LDST_PCREL(ldr, guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard_local)); # define PTR_MANGLE(dst, src, guard, tmp) \ - LDST_PCREL(ldr, guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard_local)); \ + PTR_MANGLE_LOAD(guard, tmp); \ PTR_MANGLE2(dst, src, guard) /* Use PTR_MANGLE2 for efficiency if guard is already loaded. */ # define PTR_MANGLE2(dst, src, guard) \ @@ -457,8 +459,10 @@ extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden; # endif #else # ifdef __ASSEMBLER__ +# define PTR_MANGLE_LOAD(guard, tmp) \ + LDST_GLOBAL(ldr, guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard)); # define PTR_MANGLE(dst, src, guard, tmp) \ - LDST_GLOBAL(ldr, guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard)); \ + PTR_MANGLE_LOAD(guard, tmp); \ PTR_MANGLE2(dst, src, guard) /* Use PTR_MANGLE2 for efficiency if guard is already loaded. */ # define PTR_MANGLE2(dst, src, guard) \ |