1/* Create new 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(__makecontext) 26 movl 4(%esp), %eax 27 28 /* Load the address of the function we are supposed to run. */ 29 movl 8(%esp), %ecx 30 31 /* Compute the address of the stack. The information comes from 32 to us_stack element. */ 33 movl oSS_SP(%eax), %edx 34 movl %ecx, oEIP(%eax) 35 addl oSS_SIZE(%eax), %edx 36 37 /* Remember the number of parameters for the exit handler since 38 it has to remove them. We store the number in the EBX register 39 which the function we will call must preserve. */ 40 movl 12(%esp), %ecx 41 movl %ecx, oEBX(%eax) 42 43 /* Make room on the new stack for the parameters. 44 Room for the arguments, return address (== L(exitcode)) and 45 oLINK pointer is needed. One of the pointer sizes is subtracted 46 after aligning the stack. */ 47 negl %ecx 48 leal -4(%edx,%ecx,4), %edx 49 negl %ecx 50 51 /* Align the stack. */ 52 andl $0xfffffff0, %edx 53 subl $4, %edx 54 55 /* Store the future stack pointer. */ 56 movl %edx, oESP(%eax) 57 58 /* Put the next context on the new stack (from the uc_link 59 element). */ 60 movl oLINK(%eax), %eax 61 movl %eax, 4(%edx,%ecx,4) 62 63 /* Copy all the parameters. */ 64 jecxz 2f 651: movl 12(%esp,%ecx,4), %eax 66 movl %eax, (%edx,%ecx,4) 67 decl %ecx 68 jnz 1b 692: 70 71#if SHSTK_ENABLED 72 /* Check if Shadow Stack is enabled. */ 73 testl $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET 74 jz L(skip_ssp) 75 76 /* Reload the pointer to ucontext. */ 77 movl 4(%esp), %eax 78 79 /* Shadow stack is enabled. We need to allocate a new shadow 80 stack. */ 81 subl oSS_SP(%eax), %edx 82 shrl $STACK_SIZE_TO_SHADOW_STACK_SIZE_SHIFT, %edx 83 84 /* Align shadow stack size to 8 bytes. */ 85 addl $7, %edx 86 andl $-8, %edx 87 88 /* Store shadow stack size in __ssp[2]. */ 89 movl %edx, (oSSP + 8)(%eax) 90 91 /* Save ESI in the second scratch register slot. */ 92 movl %esi, oSCRATCH2(%eax) 93 /* Save EDI in the third scratch register slot. */ 94 movl %edi, oSCRATCH3(%eax) 95 96 /* Save the pointer to ucontext. */ 97 movl %eax, %edi 98 99 /* Get the original shadow stack pointer. */ 100 rdsspd %esi 101 102 /* Align the saved original shadow stack pointer to the next 103 8 byte aligned boundary. */ 104 andl $-8, %esi 105 106 /* Load the top of the new stack into EDX. */ 107 movl oESP(%eax), %edx 108 109 /* We need to terminate the FDE here because the unwinder looks 110 at ra-1 for unwind information. */ 111 cfi_endproc 112 113 /* Swap the original stack pointer with the top of the new 114 stack. */ 115 xchgl %esp, %edx 116 117 /* Add 4 bytes since CALL will push the 4-byte return address 118 onto stack. */ 119 addl $4, %esp 120 121 /* Allocate the new shadow stack. Save EBX in the first scratch 122 register slot. */ 123 movl %ebx, oSCRATCH1(%eax) 124 125 /* CET syscall takes 64-bit sizes. */ 126 subl $16, %esp 127 movl (oSSP + 8)(%eax), %ecx 128 movl %ecx, (%esp) 129 movl $0, 4(%esp) 130 movl %ecx, 8(%esp) 131 movl $0, 12(%esp) 132 movl %esp, %ecx 133 134 movl $ARCH_CET_ALLOC_SHSTK, %ebx 135 movl $__NR_arch_prctl, %eax 136 ENTER_KERNEL 137 testl %eax, %eax 138 jne L(hlt) /* This should never happen. */ 139 140 /* Copy the base address of the new shadow stack to __ssp[1]. */ 141 movl (%esp), %eax 142 movl %eax, (oSSP + 4)(%edi) 143 144 addl $16, %esp 145 146 /* Restore EBX from the first scratch register slot. */ 147 movl oSCRATCH1(%edi), %ebx 148 149 /* Get the size of the new shadow stack. */ 150 movl (oSSP + 8)(%edi), %ecx 151 152 /* Use the restore stoken to restore the new shadow stack. */ 153 rstorssp -8(%eax, %ecx) 154 155 /* Save the restore token at the next 8 byte aligned boundary 156 on the original shadow stack. */ 157 saveprevssp 158 159 /* Push the address of "jmp exitcode" onto the new stack as 160 well as the new shadow stack. */ 161 call 1f 162 jmp L(exitcode) 1631: 164 165 /* Get the new shadow stack pointer. */ 166 rdsspd %eax 167 168 /* Use the restore stoken to restore the original shadow stack. */ 169 rstorssp -8(%esi) 170 171 /* Save the restore token on the new shadow stack. */ 172 saveprevssp 173 174 /* Store the new shadow stack pointer in __ssp[0]. */ 175 movl %eax, oSSP(%edi) 176 177 /* Restore the original stack. */ 178 mov %edx, %esp 179 180 cfi_startproc 181 182 /* Restore ESI from the second scratch register slot. */ 183 movl oSCRATCH2(%edi), %esi 184 /* Restore EDI from the third scratch register slot. */ 185 movl oSCRATCH3(%edi), %edi 186 187 ret 188 189L(skip_ssp): 190#endif 191 192 /* If the function we call returns we must continue with the 193 context which is given in the uc_link element. To do this 194 set the return address for the function the user provides 195 to a little bit of helper code which does the magic (see 196 below). */ 197#ifdef PIC 198 call 1f 199 cfi_adjust_cfa_offset (4) 2001: popl %ecx 201 cfi_adjust_cfa_offset (-4) 202 addl $L(exitcode)-1b, %ecx 203 movl %ecx, (%edx) 204#else 205 movl $L(exitcode), (%edx) 206#endif 207 /* We need to terminate the FDE here instead of after ret because 208 the unwinder looks at ra-1 for unwind information. */ 209 cfi_endproc 210 211 /* 'makecontext' returns no value. */ 212 ret 213 214 /* This is the helper code which gets called if a function which 215 is registered with 'makecontext' returns. In this case we 216 have to install the context listed in the uc_link element of 217 the context 'makecontext' manipulated at the time of the 218 'makecontext' call. If the pointer is NULL the process must 219 terminate. */ 220L(exitcode): 221 /* This removes the parameters passed to the function given to 222 'makecontext' from the stack. EBX contains the number of 223 parameters (see above). */ 224 leal (%esp,%ebx,4), %esp 225 226 cmpl $0, (%esp) /* Check the next context. */ 227 je 2f /* If it is zero exit. */ 228 229 call HIDDEN_JUMPTARGET(__setcontext) 230 /* If this returns (which can happen if the syscall fails) we'll 231 exit the program with the return error value (-1). */ 232 jmp L(call_exit) 233 2342: 235 /* Exit with status 0. */ 236 xorl %eax, %eax 237 238L(call_exit): 239 /* Align the stack and pass the exit code (from %eax). */ 240 andl $0xfffffff0, %esp 241 subl $12, %esp 242 pushl %eax 243 244 call HIDDEN_JUMPTARGET(exit) 245 /* The 'exit' call should never return. In case it does cause 246 the process to terminate. */ 247L(hlt): 248 hlt 249 cfi_startproc 250END(__makecontext) 251 252weak_alias (__makecontext, makecontext) 253