This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH v2] ia64: longjmp_chk: support signal stacks [BZ #16372]


The sp check has to be moved up to the start of the func since it now
makes a system call and that'll clobber a lot of registers.

URL: https://sourceware.org/bugzilla/show_bug.cgi?id=16372
Signed-off-by: Mike Frysinger <vapier@gentoo.org>

2013-12-29   Mike Frysinger  <vapier@gentoo.org>

	* sysdeps/unix/sysv/linux/ia64/Makefile (gen-as-const-headers): Add
	sigaltstack-offsets.sym.
	* sysdeps/unix/sysv/linux/ia64/____longjmp_chk.S: Include new
	sigaltstack-offsets.h header.
	(STACK_SPACE): Define.
	(CHECK_RSP): Rewrite to support sigaltstack.
	* sysdeps/unix/sysv/linux/ia64/__longjmp.S: Move CHECK_RSP to top.
	* sysdeps/unix/sysv/linux/ia64/sigaltstack-offsets.sym: New file.
---
v2
	- apply Andreas' stack fix
	- improve assembly a bit more

 ports/sysdeps/unix/sysv/linux/ia64/Makefile        |  1 +
 .../sysdeps/unix/sysv/linux/ia64/____longjmp_chk.S | 61 +++++++++++++++++++---
 ports/sysdeps/unix/sysv/linux/ia64/__longjmp.S     |  8 ++-
 .../unix/sysv/linux/ia64/sigaltstack-offsets.sym   | 13 +++++
 4 files changed, 71 insertions(+), 12 deletions(-)
 create mode 100644 ports/sysdeps/unix/sysv/linux/ia64/sigaltstack-offsets.sym

diff --git a/ports/sysdeps/unix/sysv/linux/ia64/Makefile b/ports/sysdeps/unix/sysv/linux/ia64/Makefile
index d9a35a7..bbfd6a2 100644
--- a/ports/sysdeps/unix/sysv/linux/ia64/Makefile
+++ b/ports/sysdeps/unix/sysv/linux/ia64/Makefile
@@ -10,6 +10,7 @@ endif
 ifeq ($(subdir),misc)
 sysdep_headers += sys/io.h
 sysdep_routines += ioperm clone2
+gen-as-const-headers += sigaltstack-offsets.sym
 endif
 
 ifeq ($(subdir),elf)
diff --git a/ports/sysdeps/unix/sysv/linux/ia64/____longjmp_chk.S b/ports/sysdeps/unix/sysv/linux/ia64/____longjmp_chk.S
index f4ce5d3..ccaf3cc 100644
--- a/ports/sysdeps/unix/sysv/linux/ia64/____longjmp_chk.S
+++ b/ports/sysdeps/unix/sysv/linux/ia64/____longjmp_chk.S
@@ -15,6 +15,8 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <sigaltstack-offsets.h>
+
 	.section .rodata.str1.8,"aMS",@progbits,1
 	.align 8
 .LC0:
@@ -29,13 +31,58 @@ longjmp_msg:
 
 #define __longjmp ____longjmp_chk
 
-#define CHECK_RSP(reg) \
-	cmp.ltu p0, p8 = reg, r12;				\
-(p8)	br.cond.dpnt .Lok;;					\
-	addl r28 = @ltoffx(longjmp_msg#), r1;;			\
-	ld8.mov r28 = [r28], longjmp_msg#;;			\
-	ld8 out0 = [r28];					\
+/* We use 32 bytes (rather than sizeof(stack_t)) so that we keep the stack
+   properly aligned.  But we still want a sanity check to make sure 32 is
+   actually enough.  */
+#define STACK_SPACE ((sizeSS + 31) & -32)
+
+/* Check the stack pointer held in the jumpbuf.  Make sure it's in either the
+   current stack (r12) or in the signal stack.  */
+#define CHECK_RSP						\
+	ld8 loc0 = [in0];					\
+	;;							\
+	/* First see if target stack is within current one.  */	\
+	cmp.ltu p0, p8 = loc0, r12;				\
+(p8)	br.cond.dptk.many .Lok;					\
+								\
+	/* Check if it's an alternative signal stack.  */	\
+	mov out0 = r0;						\
+	add out1 = -STACK_SPACE, r12;				\
+	;;							\
+	mov r12 = out1;						\
+	DO_CALL_VIA_BREAK (SYS_ify (sigaltstack));		\
+	;;							\
+	/* If the syscall failed, then assume it's OK.  */	\
+	cmp.eq p8, p0 = -1, r10;				\
+(p8)	br.cond.spnt .Lok;					\
+	/* Move stack_t into regs.  */				\
+	add r14 = oSS_FLAGS, r12;	/* ss_flags */		\
+	add r15 = oSS_SIZE, r12;	/* ss_size */		\
+	ld8 r16 = [r12];		/* ss_sp */		\
+	;;							\
+	ld4 r17 = [r14];		/* ss_flags */		\
+	ld8 r18 = [r15];		/* ss_size */		\
+	;;							\
+	sub r19 = r16, r18;		/* sp - size */		\
+	/* See if we're currently on the altstack.  */		\
+	tbit.nz p0, p8 = r17, 0;	/* SS_ONSTACK */	\
+(p8)	br.cond.spnt .Lfail;					\
+	/* Verify target is within alternative stack.  */	\
+	cmp.gtu p7, p0 = loc0, r16;				\
+(p7)	br.cond.spnt .Lfail;					\
+	;;							\
+	cmp.ltu p0, p8 = loc0, r19;				\
+(p8)	br.cond.sptk.many .Lok;					\
+	;;							\
+								\
+	/* Still here?  Abort!  */				\
+.Lfail:								\
+	add r12 = STACK_SPACE, r12;				\
+	addl loc0 = @ltoffx(longjmp_msg#), r1;;			\
+	ld8.mov loc0 = [loc0], longjmp_msg#;;			\
+	ld8 out0 = [loc0];					\
 	br.call.sptk.many b0 = HIDDEN_JUMPTARGET(__fortify_fail)#;; \
-.Lok:
+.Lok:								\
+	add r12 = STACK_SPACE, r12;
 
 #include "__longjmp.S"
diff --git a/ports/sysdeps/unix/sysv/linux/ia64/__longjmp.S b/ports/sysdeps/unix/sysv/linux/ia64/__longjmp.S
index 4860a8c..4968802 100644
--- a/ports/sysdeps/unix/sysv/linux/ia64/__longjmp.S
+++ b/ports/sysdeps/unix/sysv/linux/ia64/__longjmp.S
@@ -42,9 +42,10 @@
 
 LEAF(__longjmp)
 #ifdef CHECK_RSP
-	alloc r8=ar.pfs,2,1,1,0
+	alloc r8=ar.pfs,2,1,3,0
+	CHECK_RSP
 #else
-	alloc r8=ar.pfs,2,1,0,0
+	alloc r8=ar.pfs,2,0,0,0
 #endif
 	mov r27=ar.rsc
 	add r2=0x98,in0		// r2 <- &jmpbuf.orig_jmp_buf_addr
@@ -79,9 +80,6 @@ LEAF(__longjmp)
 	mov r26=ar.rnat
 	mov ar.unat=r25		// setup ar.unat (NaT bits for r1, r4-r7, and r12)
 	;;
-#ifdef CHECK_RSP
-	CHECK_RSP (r28)
-#endif
 	ld8.fill.nta gp=[r3],32		// r1 (gp)
 	dep r11=-1,r23,3,6	// r11 <- ia64_rse_rnat_addr(jmpbuf.ar_bsp)
 	mov sp=r28		// r12 (sp)
diff --git a/ports/sysdeps/unix/sysv/linux/ia64/sigaltstack-offsets.sym b/ports/sysdeps/unix/sysv/linux/ia64/sigaltstack-offsets.sym
new file mode 100644
index 0000000..f734469
--- /dev/null
+++ b/ports/sysdeps/unix/sysv/linux/ia64/sigaltstack-offsets.sym
@@ -0,0 +1,13 @@
+#include <stddef.h>
+#include <signal.h>
+
+--
+
+#define sigaltstack(member)	offsetof (stack_t, member)
+
+sizeSS				sizeof (stack_t)
+oSS_SP				sigaltstack (ss_sp)
+oSS_FLAGS			sigaltstack (ss_flags)
+oSS_SIZE			sigaltstack (ss_size)
+
+SS_ONSTACK
-- 
1.8.4.3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]