gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/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 SYS_EXIT_GROUP 94 // +checkconst unix SYS_EXIT_GROUP 26 #define PR_SET_PDEATHSIG 1 // +checkconst unix PR_SET_PDEATHSIG 27 28 #define SYS_FUTEX 98 // +checkconst unix SYS_FUTEX 29 #define FUTEX_WAKE 1 // +checkconst linux FUTEX_WAKE 30 #define FUTEX_WAIT 0 // +checkconst linux FUTEX_WAIT 31 32 #define NEW_STUB 1 // +checkconst . _NEW_STUB 33 #define RUN_SYSCALL_LOOP 5 // +checkconst . _RUN_SYSCALL_LOOP 34 #define RUN_SECCOMP_LOOP 6 // +checkconst . _RUN_SECCOMP_LOOP 35 36 // syscallSentryMessage offsets. 37 #define SENTRY_MESSAGE_STATE 0 // +checkoffset . syscallSentryMessage.state 38 #define SENTRY_MESSAGE_SYSNO 8 // +checkoffset . syscallSentryMessage.sysno 39 #define SENTRY_MESSAGE_ARGS 16 // +checkoffset . syscallSentryMessage.args 40 #define SENTRY_MESSAGE_ARG0 (SENTRY_MESSAGE_ARGS + 0*8) 41 #define SENTRY_MESSAGE_ARG1 (SENTRY_MESSAGE_ARGS + 1*8) 42 #define SENTRY_MESSAGE_ARG2 (SENTRY_MESSAGE_ARGS + 2*8) 43 #define SENTRY_MESSAGE_ARG3 (SENTRY_MESSAGE_ARGS + 3*8) 44 #define SENTRY_MESSAGE_ARG4 (SENTRY_MESSAGE_ARGS + 4*8) 45 #define SENTRY_MESSAGE_ARG5 (SENTRY_MESSAGE_ARGS + 5*8) 46 47 // syscallStubMessage offsets. 48 #define STUB_MESSAGE_OFFSET 4096 // +checkconst . syscallStubMessageOffset 49 #define STUB_MESSAGE_RET 0 // +checkoffset . syscallStubMessage.ret 50 51 // initStubProcess bootstraps the child and sends itself SIGSTOP to wait for attach. 52 // 53 // R7 contains the expected PPID. 54 // 55 // This should not be used outside the context of a new ptrace child (as the 56 // function is otherwise a bunch of nonsense). 57 TEXT ·initStubProcess(SB),NOSPLIT,$0 58 begin: 59 // N.B. This loop only executes in the context of a single-threaded 60 // fork child. 61 62 MOVD $SYS_PRCTL, R8 63 MOVD $PR_SET_PDEATHSIG, R0 64 MOVD $SIGKILL, R1 65 SVC 66 67 CMN $4095, R0 68 BCS error 69 70 // If the parent already died before we called PR_SET_DEATHSIG then 71 // we'll have an unexpected PPID. 72 MOVD $SYS_GETPPID, R8 73 SVC 74 75 CMP R0, R7 76 BNE parent_dead 77 78 MOVD $SYS_GETPID, R8 79 SVC 80 81 CMP $0x0, R0 82 BLT error 83 84 MOVD $0, R9 85 86 // SIGSTOP to wait for attach. 87 // 88 // The SYSCALL instruction will be used for future syscall injection by 89 // thread.syscall. 90 MOVD $SYS_KILL, R8 91 MOVD $SIGSTOP, R1 92 SVC 93 94 // The sentry sets R9 to $NEW_STUB when creating stub process. 95 CMP $NEW_STUB, R9 96 BEQ clone 97 98 // The sentry sets R9 to $RUN_SYSCALL_LOOP when creating a new syscall 99 // thread. 100 CMP $RUN_SYSCALL_LOOP, R9 101 BEQ syscall_loop 102 103 CMP $RUN_SECCOMP_LOOP, R9 104 BEQ seccomp_loop 105 done: 106 // Notify the Sentry that syscall exited. 107 BRK $3 108 B done // Be paranoid. 109 clone: 110 // subprocess.createStub clones a new stub process that is untraced, 111 // thus executing this code. We setup the PDEATHSIG before SIGSTOPing 112 // ourselves for attach by the tracer. 113 // 114 // R7 has been updated with the expected PPID. 115 CMP $0, R0 116 BEQ begin 117 118 // The clone system call returned a non-zero value. 119 B done 120 121 error: 122 // Exit with -errno. 123 NEG R0, R0 124 MOVD $SYS_EXIT, R8 125 SVC 126 HLT 127 128 parent_dead: 129 MOVD $SYS_EXIT, R8 130 MOVD $1, R0 131 SVC 132 HLT 133 134 // syscall_loop handles requests from the Sentry to execute syscalls. 135 // Look at syscall_thread for more details. 136 // 137 // syscall_loop is running without using the stack because it can be 138 // compromised by sysmsg (guest) threads that run in the same address 139 // space. 140 syscall_loop: 141 // while (sentryMessage->state != R13) { 142 // futex(sentryMessage->state, FUTEX_WAIT, 0, NULL, NULL, 0); 143 // } 144 MOVD R12, R0 145 MOVD $FUTEX_WAIT, R1 146 MOVD $0, R3 147 MOVD $0, R4 148 MOVD $0, R5 149 wait_for_syscall: 150 // Move the sentry message state to R2. 151 MOVW SENTRY_MESSAGE_STATE(R12), R2 152 CMPW R2, R13 153 BEQ execute_syscall 154 155 MOVD $SYS_FUTEX, R8 156 SVC 157 JMP wait_for_syscall 158 159 execute_syscall: 160 MOVD SENTRY_MESSAGE_SYSNO(R12), R8 161 MOVD SENTRY_MESSAGE_ARG0(R12), R0 162 MOVD SENTRY_MESSAGE_ARG1(R12), R1 163 MOVD SENTRY_MESSAGE_ARG2(R12), R2 164 MOVD SENTRY_MESSAGE_ARG3(R12), R3 165 MOVD SENTRY_MESSAGE_ARG4(R12), R4 166 MOVD SENTRY_MESSAGE_ARG5(R12), R5 167 SVC 168 169 // stubMessage->ret = ret 170 MOVD R0, (STUB_MESSAGE_OFFSET + STUB_MESSAGE_RET)(R12) 171 172 // for { 173 // if futex(sentryMessage->state, FUTEX_WAKE, 1) == 1 { 174 // break; 175 // } 176 // } 177 MOVD $FUTEX_WAKE, R1 178 MOVD $1, R2 179 MOVD $0, R3 180 MOVD $0, R4 181 MOVD $0, R5 182 MOVD $SYS_FUTEX, R8 183 wake_up_sentry: 184 MOVD R12, R0 185 SVC 186 187 // futex returns the number of waiters that were woken up. If futex 188 // returns 0 here, it means that the Sentry has not called futex_wait 189 // yet and we need to try again. The value of sentryMessage->state 190 // isn't changed, so futex_wake is the only way to wake up the Sentry. 191 CMP $1, R0 192 BNE wake_up_sentry 193 194 ADDW $1, R13, R13 195 JMP syscall_loop 196 seccomp_loop: 197 // SYS_EXIT_GROUP triggers seccomp notifications. 198 MOVD $SYS_EXIT_GROUP, R8 199 SVC 200 201 MOVD SENTRY_MESSAGE_SYSNO(R12), R8 202 MOVD SENTRY_MESSAGE_ARG0(R12), R0 203 MOVD SENTRY_MESSAGE_ARG1(R12), R1 204 MOVD SENTRY_MESSAGE_ARG2(R12), R2 205 MOVD SENTRY_MESSAGE_ARG3(R12), R3 206 MOVD SENTRY_MESSAGE_ARG4(R12), R4 207 MOVD SENTRY_MESSAGE_ARG5(R12), R5 208 SVC 209 210 // stubMessage->ret = ret 211 MOVD R0, (STUB_MESSAGE_OFFSET + STUB_MESSAGE_RET)(R12) 212 JMP seccomp_loop 213 214 // func addrOfInitStubProcess() uintptr 215 TEXT ·addrOfInitStubProcess(SB), $0-8 216 MOVD $·initStubProcess(SB), R0 217 MOVD R0, ret+0(FP) 218 RET 219 220 // stubCall calls the stub function at the given address with the given PPID. 221 // 222 // This is a distinct function because stub, above, may be mapped at any 223 // arbitrary location, and stub has a specific binary API (see above). 224 TEXT ·stubCall(SB),NOSPLIT,$0-16 225 MOVD addr+0(FP), R0 226 MOVD pid+8(FP), R7 227 B (R0)