ia64: longjmp_chk: support signal stacks [BZ #16372]
authorMike Frysinger <vapier@gentoo.org>
Sun, 29 Dec 2013 21:16:25 +0000 (21:16 +0000)
committerMike Frysinger <vapier@gentoo.org>
Tue, 31 Dec 2013 04:12:16 +0000 (23:12 -0500)
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>
NEWS
ports/ChangeLog.ia64
ports/sysdeps/unix/sysv/linux/ia64/Makefile
ports/sysdeps/unix/sysv/linux/ia64/____longjmp_chk.S
ports/sysdeps/unix/sysv/linux/ia64/__longjmp.S
ports/sysdeps/unix/sysv/linux/ia64/sigaltstack-offsets.sym [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 6a122207c506abcbce5ae0907377577467b8c39c..a94db2380ccf21e94a93df64087ee0975029c4b1 100644 (file)
--- 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.
index d5e19243588e91b3ef80a7ff5a461f478ee7c450..c0bac5567c4aece6ef50705a26683745d53aefaa 100644 (file)
@@ -1,3 +1,14 @@
+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]
index d9a35a7c673f5db007e83ea714d38e8f61656dcf..bbfd6a239271727b79a882e1e08577ba147c3c5b 100644 (file)
@@ -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)
index f4ce5d3a3c1afea796c7104dbcecde1e781a78a4..ccaf3ccf84d3e284df33196b3ce3df85aaa5ca0e 100644 (file)
@@ -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"
index 4860a8caef7231da326da14f53c2011fe23454cf..4968802ae9daeb8b9b04965d1b870de6f90a2c0b 100644 (file)
 
 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 (file)
index 0000000..f734469
--- /dev/null
@@ -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