summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2013-12-29 21:16:25 +0000
committerMike Frysinger <vapier@gentoo.org>2013-12-30 23:12:16 -0500
commit98b78b4b72131264b1950edbcd94287041ec8311 (patch)
treefebc663314bcf3ea0680513b11d0db1464bb2820
parente646a161cef3069fe1a6c92b750a87350630c62d (diff)
downloadglibc-98b78b4b72131264b1950edbcd94287041ec8311.tar.gz
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>
-rw-r--r--NEWS2
-rw-r--r--ports/ChangeLog.ia6411
-rw-r--r--ports/sysdeps/unix/sysv/linux/ia64/Makefile1
-rw-r--r--ports/sysdeps/unix/sysv/linux/ia64/____longjmp_chk.S61
-rw-r--r--ports/sysdeps/unix/sysv/linux/ia64/__longjmp.S8
-rw-r--r--ports/sysdeps/unix/sysv/linux/ia64/sigaltstack-offsets.sym13
6 files changed, 83 insertions, 13 deletions
diff --git a/NEWS b/NEWS
index 6a122207c5..a94db2380c 100644
--- a/NEWS
+++ b/NEWS
@@ -23,7 +23,7 @@ Version 2.19
16038, 16041, 16055, 16071, 16072, 16074, 16077, 16078, 16103, 16112,
16143, 16144, 16146, 16150, 16151, 16153, 16167, 16172, 16195, 16214,
16245, 16271, 16274, 16283, 16289, 16293, 16314, 16316, 16330, 16337,
- 16338, 16356, 16369, 16375.
+ 16338, 16356, 16369, 16372, 16375.
* Slovenian translations for glibc messages have been contributed by the
Translation Project's Slovenian team of translators.
diff --git a/ports/ChangeLog.ia64 b/ports/ChangeLog.ia64
index d5e1924358..c0bac5567c 100644
--- a/ports/ChangeLog.ia64
+++ b/ports/ChangeLog.ia64
@@ -1,5 +1,16 @@
2013-12-30 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.
+
+2013-12-30 Mike Frysinger <vapier@gentoo.org>
+
[BZ #16379]
* sysdeps/unix/sysv/linux/ia64/__longjmp.S: Comment out loading of
fpsr. Update offsets accordingly.
diff --git a/ports/sysdeps/unix/sysv/linux/ia64/Makefile b/ports/sysdeps/unix/sysv/linux/ia64/Makefile
index d9a35a7c67..bbfd6a2392 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 f4ce5d3a3c..ccaf3ccf84 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 4860a8caef..4968802ae9 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 0000000000..f73446941a
--- /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