1/* Save current context. 2 Copyright (C) 2001-2022 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 The GNU C Library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; if not, see 17 <https://www.gnu.org/licenses/>. */ 18 19#include <sysdep.h> 20#include <asm/prctl.h> 21 22#include "ucontext_i.h" 23 24 25ENTRY(__getcontext) 26 /* Load address of the context data structure. */ 27 movl 4(%esp), %eax 28 29 /* Save the preserved register values and the return address. */ 30 movl %edi, oEDI(%eax) 31 movl %esi, oESI(%eax) 32 movl %ebp, oEBP(%eax) 33 movl (%esp), %ecx 34 movl %ecx, oEIP(%eax) 35 leal 4(%esp), %ecx /* Exclude the return address. */ 36 movl %ecx, oESP(%eax) 37 movl %ebx, oEBX(%eax) 38 39 /* Save the FS segment register. We don't touch the GS register 40 since it is used for threads. */ 41 xorl %edx, %edx 42 movw %fs, %dx 43 movl %edx, oFS(%eax) 44 45#if SHSTK_ENABLED 46 /* Check if shadow stack is enabled. */ 47 testl $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET 48 jz L(no_shstk) 49 50 /* Save EAX in EDX. */ 51 movl %eax, %edx 52 53 xorl %eax, %eax 54 cmpl %gs:SSP_BASE_OFFSET, %eax 55 jnz L(shadow_stack_bound_recorded) 56 57 /* Save EBX in the first scratch register slot. */ 58 movl %ebx, oSCRATCH1(%edx) 59 60 /* Get the base address and size of the default shadow stack 61 which must be the current shadow stack since nothing has 62 been recorded yet. */ 63 sub $24, %esp 64 mov %esp, %ecx 65 movl $ARCH_CET_STATUS, %ebx 66 movl $__NR_arch_prctl, %eax 67 ENTER_KERNEL 68 testl %eax, %eax 69 jz L(continue_no_err) 70 71 /* This should never happen. */ 72 hlt 73 74L(continue_no_err): 75 /* Restore EBX from the first scratch register slot. */ 76 movl oSCRATCH1(%edx), %ebx 77 78 /* Record the base of the current shadow stack. */ 79 movl 8(%esp), %eax 80 movl %eax, %gs:SSP_BASE_OFFSET 81 add $24, %esp 82 83L(shadow_stack_bound_recorded): 84 /* Load address of the context data structure. */ 85 movl 4(%esp), %eax 86 87 /* Get the current shadow stack pointer. */ 88 rdsspd %edx 89 /* NB: Save the caller's shadow stack so that we can jump back 90 to the caller directly. */ 91 addl $4, %edx 92 movl %edx, oSSP(%eax) 93 94 /* Save the current shadow stack base in ucontext. */ 95 movl %gs:SSP_BASE_OFFSET, %edx 96 movl %edx, (oSSP + 4)(%eax) 97 98L(no_shstk): 99#endif 100 /* We have separate floating-point register content memory on the 101 stack. We use the __fpregs_mem block in the context. Set the 102 links up correctly. */ 103 leal oFPREGSMEM(%eax), %ecx 104 movl %ecx, oFPREGS(%eax) 105 /* Save the floating-point context. */ 106 fnstenv (%ecx) 107 /* And load it right back since the processor changes the mask. 108 Intel thought this opcode to be used in interrupt handlers which 109 would block all exceptions. */ 110 fldenv (%ecx) 111 112 /* Save the current signal mask. */ 113 pushl %ebx 114 cfi_adjust_cfa_offset (4) 115 cfi_rel_offset (ebx, 0) 116 leal oSIGMASK(%eax), %edx 117 xorl %ecx, %ecx 118 movl $SIG_BLOCK, %ebx 119 movl $__NR_sigprocmask, %eax 120 ENTER_KERNEL 121 popl %ebx 122 cfi_adjust_cfa_offset (-4) 123 cfi_restore (ebx) 124 cmpl $-4095, %eax /* Check %eax for error. */ 125 jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */ 126 127 /* All done, return 0 for success. */ 128 xorl %eax, %eax 129 ret 130PSEUDO_END(__getcontext) 131 132weak_alias (__getcontext, getcontext) 133