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 <jmp_buf-ssp.h> 21#include <asm-syntax.h> 22#include <stap-probe.h> 23 24/* Don't restore shadow stack register if shadow stack isn't enabled. */ 25#if !SHSTK_ENABLED 26# undef SHADOW_STACK_POINTER_OFFSET 27#endif 28 29 .section .rodata.str1.1,"aMS",@progbits,1 30 .type longjmp_msg,@object 31longjmp_msg: 32 .string "longjmp causes uninitialized stack frame" 33 .size longjmp_msg, .-longjmp_msg 34 35 36#ifdef PIC 37# define CALL_FAIL movl %ebx, %ecx; \ 38 cfi_register(%ebx,%ecx); \ 39 LOAD_PIC_REG (bx); \ 40 leal longjmp_msg@GOTOFF(%ebx), %eax; \ 41 movl %eax, (%esp); \ 42 call HIDDEN_JUMPTARGET(__fortify_fail) 43#else 44# define CALL_FAIL movl $longjmp_msg, %eax; \ 45 movl %eax, (%esp); \ 46 call HIDDEN_JUMPTARGET(__fortify_fail) 47#endif 48 49 50 .text 51ENTRY (____longjmp_chk) 52 movl 4(%esp), %ecx /* User's jmp_buf in %ecx. */ 53 54#ifdef SHADOW_STACK_POINTER_OFFSET 55# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET 56 /* Check if Shadow Stack is enabled. */ 57 testl $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET 58 jz L(skip_ssp) 59# else 60 xorl %edx, %edx 61# endif 62 /* Check and adjust the Shadow-Stack-Pointer. */ 63 rdsspd %edx 64 /* And compare it with the saved ssp value. */ 65 subl SHADOW_STACK_POINTER_OFFSET(%ecx), %edx 66 je L(skip_ssp) 67 /* Count the number of frames to adjust and adjust it 68 with incssp instruction. The instruction can adjust 69 the ssp by [0..255] value only thus use a loop if 70 the number of frames is bigger than 255. */ 71 negl %edx 72 shrl $2, %edx 73 /* NB: We saved Shadow-Stack-Pointer of setjmp. Since we are 74 restoring Shadow-Stack-Pointer of setjmp's caller, we 75 need to unwind shadow stack by one more frame. */ 76 addl $1, %edx 77 movl $255, %ebx 78L(loop): 79 cmpl %ebx, %edx 80 cmovb %edx, %ebx 81 incsspd %ebx 82 subl %ebx, %edx 83 ja L(loop) 84L(skip_ssp): 85#endif 86 /* Save the return address now. */ 87 movl (JB_PC*4)(%ecx), %edx 88 /* Get the stack pointer. */ 89 movl (JB_SP*4)(%ecx), %edi 90 cfi_undefined(%edi) 91 PTR_DEMANGLE (%edx) 92 PTR_DEMANGLE (%edi) 93 94 cmpl %edi, %esp 95 jbe .Lok 96 97 subl $12, %esp 98 cfi_adjust_cfa_offset(12) 99 xorl %ebx, %ebx 100 movl %esp, %ecx 101 movl $__NR_sigaltstack, %eax 102 ENTER_KERNEL 103 /* Without working sigaltstack we cannot perform the test. */ 104 test %eax, %eax 105 jne .Lok2 106 testl $1, 4(%esp) 107 jz .Lfail 108 109 movl (%esp), %eax 110 addl 8(%esp), %eax 111 subl %edi, %eax 112 cmpl 8(%esp), %eax 113 jae .Lok2 114 115.Lfail: CALL_FAIL 116 117.Lok2: addl $12, %esp 118 cfi_adjust_cfa_offset(-12) 119 movl 4(%esp), %ecx 120 121.Lok: 122 LIBC_PROBE (longjmp, 3, 4@%ecx, -4@8(%esp), 4@%edx) 123 /* We add unwind information for the target here. */ 124 cfi_def_cfa(%ecx, 0) 125 cfi_register(%eip, %edx) 126 cfi_register(%esp, %edi) 127 cfi_offset(%ebx, JB_BX*4) 128 cfi_offset(%esi, JB_SI*4) 129 cfi_offset(%edi, JB_DI*4) 130 cfi_offset(%ebp, JB_BP*4) 131 132 movl 8(%esp), %eax /* Second argument is return value. */ 133 movl %edi, %esp 134 135 /* Restore registers. */ 136 movl (JB_BX*4)(%ecx), %ebx 137 movl (JB_SI*4)(%ecx), %esi 138 movl (JB_DI*4)(%ecx), %edi 139 movl (JB_BP*4)(%ecx), %ebp 140 cfi_restore(%ebx) 141 cfi_restore(%esi) 142 cfi_restore(%edi) 143 cfi_restore(%ebp) 144 145 /* Jump to saved PC. */ 146 LIBC_PROBE (longjmp_target, 3, 4@%ecx, -4@%eax, 4@%edx) 147 jmp *%edx 148END (____longjmp_chk) 149