[glibc/f20] Resolves: #1019452

Siddhesh Poyarekar siddhesh at fedoraproject.org
Thu Feb 6 11:12:37 UTC 2014


commit f4ab03df66ceb8f838af40e8f3afadc641b2155a
Author: Siddhesh Poyarekar <siddhesh at redhat.com>
Date:   Thu Feb 6 16:42:20 2014 +0530

    Resolves: #1019452
    
    Add pointer mangling support for ARM.

 glibc-rh1019452.patch |  216 +++++++++++++++++++++++++++++++++++++++++++++++++
 glibc.spec            |    7 ++-
 2 files changed, 222 insertions(+), 1 deletions(-)
---
diff --git a/glibc-rh1019452.patch b/glibc-rh1019452.patch
new file mode 100644
index 0000000..cce6638
--- /dev/null
+++ b/glibc-rh1019452.patch
@@ -0,0 +1,216 @@
+commit b7f2d27dbd85f6a0966dc389ad4f8205085b7ae8
+Author: Will Newton <will.newton at linaro.org>
+Date:   Wed Aug 7 13:55:30 2013 +0100
+
+    ARM: Add pointer encryption support.
+    
+    Add support for pointer encryption in glibc internal structures in C
+    and assembler code. Pointer encryption is a glibc security feature
+    described here:
+    
+    https://sourceware.org/glibc/wiki/PointerEncryption
+    
+    The ARM implementation uses global variables instead of thread pointer
+    relative accesses to get the value of the pointer encryption guard
+    because accessing the thread pointer can be very expensive on older
+    ARM cores.
+    
+    ports/ChangeLog.arm:
+    
+    2013-10-03  Will Newton  <will.newton at linaro.org>
+    
+    	* sysdeps/arm/__longjmp.S (__longjmp): Demangle fp, sp
+    	and lr when restoring register values.
+    	* sysdeps/arm/include/bits/setjmp.h (JMP_BUF_REGLIST): Remove
+    	sp and lr from list and replace fp with a4.
+    	* sysdeps/arm/jmpbuf-unwind.h (_jmpbuf_sp): New function.
+    	(_JMPBUF_UNWINDS_ADJ): Call _jmpbuf_sp.
+    	* sysdeps/arm/setjmp.S (__sigsetjmp): Mangle fp, sp and lr
+    	before storing register values.
+    	* sysdeps/arm/sysdep.h (LDST_GLOBAL): New macro.
+    	* sysdeps/unix/sysv/linux/arm/sysdep.h (PTR_MANGLE): New macro.
+    	(PTR_DEMANGLE): Likewise. (PTR_MANGLE2): Likewise.
+    	(PTR_DEMANGLE2): Likewise.
+
+diff --git a/ports/sysdeps/arm/__longjmp.S b/ports/sysdeps/arm/__longjmp.S
+index a5edede..2b1f7f4 100644
+--- a/ports/sysdeps/arm/__longjmp.S
++++ b/ports/sysdeps/arm/__longjmp.S
+@@ -34,10 +34,24 @@ ENTRY (__longjmp)
+ 	sfi_breg ip, \
+ 	ldr	r4, [\B, #32]	/* jmpbuf's sp */
+ 	cfi_undefined (r4)
++#ifdef PTR_DEMANGLE
++	PTR_DEMANGLE (r4, r4, a3, a4)
++#endif
+ 	CHECK_SP (r4)
+ #endif
+ 	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 (sp, a4, a3)
++	ldr	a4, [ip], #4
++	PTR_DEMANGLE2 (lr, a4, a3)
++#else
++	mov	fp, a4
++	ldr	sp, [ip], #4
++	ldr	lr, [ip], #4
++#endif
+ 	cfi_restore (v1)
+ 	cfi_restore (v2)
+ 	cfi_restore (v3)
+diff --git a/ports/sysdeps/arm/include/bits/setjmp.h b/ports/sysdeps/arm/include/bits/setjmp.h
+index 1559d7b..64505dc 100644
+--- a/ports/sysdeps/arm/include/bits/setjmp.h
++++ b/ports/sysdeps/arm/include/bits/setjmp.h
+@@ -26,8 +26,9 @@
+ 
+ #ifndef _ISOMAC
+ /* Register list for a ldm/stm instruction to load/store
+-   the general registers from a __jmp_buf.  */
+-# define JMP_BUF_REGLIST	{v1-v6, sl, fp, sp, lr}
++   the general registers from a __jmp_buf. The a4 register
++   contains fp at this point.  */
++# define JMP_BUF_REGLIST	{a4, v1-v6, sl}
+ 
+ /* Index of __jmp_buf where the sp register resides.  */
+ # define __JMP_BUF_SP		8
+diff --git a/ports/sysdeps/arm/jmpbuf-unwind.h b/ports/sysdeps/arm/jmpbuf-unwind.h
+index 0863540..1b0d020 100644
+--- a/ports/sysdeps/arm/jmpbuf-unwind.h
++++ b/ports/sysdeps/arm/jmpbuf-unwind.h
+@@ -17,6 +17,7 @@
+ 
+ #include <setjmp.h>
+ #include <stdint.h>
++#include <sysdep.h>
+ #include <unwind.h>
+ 
+ /* Test if longjmp to JMPBUF would unwind the frame
+@@ -27,8 +28,18 @@
+ #define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
+   _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
+ 
++static inline uintptr_t __attribute__ ((unused))
++_jmpbuf_sp (__jmp_buf regs)
++{
++  uintptr_t sp = regs[__JMP_BUF_SP];
++#ifdef PTR_DEMANGLE
++  PTR_DEMANGLE (sp);
++#endif
++  return sp;
++}
++
+ #define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
+-  ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[__JMP_BUF_SP] - (_adj))
++  ((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj))
+ 
+ /* We use the normal longjmp for unwinding.  */
+ #define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val)
+diff --git a/ports/sysdeps/arm/setjmp.S b/ports/sysdeps/arm/setjmp.S
+index a6c161d..b38b919 100644
+--- a/ports/sysdeps/arm/setjmp.S
++++ b/ports/sysdeps/arm/setjmp.S
+@@ -24,11 +24,25 @@
+ #include <arm-features.h>
+ 
+ ENTRY (__sigsetjmp)
++#ifdef PTR_MANGLE
++	PTR_MANGLE (a4, fp, a3, ip)
++#else
++	mov	a4, fp
++#endif
+ 	mov	ip, r0
+ 
+ 	/* Save registers */
+ 	sfi_breg ip, \
+ 	stmia	\B!, JMP_BUF_REGLIST
++#ifdef PTR_MANGLE
++	PTR_MANGLE2 (a4, sp, a3)
++	str	a4, [ip], #4
++	PTR_MANGLE2 (a4, lr, a3)
++	str	a4, [ip], #4
++#else
++	str	sp, [ip], #4
++	str	lr, [ip], #4
++#endif
+ 
+ #if !defined ARM_ASSUME_NO_IWMMXT || defined __SOFTFP__
+ # define NEED_HWCAP 1
+diff --git a/ports/sysdeps/arm/sysdep.h b/ports/sysdeps/arm/sysdep.h
+index 5501597..3823617 100644
+--- a/ports/sysdeps/arm/sysdep.h
++++ b/ports/sysdeps/arm/sysdep.h
+@@ -171,6 +171,18 @@
+ 99:	OP	R, [pc, T]
+ # endif
+ 
++/* Load or store to/from a global EXPR into/from R, using T.  */
++# define LDST_GLOBAL(OP, R, T, EXPR)			\
++	ldr	T, 99f;					\
++	ldr	R, 100f;				\
++98:	add	T, T, pc;				\
++	ldr	T, [T, R];				\
++	.subsection 2;					\
++99:	.word	_GLOBAL_OFFSET_TABLE_ - 98b - PC_OFS;	\
++100:	.word	EXPR##(GOT);				\
++	.previous;					\
++	OP	R, [T]
++
+ /* Cope with negative memory offsets, which thumb can't encode.
+    Use NEGOFF_ADJ_BASE to (conditionally) alter the base register,
+    and then NEGOFF_OFF1 to use 0 for thumb and the offset for arm,
+diff --git a/ports/sysdeps/unix/sysv/linux/arm/sysdep.h b/ports/sysdeps/unix/sysv/linux/arm/sysdep.h
+index b195d8e..6cfe4e0 100644
+--- a/ports/sysdeps/unix/sysv/linux/arm/sysdep.h
++++ b/ports/sysdeps/unix/sysv/linux/arm/sysdep.h
+@@ -435,8 +435,44 @@ __local_syscall_error:						\
+ 
+ #endif	/* __ASSEMBLER__ */
+ 
+-/* Pointer mangling is not yet supported for ARM.  */
+-#define PTR_MANGLE(var) (void) (var)
+-#define PTR_DEMANGLE(var) (void) (var)
++/* Pointer mangling support.  */
++#if (defined NOT_IN_libc && defined IS_IN_rtld) || \
++  (!defined SHARED && (!defined NOT_IN_libc || defined IS_IN_libpthread))
++# ifdef __ASSEMBLER__
++#  define PTR_MANGLE(dst, src, guard, tmp)				\
++  LDST_PCREL(ldr, guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard_local)); \
++  PTR_MANGLE2(dst, src, guard)
++/* Use PTR_MANGLE2 for efficiency if guard is already loaded.  */
++#  define PTR_MANGLE2(dst, src, guard)		\
++  eor dst, src, guard
++#  define PTR_DEMANGLE(dst, src, guard, tmp)	\
++  PTR_MANGLE (dst, src, guard, tmp)
++#  define PTR_DEMANGLE2(dst, src, guard)	\
++  PTR_MANGLE2 (dst, src, guard)
++# else
++extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden;
++#  define PTR_MANGLE(var) \
++  (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local)
++#  define PTR_DEMANGLE(var)     PTR_MANGLE (var)
++# endif
++#else
++# ifdef __ASSEMBLER__
++#  define PTR_MANGLE(dst, src, guard, tmp)				\
++  LDST_GLOBAL(ldr, guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard));	\
++  PTR_MANGLE2(dst, src, guard)
++/* Use PTR_MANGLE2 for efficiency if guard is already loaded.  */
++#  define PTR_MANGLE2(dst, src, guard)		\
++  eor dst, src, guard
++#  define PTR_DEMANGLE(dst, src, guard, tmp)	\
++  PTR_MANGLE (dst, src, guard, tmp)
++#  define PTR_DEMANGLE2(dst, src, guard)	\
++  PTR_MANGLE2 (dst, src, guard)
++# else
++extern uintptr_t __pointer_chk_guard attribute_relro;
++#  define PTR_MANGLE(var) \
++  (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard)
++#  define PTR_DEMANGLE(var)     PTR_MANGLE (var)
++# endif
++#endif
+ 
+ #endif /* linux/arm/sysdep.h */
diff --git a/glibc.spec b/glibc.spec
index c2464fe..a87a565 100644
--- a/glibc.spec
+++ b/glibc.spec
@@ -1,6 +1,6 @@
 %define glibcsrcdir glibc-2.18
 %define glibcversion 2.18
-%define glibcrelease 12%{?dist}
+%define glibcrelease 13%{?dist}
 # Pre-release tarballs are pulled in from git using a command that is
 # effectively:
 #
@@ -191,6 +191,7 @@ Patch1001: %{name}-rh995841.patch
 Patch1002: %{name}-rh1008299.patch
 Patch1003: %{name}-rh1047979.patch
 Patch1004: %{name}-rh1055613.patch
+Patch1005: %{name}-rh1019452.patch
 
 #
 # Patches submitted, but not yet approved upstream.
@@ -568,6 +569,7 @@ package or when debugging this package.
 %patch0043 -p1
 %patch1003 -p1
 %patch1004 -p1
+%patch1005 -p1
 
 ##############################################################################
 # %%prep - Additional prep required...
@@ -1653,6 +1655,9 @@ rm -f *.filelist*
 %endif
 
 %changelog
+* Thu Feb  6 2014 Siddhesh Poyarekar <siddhesh at redhat.com> - 2.18-13
+- Add pointer mangling support for ARM (#1019452).
+
 * Thu Jan 23 2014 Siddhesh Poyarekar <siddhesh at redhat.com> - 2.18-12
 - Use first name entry for address in /etc/hosts as the canonical name
   in getaddrinfo (#1047979).


More information about the scm-commits mailing list