1/* Copyright (C) 2002-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 20#if SHSTK_ENABLED 21# include <asm/prctl.h> 22# include "ucontext_i.h" 23 24/* Use CALL to push __start_context onto the new stack as well as the new 25 shadow stack. RDI points to ucontext: 26 Incoming: 27 __ssp[0]: The original caller's shadow stack pointer. 28 __ssp[1]: The size of the new shadow stack. 29 __ssp[2]: The size of the new shadow stack. 30 Outgoing: 31 __ssp[0]: The new shadow stack pointer. 32 __ssp[1]: The base address of the new shadow stack. 33 __ssp[2]: The size of the new shadow stack. 34 */ 35 36ENTRY(__push___start_context) 37 /* Save the pointer to ucontext. */ 38 movq %rdi, %r9 39 /* Get the original shadow stack pointer. */ 40 rdsspq %r8 41 /* Save the original stack pointer. */ 42 movq %rsp, %rdx 43 /* Load the top of the new stack into RSI. */ 44 movq oRSP(%rdi), %rsi 45 /* Add 8 bytes to RSI since CALL will push the 8-byte return 46 address onto stack. */ 47 leaq 8(%rsi), %rsp 48 /* Allocate the new shadow stack. The size of the new shadow 49 stack is passed in __ssp[1]. */ 50 lea (oSSP + 8)(%rdi), %RSI_LP 51 movl $ARCH_CET_ALLOC_SHSTK, %edi 52 movl $__NR_arch_prctl, %eax 53 /* The new shadow stack base is returned in __ssp[1]. */ 54 syscall 55 testq %rax, %rax 56 jne L(hlt) /* This should never happen. */ 57 58 /* Get the size of the new shadow stack. */ 59 movq 8(%rsi), %rdi 60 61 /* Get the base address of the new shadow stack. */ 62 movq (%rsi), %rsi 63 64 /* Use the restore stoken to restore the new shadow stack. */ 65 rstorssp -8(%rsi, %rdi) 66 67 /* Save the restore token on the original shadow stack. */ 68 saveprevssp 69 70 /* Push the address of "jmp __start_context" onto the new stack 71 as well as the new shadow stack. */ 72 call 1f 73 jmp __start_context 741: 75 76 /* Get the new shadow stack pointer. */ 77 rdsspq %rdi 78 79 /* Use the restore stoken to restore the original shadow stack. */ 80 rstorssp -8(%r8) 81 82 /* Save the restore token on the new shadow stack. */ 83 saveprevssp 84 85 /* Store the new shadow stack pointer in __ssp[0]. */ 86 movq %rdi, oSSP(%r9) 87 88 /* Restore the original stack. */ 89 mov %rdx, %rsp 90 ret 91END(__push___start_context) 92#endif 93 94/* This is the helper code which gets called if a function which is 95 registered with 'makecontext' returns. In this case we have to 96 install the context listed in the uc_link element of the context 97 'makecontext' manipulated at the time of the 'makecontext' call. 98 If the pointer is NULL the process must terminate. */ 99 100 101ENTRY(__start_context) 102 /* This removes the parameters passed to the function given to 103 'makecontext' from the stack. RBX contains the address 104 on the stack pointer for the next context. */ 105 movq %rbx, %rsp 106 107 /* Don't use pop here so that stack is aligned to 16 bytes. */ 108 movq (%rsp), %rdi /* This is the next context. */ 109 testq %rdi, %rdi 110 je 2f /* If it is zero exit. */ 111 112 call __setcontext 113 /* If this returns (which can happen if the syscall fails) we'll 114 exit the program with the return error value (-1). */ 115 movq %rax,%rdi 116 1172: 118 call HIDDEN_JUMPTARGET(exit) 119 /* The 'exit' call should never return. In case it does cause 120 the process to terminate. */ 121L(hlt): 122 hlt 123END(__start_context) 124