1/* Copyright (C) 2001-2021 Free Software Foundation, Inc. 2 This file is part of the GNU C Library. 3 4 The GNU C Library is free software; you can redistribute it and/or 5 modify it under the terms of the GNU Lesser General Public 6 License as published by the Free Software Foundation; either 7 version 2.1 of the License, or (at your option) any later version. 8 9 The GNU C Library is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 14 You should have received a copy of the GNU Lesser General Public 15 License along with the GNU C Library; if not, see 16 <https://www.gnu.org/licenses/>. */ 17 18#include <sysdep.h> 19#include <jmpbuf-offsets.h> 20#include <tcb-offsets.h> 21#include <asm-syntax.h> 22 23#include <signal-defines.h> 24/* #include <signal.h> */ 25#define SS_ONSTACK 1 26 27 28 .section .rodata.str1.1,"aMS",@progbits,1 29 .type longjmp_msg,@object 30longjmp_msg: 31 .string "longjmp causes uninitialized stack frame" 32 .size longjmp_msg, .-longjmp_msg 33 34 35#ifdef PIC 36# define CALL_FAIL movl %ebx, %ecx; /* TODO: what's this mov good for? */ \ 37 cfi_register(%ebx,%ecx); \ 38 LOAD_PIC_REG (bx); \ 39 leal longjmp_msg@GOTOFF(%ebx), %eax; \ 40 movl %eax, (%esp); \ 41 call HIDDEN_JUMPTARGET(__fortify_fail) 42#else 43# define CALL_FAIL movl $longjmp_msg, %eax; \ 44 movl %eax, (%esp); \ 45 call HIDDEN_JUMPTARGET(__fortify_fail) 46#endif 47 48 49 .text 50ENTRY (____longjmp_chk) 51 movl 4(%esp), %eax /* User's jmp_buf in %eax. */ 52 53 /* Save the return address now. */ 54 movl (JB_PC*4)(%eax), %edx 55 /* Get the stack pointer. */ 56 movl (JB_SP*4)(%eax), %ecx 57 cfi_undefined(%ecx) 58#ifdef PTR_DEMANGLE 59 PTR_DEMANGLE (%edx) 60 PTR_DEMANGLE (%ecx) 61#endif 62 63 movw %ds, %si 64 movw %gs, %di 65 cmpw %si, %di 66 jz .Lok /* TLS not initialized yet */ 67 68 movl %gs:SIGSTATE_OFFSET, %edi 69 testl %edi, %edi 70 jz .Lok /* sigstate not initialized yet */ 71 72 testl $SS_ONSTACK, (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_FLAGS__OFFSET)(%edi) 73 jnz .Lonstack 74 75 /* We were on the main stack */ 76 77 cmpl %ecx, %esp 78 /* Jumping to a higher-address frame is always allowed. */ 79 jbe .Lok 80 81 /* Otherwise it's not allowed. */ 82 CALL_FAIL 83 84.Lonstack: 85 /* We were on the alternate stack, can't really easily check anything 86 since longjmp may get us out of the alternate stack. */ 87 88 cmpl (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_SP__OFFSET)(%edi), %ecx 89 jb .Loks /* We jump below the alternate stack, switch. */ 90 91 movl (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_SP__OFFSET)(%edi), %ebx 92 addl (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_SIZE__OFFSET)(%edi), %ebx 93 cmpl %ebx, %ecx 94 jb .Lok /* We jump inside the alternate stack, do not switch. */ 95 96 /* We jump above the alternate stack, switch. */ 97 98.Loks: /* We jump out of the alternate stack, clear SS_ONSTACK flag. */ 99 andl $~(SS_ONSTACK), (HURD_SIGSTATE__SIGALTSTACK__OFFSET + SIGALTSTACK__SS_FLAGS__OFFSET)(%edi) 100 101.Lok: /* We add unwind information for the target here. */ 102 cfi_def_cfa(%eax, 0) 103 cfi_register(%eip, %edx) 104 cfi_register(%esp, %ecx) 105 cfi_offset(%ebx, JB_BX*4) 106 cfi_offset(%esi, JB_SI*4) 107 cfi_offset(%edi, JB_DI*4) 108 cfi_offset(%ebp, JB_BP*4) 109 /* Restore registers. */ 110 movl (JB_BX*4)(%eax), %ebx 111 movl (JB_SI*4)(%eax), %esi 112 movl (JB_DI*4)(%eax), %edi 113 movl (JB_BP*4)(%eax), %ebp 114 cfi_restore(%ebx) 115 cfi_restore(%esi) 116 cfi_restore(%edi) 117 cfi_restore(%ebp) 118 119 movl 8(%esp), %eax /* Second argument is return value. */ 120 movl %ecx, %esp 121 122 /* Jump to saved PC. */ 123 jmp *%edx 124END (____longjmp_chk) 125