]>
Commit | Line | Data |
---|---|---|
2b778ceb | 1 | /* Copyright (C) 2001-2021 Free Software Foundation, Inc. |
98b1e6c8 UD |
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 | |
59ba27a6 | 15 | License along with the GNU C Library; if not, see |
5a82c748 | 16 | <https://www.gnu.org/licenses/>. */ |
98b1e6c8 UD |
17 | |
18 | #include <sysdep.h> | |
19 | #include <jmpbuf-offsets.h> | |
20 | #include <asm-syntax.h> | |
8422c9a5 | 21 | #include <stap-probe.h> |
31e422ca L |
22 | #include <sigaltstack-offsets.h> |
23 | #include <jmp_buf-ssp.h> | |
98b1e6c8 | 24 | |
faaee1f0 L |
25 | /* Don't restore shadow stack register if shadow stack isn't enabled. */ |
26 | #if !SHSTK_ENABLED | |
27 | # undef SHADOW_STACK_POINTER_OFFSET | |
28 | #endif | |
29 | ||
98b1e6c8 UD |
30 | .section .rodata.str1.1,"aMS",@progbits,1 |
31 | .type longjmp_msg,@object | |
32 | longjmp_msg: | |
33 | .string "longjmp causes uninitialized stack frame" | |
34 | .size longjmp_msg, .-longjmp_msg | |
35 | ||
36 | ||
37 | //#define __longjmp ____longjmp_chk | |
38 | ||
39 | #ifdef PIC | |
85736dc7 | 40 | # define CALL_FAIL sub $8, %RSP_LP; \ |
e451d22b AS |
41 | cfi_remember_state; \ |
42 | cfi_def_cfa_offset(16); \ | |
85736dc7 | 43 | lea longjmp_msg(%rip), %RDI_LP; \ |
b402e91a | 44 | call HIDDEN_JUMPTARGET(__fortify_fail); \ |
e451d22b AS |
45 | nop; \ |
46 | cfi_restore_state | |
98b1e6c8 | 47 | #else |
85736dc7 | 48 | # define CALL_FAIL sub $8, %RSP_LP; \ |
e451d22b AS |
49 | cfi_remember_state; \ |
50 | cfi_def_cfa_offset(16); \ | |
85736dc7 | 51 | mov $longjmp_msg, %RDI_LP; \ |
b402e91a | 52 | call HIDDEN_JUMPTARGET(__fortify_fail); \ |
e451d22b AS |
53 | nop; \ |
54 | cfi_restore_state | |
98b1e6c8 UD |
55 | #endif |
56 | ||
98b1e6c8 UD |
57 | /* Jump to the position specified by ENV, causing the |
58 | setjmp call there to return VAL, or 1 if VAL is 0. | |
59 | void __longjmp (__jmp_buf env, int val). */ | |
60 | .text | |
61 | ENTRY(____longjmp_chk) | |
62 | /* Restore registers. */ | |
85736dc7 | 63 | mov (JB_RSP*8)(%rdi), %R8_LP |
6c7fb145 | 64 | mov (JB_RBP*8)(%rdi),%R9_LP |
85736dc7 | 65 | mov (JB_PC*8)(%rdi), %RDX_LP |
98b1e6c8 | 66 | #ifdef PTR_DEMANGLE |
85736dc7 | 67 | PTR_DEMANGLE (%R8_LP) |
6c7fb145 | 68 | PTR_DEMANGLE (%R9_LP) |
85736dc7 | 69 | PTR_DEMANGLE (%RDX_LP) |
6c7fb145 RM |
70 | # ifdef __ILP32__ |
71 | /* We ignored the high bits of the %rbp value because only the low | |
72 | bits are mangled. But we cannot presume that %rbp is being used | |
73 | as a pointer and truncate it, so recover the high bits. */ | |
74 | movl (JB_RBP*8 + 4)(%rdi), %eax | |
75 | shlq $32, %rax | |
76 | orq %rax, %r9 | |
77 | # endif | |
98b1e6c8 UD |
78 | #endif |
79 | ||
85736dc7 | 80 | cmp %R8_LP, %RSP_LP |
e4143e7a UD |
81 | jbe .Lok |
82 | ||
98b1e6c8 UD |
83 | /* Save function parameters. */ |
84 | movq %rdi, %r10 | |
c044aa75 CLT |
85 | cfi_register (%rdi, %r10) |
86 | movl %esi, %ebx | |
87 | cfi_register (%rsi, %rbx) | |
98b1e6c8 | 88 | |
98b1e6c8 | 89 | xorl %edi, %edi |
85736dc7 | 90 | lea -sizeSS(%rsp), %RSI_LP |
98b1e6c8 UD |
91 | movl $__NR_sigaltstack, %eax |
92 | syscall | |
e4143e7a | 93 | /* Without working sigaltstack we cannot perform the test. */ |
98b1e6c8 | 94 | testl %eax, %eax |
e4143e7a | 95 | jne .Lok2 |
85736dc7 | 96 | testl $1, (-sizeSS + oSS_FLAGS)(%rsp) |
e4143e7a | 97 | jz .Lfail |
98b1e6c8 | 98 | |
85736dc7 L |
99 | mov (-sizeSS + oSS_SP)(%rsp), %RAX_LP |
100 | add (-sizeSS + oSS_SIZE)(%rsp), %RAX_LP | |
101 | sub %R8_LP, %RAX_LP | |
102 | cmp (-sizeSS + oSS_SIZE)(%rsp), %RAX_LP | |
e4143e7a UD |
103 | jae .Lok2 |
104 | ||
105 | .Lfail: CALL_FAIL | |
106 | ||
107 | .Lok2: movq %r10, %rdi | |
c044aa75 CLT |
108 | cfi_restore (%rdi) |
109 | movl %ebx, %esi | |
110 | cfi_restore (%rsi) | |
e4143e7a | 111 | |
8422c9a5 | 112 | .Lok: |
faaee1f0 L |
113 | #ifdef SHADOW_STACK_POINTER_OFFSET |
114 | # if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET | |
115 | /* Check if Shadow Stack is enabled. */ | |
116 | testl $X86_FEATURE_1_SHSTK, %fs:FEATURE_1_OFFSET | |
117 | jz L(skip_ssp) | |
118 | # else | |
119 | xorl %eax, %eax | |
120 | # endif | |
121 | /* Check and adjust the Shadow-Stack-Pointer. */ | |
122 | rdsspq %rax | |
123 | /* And compare it with the saved ssp value. */ | |
124 | subq SHADOW_STACK_POINTER_OFFSET(%rdi), %rax | |
125 | je L(skip_ssp) | |
126 | /* Count the number of frames to adjust and adjust it | |
127 | with incssp instruction. The instruction can adjust | |
128 | the ssp by [0..255] value only thus use a loop if | |
129 | the number of frames is bigger than 255. */ | |
130 | negq %rax | |
131 | shrq $3, %rax | |
132 | /* NB: We saved Shadow-Stack-Pointer of setjmp. Since we are | |
133 | restoring Shadow-Stack-Pointer of setjmp's caller, we | |
134 | need to unwind shadow stack by one more frame. */ | |
135 | addq $1, %rax | |
136 | movl $255, %ebx | |
137 | L(loop): | |
138 | cmpq %rbx, %rax | |
139 | cmovb %rax, %rbx | |
140 | incsspq %rbx | |
141 | subq %rbx, %rax | |
142 | ja L(loop) | |
143 | L(skip_ssp): | |
144 | #endif | |
8422c9a5 RM |
145 | LIBC_PROBE (longjmp, 3, LP_SIZE@%RDI_LP, -4@%esi, LP_SIZE@%RDX_LP) |
146 | /* We add unwind information for the target here. */ | |
e4143e7a | 147 | cfi_def_cfa(%rdi, 0) |
98b1e6c8 UD |
148 | cfi_register(%rsp,%r8) |
149 | cfi_register(%rbp,%r9) | |
150 | cfi_register(%rip,%rdx) | |
151 | cfi_offset(%rbx,JB_RBX*8) | |
152 | cfi_offset(%r12,JB_R12*8) | |
153 | cfi_offset(%r13,JB_R13*8) | |
154 | cfi_offset(%r14,JB_R14*8) | |
155 | cfi_offset(%r15,JB_R15*8) | |
c044aa75 CLT |
156 | movq (JB_RBX*8)(%rdi), %rbx |
157 | movq (JB_R12*8)(%rdi), %r12 | |
158 | movq (JB_R13*8)(%rdi), %r13 | |
159 | movq (JB_R14*8)(%rdi), %r14 | |
160 | movq (JB_R15*8)(%rdi), %r15 | |
98b1e6c8 | 161 | /* Set return value for setjmp. */ |
e4143e7a | 162 | movl %esi, %eax |
85736dc7 | 163 | mov %R8_LP, %RSP_LP |
e4143e7a | 164 | movq %r9,%rbp |
8422c9a5 RM |
165 | LIBC_PROBE (longjmp_target, 3, |
166 | LP_SIZE@%RDI_LP, -4@%eax, LP_SIZE@%RDX_LP) | |
98b1e6c8 | 167 | jmpq *%rdx |
9663bb3e | 168 | END (____longjmp_chk) |