Fix x86-64 ____longjmp_chk to handle signal stacks.

The simple test previously used might trigger if the longjmp jumps
from the signal stack to the normal stack.  We now explicitly test
for this case.
This commit is contained in:
Ulrich Drepper 2009-07-30 17:31:48 -07:00
parent 2dec6007d1
commit 5ead9ce5c7
3 changed files with 111 additions and 7 deletions

View File

@ -1,5 +1,10 @@
2009-07-30 Ulrich Drepper <drepper@redhat.com>
* sysdeps/x86_64/__longjmp.S: Remove CHECK_RSP handling. Fix CFI.
Remove incorrect use of BP_SYM.
* sysdeps/x86_64/____longjmp_chk.S: Rewrite. Complete implementation
here now since it is more complex than just a simple check.
* sysdeps/ia64/backtrace.c (backtrace_helper): Stop backtrace when
we make no more progress.

View File

@ -16,6 +16,10 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <sysdep.h>
#include <jmpbuf-offsets.h>
#include <asm-syntax.h>
.section .rodata.str1.1,"aMS",@progbits,1
.type longjmp_msg,@object
longjmp_msg:
@ -23,7 +27,7 @@ longjmp_msg:
.size longjmp_msg, .-longjmp_msg
#define __longjmp ____longjmp_chk
//#define __longjmp ____longjmp_chk
#ifdef PIC
# define CALL_FAIL leaq longjmp_msg(%rip), %rdi; \
@ -39,4 +43,103 @@ longjmp_msg:
CALL_FAIL; \
.Lok:
#include "__longjmp.S"
/* Jump to the position specified by ENV, causing the
setjmp call there to return VAL, or 1 if VAL is 0.
void __longjmp (__jmp_buf env, int val). */
.text
ENTRY(____longjmp_chk)
/* Restore registers. */
movq (JB_RSP*8)(%rdi),%r8
movq (JB_RBP*8)(%rdi),%r9
movq (JB_PC*8)(%rdi),%rdx
#ifdef PTR_DEMANGLE
PTR_DEMANGLE (%r8)
PTR_DEMANGLE (%r9)
PTR_DEMANGLE (%rdx)
#endif
/* Save function parameters. */
movq %rdi, %r10
movl %esi, %ecx
xorl %eax, %eax
cmpq %r8, %rsp
jbe .Lok
subq $32, %rsp
cfi_adjust_cfa_offset(32)
movq %r10, 24(%rsp)
xorl %edi, %edi
movq %rsp, %rsi
movl $__NR_sigaltstack, %eax
syscall
movq 24(%rsp), %r10
testl %eax, %eax
movl $0, %eax
jne .Lok
movl 8(%rsp), %eax
andl $1, %eax
.Lok:
/* We add unwind information for the target here. */
cfi_def_cfa(%r10, 0)
cfi_register(%rsp,%r8)
cfi_register(%rbp,%r9)
cfi_register(%rip,%rdx)
cfi_offset(%rbx,JB_RBX*8)
cfi_offset(%r12,JB_R12*8)
cfi_offset(%r13,JB_R13*8)
cfi_offset(%r14,JB_R14*8)
cfi_offset(%r15,JB_R15*8)
xchgq %r8, %rsp
cfi_restore(%rsp)
xchgq %r9, %rbp
cfi_restore(%rbp)
movq (JB_RBX*8)(%r10),%rbx
movq (JB_R12*8)(%r10),%r12
movq (JB_R13*8)(%r10),%r13
movq (JB_R14*8)(%r10),%r14
movq (JB_R15*8)(%r10),%r15
cmpq %rsp, %r8
jnbe .Lcheck
/* Set return value for setjmp. */
.Lout: movl %ecx, %eax
jmpq *%rdx
.Lcheck:
testl %eax, %eax
je .Lfail
subq $24, %rsp
cfi_adjust_cfa_offset(24)
xorl %edi, %edi
movq %rsp, %rsi
movl $__NR_sigaltstack, %eax
syscall
addq $24, %rsp
cfi_adjust_cfa_offset(-24)
testl $1, 8(%rsp)
je .Lout
.Lfail: xchgq %r8, %rsp
/* We want the stack trace to show that of the caller. */
cfi_def_cfa(%rsp, 40)
cfi_restore(%rsp)
cfi_register(%rbp, %r9)
cfi_restore(%rip)
cfi_restore(%rbx)
cfi_restore(%r12)
cfi_restore(%r13)
cfi_restore(%r14)
cfi_restore(%r15)
xchgq %r9, %rbp
cfi_restore(%rbp)
CALL_FAIL
hlt
END (BP_SYM (____longjmp_chk))

View File

@ -33,9 +33,6 @@ ENTRY(__longjmp)
PTR_DEMANGLE (%r8)
PTR_DEMANGLE (%r9)
PTR_DEMANGLE (%rdx)
#endif
#ifdef CHECK_RSP
CHECK_RSP (%r8)
#endif
/* We add unwind information for the target here. */
cfi_def_cfa(%rdi, 0)
@ -43,7 +40,6 @@ ENTRY(__longjmp)
cfi_register(%rbp,%r9)
cfi_register(%rip,%rdx)
cfi_offset(%rbx,JB_RBX*8)
cfi_offset(%rbp,JB_RBP*8)
cfi_offset(%r12,JB_R12*8)
cfi_offset(%r13,JB_R13*8)
cfi_offset(%r14,JB_R14*8)
@ -58,4 +54,4 @@ ENTRY(__longjmp)
movq %r8,%rsp
movq %r9,%rbp
jmpq *%rdx
END (BP_SYM (__longjmp))
END (__longjmp)