github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/sentry/platform/systrap/stub_arm64.s (about) 1 // Copyright 2019 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "funcdata.h" 16 #include "textflag.h" 17 18 #define SYS_GETPID 172 // +checkconst unix SYS_GETPID 19 #define SYS_EXIT 93 // +checkconst unix SYS_EXIT 20 #define SYS_KILL 129 // +checkconst unix SYS_KILL 21 #define SYS_GETPPID 173 // +checkconst unix SYS_GETPPID 22 #define SIGKILL 9 // +checkconst unix SIGKILL 23 #define SIGSTOP 19 // +checkconst unix SIGSTOP 24 #define SYS_PRCTL 167 // +checkconst unix SYS_PRCTL 25 #define PR_SET_PDEATHSIG 1 // +checkconst unix PR_SET_PDEATHSIG 26 27 #define SYS_FUTEX 98 // +checkconst unix SYS_FUTEX 28 #define FUTEX_WAKE 1 // +checkconst linux FUTEX_WAKE 29 #define FUTEX_WAIT 0 // +checkconst linux FUTEX_WAIT 30 31 #define NEW_STUB 1 // +checkconst . _NEW_STUB 32 #define RUN_SYSCALL_LOOP 5 // +checkconst . _RUN_SYSCALL_LOOP 33 34 // syscallSentryMessage offsets. 35 #define SENTRY_MESSAGE_STATE 0 // +checkoffset . syscallSentryMessage.state 36 #define SENTRY_MESSAGE_SYSNO 8 // +checkoffset . syscallSentryMessage.sysno 37 #define SENTRY_MESSAGE_ARGS 16 // +checkoffset . syscallSentryMessage.args 38 #define SENTRY_MESSAGE_ARG0 (SENTRY_MESSAGE_ARGS + 0*8) 39 #define SENTRY_MESSAGE_ARG1 (SENTRY_MESSAGE_ARGS + 1*8) 40 #define SENTRY_MESSAGE_ARG2 (SENTRY_MESSAGE_ARGS + 2*8) 41 #define SENTRY_MESSAGE_ARG3 (SENTRY_MESSAGE_ARGS + 3*8) 42 #define SENTRY_MESSAGE_ARG4 (SENTRY_MESSAGE_ARGS + 4*8) 43 #define SENTRY_MESSAGE_ARG5 (SENTRY_MESSAGE_ARGS + 5*8) 44 45 // syscallStubMessage offsets. 46 #define STUB_MESSAGE_OFFSET 4096 // +checkconst . syscallStubMessageOffset 47 #define STUB_MESSAGE_RET 0 // +checkoffset . syscallStubMessage.ret 48 49 // initStubProcess bootstraps the child and sends itself SIGSTOP to wait for attach. 50 // 51 // R7 contains the expected PPID. 52 // 53 // This should not be used outside the context of a new ptrace child (as the 54 // function is otherwise a bunch of nonsense). 55 TEXT ·initStubProcess(SB),NOSPLIT,$0 56 begin: 57 // N.B. This loop only executes in the context of a single-threaded 58 // fork child. 59 60 MOVD $SYS_PRCTL, R8 61 MOVD $PR_SET_PDEATHSIG, R0 62 MOVD $SIGKILL, R1 63 SVC 64 65 CMN $4095, R0 66 BCS error 67 68 // If the parent already died before we called PR_SET_DEATHSIG then 69 // we'll have an unexpected PPID. 70 MOVD $SYS_GETPPID, R8 71 SVC 72 73 CMP R0, R7 74 BNE parent_dead 75 76 MOVD $SYS_GETPID, R8 77 SVC 78 79 CMP $0x0, R0 80 BLT error 81 82 MOVD $0, R9 83 84 // SIGSTOP to wait for attach. 85 // 86 // The SYSCALL instruction will be used for future syscall injection by 87 // thread.syscall. 88 MOVD $SYS_KILL, R8 89 MOVD $SIGSTOP, R1 90 SVC 91 92 // The sentry sets R9 to $NEW_STUB when creating stub process. 93 CMP $NEW_STUB, R9 94 BEQ clone 95 96 // The sentry sets R9 to $RUN_SYSCALL_LOOP when creating a new syscall 97 // thread. 98 CMP $RUN_SYSCALL_LOOP, R9 99 BEQ syscall_loop 100 101 done: 102 // Notify the Sentry that syscall exited. 103 BRK $3 104 B done // Be paranoid. 105 clone: 106 // subprocess.createStub clones a new stub process that is untraced, 107 // thus executing this code. We setup the PDEATHSIG before SIGSTOPing 108 // ourselves for attach by the tracer. 109 // 110 // R7 has been updated with the expected PPID. 111 CMP $0, R0 112 BEQ begin 113 114 // The clone system call returned a non-zero value. 115 B done 116 117 error: 118 // Exit with -errno. 119 NEG R0, R0 120 MOVD $SYS_EXIT, R8 121 SVC 122 HLT 123 124 parent_dead: 125 MOVD $SYS_EXIT, R8 126 MOVD $1, R0 127 SVC 128 HLT 129 130 // syscall_loop handles requests from the Sentry to execute syscalls. 131 // Look at syscall_thread for more details. 132 // 133 // syscall_loop is running without using the stack because it can be 134 // compromised by sysmsg (guest) threads that run in the same address 135 // space. 136 syscall_loop: 137 // while (sentryMessage->state != R13) { 138 // futex(sentryMessage->state, FUTEX_WAIT, 0, NULL, NULL, 0); 139 // } 140 MOVD R12, R0 141 MOVD $FUTEX_WAIT, R1 142 MOVD $0, R3 143 MOVD $0, R4 144 MOVD $0, R5 145 wait_for_syscall: 146 // Move the sentry message state to R2. 147 MOVW SENTRY_MESSAGE_STATE(R12), R2 148 CMPW R2, R13 149 BEQ execute_syscall 150 151 MOVD $SYS_FUTEX, R8 152 SVC 153 JMP wait_for_syscall 154 155 execute_syscall: 156 MOVD SENTRY_MESSAGE_SYSNO(R12), R8 157 MOVD SENTRY_MESSAGE_ARG0(R12), R0 158 MOVD SENTRY_MESSAGE_ARG1(R12), R1 159 MOVD SENTRY_MESSAGE_ARG2(R12), R2 160 MOVD SENTRY_MESSAGE_ARG3(R12), R3 161 MOVD SENTRY_MESSAGE_ARG4(R12), R4 162 MOVD SENTRY_MESSAGE_ARG5(R12), R5 163 SVC 164 165 // stubMessage->ret = ret 166 MOVD R0, (STUB_MESSAGE_OFFSET + STUB_MESSAGE_RET)(R12) 167 168 // for { 169 // if futex(sentryMessage->state, FUTEX_WAKE, 1) == 1 { 170 // break; 171 // } 172 // } 173 MOVD $FUTEX_WAKE, R1 174 MOVD $1, R2 175 MOVD $0, R3 176 MOVD $0, R4 177 MOVD $0, R5 178 MOVD $SYS_FUTEX, R8 179 wake_up_sentry: 180 MOVD R12, R0 181 SVC 182 183 // futex returns the number of waiters that were woken up. If futex 184 // returns 0 here, it means that the Sentry has not called futex_wait 185 // yet and we need to try again. The value of sentryMessage->state 186 // isn't changed, so futex_wake is the only way to wake up the Sentry. 187 CMP $1, R0 188 BNE wake_up_sentry 189 190 ADDW $1, R13, R13 191 JMP syscall_loop 192 193 // func addrOfInitStubProcess() uintptr 194 TEXT ·addrOfInitStubProcess(SB), $0-8 195 MOVD $·initStubProcess(SB), R0 196 MOVD R0, ret+0(FP) 197 RET 198 199 // stubCall calls the stub function at the given address with the given PPID. 200 // 201 // This is a distinct function because stub, above, may be mapped at any 202 // arbitrary location, and stub has a specific binary API (see above). 203 TEXT ·stubCall(SB),NOSPLIT,$0-16 204 MOVD addr+0(FP), R0 205 MOVD pid+8(FP), R7 206 B (R0)