1 | /* Copyright (C) 2001-2022 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 |
30 | longjmp_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 |
50 | ENTRY (____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 |
124 | END (____longjmp_chk) |
125 | |