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>
This commit is contained in:
Mike Frysinger 2013-12-29 21:16:25 +00:00
parent e646a161ce
commit 98b78b4b72
6 changed files with 83 additions and 13 deletions

2
NEWS
View File

@ -23,7 +23,7 @@ Version 2.19
16038, 16041, 16055, 16071, 16072, 16074, 16077, 16078, 16103, 16112, 16038, 16041, 16055, 16071, 16072, 16074, 16077, 16078, 16103, 16112,
16143, 16144, 16146, 16150, 16151, 16153, 16167, 16172, 16195, 16214, 16143, 16144, 16146, 16150, 16151, 16153, 16167, 16172, 16195, 16214,
16245, 16271, 16274, 16283, 16289, 16293, 16314, 16316, 16330, 16337, 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 * Slovenian translations for glibc messages have been contributed by the
Translation Project's Slovenian team of translators. Translation Project's Slovenian team of translators.

View 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> 2013-12-30 Mike Frysinger <vapier@gentoo.org>
[BZ #16379] [BZ #16379]

View File

@ -10,6 +10,7 @@ endif
ifeq ($(subdir),misc) ifeq ($(subdir),misc)
sysdep_headers += sys/io.h sysdep_headers += sys/io.h
sysdep_routines += ioperm clone2 sysdep_routines += ioperm clone2
gen-as-const-headers += sigaltstack-offsets.sym
endif endif
ifeq ($(subdir),elf) ifeq ($(subdir),elf)

View File

@ -15,6 +15,8 @@
License along with the GNU C Library; if not, see License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
#include <sigaltstack-offsets.h>
.section .rodata.str1.8,"aMS",@progbits,1 .section .rodata.str1.8,"aMS",@progbits,1
.align 8 .align 8
.LC0: .LC0:
@ -29,13 +31,58 @@ longjmp_msg:
#define __longjmp ____longjmp_chk #define __longjmp ____longjmp_chk
#define CHECK_RSP(reg) \ /* We use 32 bytes (rather than sizeof(stack_t)) so that we keep the stack
cmp.ltu p0, p8 = reg, r12; \ properly aligned. But we still want a sanity check to make sure 32 is
(p8) br.cond.dpnt .Lok;; \ actually enough. */
addl r28 = @ltoffx(longjmp_msg#), r1;; \ #define STACK_SPACE ((sizeSS + 31) & -32)
ld8.mov r28 = [r28], longjmp_msg#;; \
ld8 out0 = [r28]; \ /* 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)#;; \ br.call.sptk.many b0 = HIDDEN_JUMPTARGET(__fortify_fail)#;; \
.Lok: .Lok: \
add r12 = STACK_SPACE, r12;
#include "__longjmp.S" #include "__longjmp.S"

View File

@ -42,9 +42,10 @@
LEAF(__longjmp) LEAF(__longjmp)
#ifdef CHECK_RSP #ifdef CHECK_RSP
alloc r8=ar.pfs,2,1,1,0 alloc r8=ar.pfs,2,1,3,0
CHECK_RSP
#else #else
alloc r8=ar.pfs,2,1,0,0 alloc r8=ar.pfs,2,0,0,0
#endif #endif
mov r27=ar.rsc mov r27=ar.rsc
add r2=0x98,in0 // r2 <- &jmpbuf.orig_jmp_buf_addr add r2=0x98,in0 // r2 <- &jmpbuf.orig_jmp_buf_addr
@ -79,9 +80,6 @@ LEAF(__longjmp)
mov r26=ar.rnat mov r26=ar.rnat
mov ar.unat=r25 // setup ar.unat (NaT bits for r1, r4-r7, and r12) 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) ld8.fill.nta gp=[r3],32 // r1 (gp)
dep r11=-1,r23,3,6 // r11 <- ia64_rse_rnat_addr(jmpbuf.ar_bsp) dep r11=-1,r23,3,6 // r11 <- ia64_rse_rnat_addr(jmpbuf.ar_bsp)
mov sp=r28 // r12 (sp) mov sp=r28 // r12 (sp)

View File

@ -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