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 <asm-syntax.h> 21#include <stap-probe.h> 22#include <sigaltstack-offsets.h> 23#include <jmp_buf-ssp.h> 24 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 30 .section .rodata.str1.1,"aMS",@progbits,1 31 .type longjmp_msg,@object 32longjmp_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 40# define CALL_FAIL sub $8, %RSP_LP; \ 41 cfi_remember_state; \ 42 cfi_def_cfa_offset(16); \ 43 lea longjmp_msg(%rip), %RDI_LP; \ 44 call HIDDEN_JUMPTARGET(__fortify_fail); \ 45 nop; \ 46 cfi_restore_state 47#else 48# define CALL_FAIL sub $8, %RSP_LP; \ 49 cfi_remember_state; \ 50 cfi_def_cfa_offset(16); \ 51 mov $longjmp_msg, %RDI_LP; \ 52 call HIDDEN_JUMPTARGET(__fortify_fail); \ 53 nop; \ 54 cfi_restore_state 55#endif 56 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 61ENTRY(____longjmp_chk) 62 /* Restore registers. */ 63 mov (JB_RSP*8)(%rdi), %R8_LP 64 mov (JB_RBP*8)(%rdi),%R9_LP 65 mov (JB_PC*8)(%rdi), %RDX_LP 66#ifdef PTR_DEMANGLE 67 PTR_DEMANGLE (%R8_LP) 68 PTR_DEMANGLE (%R9_LP) 69 PTR_DEMANGLE (%RDX_LP) 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 78#endif 79 80 cmp %R8_LP, %RSP_LP 81 jbe .Lok 82 83 /* Save function parameters. */ 84 movq %rdi, %r10 85 cfi_register (%rdi, %r10) 86 movl %esi, %ebx 87 cfi_register (%rsi, %rbx) 88 89 xorl %edi, %edi 90 lea -sizeSS(%rsp), %RSI_LP 91 movl $__NR_sigaltstack, %eax 92 syscall 93 /* Without working sigaltstack we cannot perform the test. */ 94 testl %eax, %eax 95 jne .Lok2 96 testl $1, (-sizeSS + oSS_FLAGS)(%rsp) 97 jz .Lfail 98 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 103 jae .Lok2 104 105.Lfail: CALL_FAIL 106 107.Lok2: movq %r10, %rdi 108 cfi_restore (%rdi) 109 movl %ebx, %esi 110 cfi_restore (%rsi) 111 112.Lok: 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 137L(loop): 138 cmpq %rbx, %rax 139 cmovb %rax, %rbx 140 incsspq %rbx 141 subq %rbx, %rax 142 ja L(loop) 143L(skip_ssp): 144#endif 145 LIBC_PROBE (longjmp, 3, LP_SIZE@%RDI_LP, -4@%esi, LP_SIZE@%RDX_LP) 146 /* We add unwind information for the target here. */ 147 cfi_def_cfa(%rdi, 0) 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) 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 161 /* Set return value for setjmp. */ 162 movl %esi, %eax 163 mov %R8_LP, %RSP_LP 164 movq %r9,%rbp 165 LIBC_PROBE (longjmp_target, 3, 166 LP_SIZE@%RDI_LP, -4@%eax, LP_SIZE@%RDX_LP) 167 jmpq *%rdx 168END (____longjmp_chk) 169