| // Copyright 2019 The gVisor Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "funcdata.h" |
| #include "textflag.h" |
| |
| #define SYS_GETPID 172 |
| #define SYS_EXIT 93 |
| #define SYS_KILL 129 |
| #define SYS_GETPPID 173 |
| #define SYS_PRCTL 167 |
| |
| #define SIGKILL 9 |
| #define SIGSTOP 19 |
| |
| #define PR_SET_PDEATHSIG 1 |
| |
| // stub bootstraps the child and sends itself SIGSTOP to wait for attach. |
| // |
| // R7 contains the expected PPID. |
| // |
| // This should not be used outside the context of a new ptrace child (as the |
| // function is otherwise a bunch of nonsense). |
| TEXT ·stub(SB),NOSPLIT,$0 |
| begin: |
| // N.B. This loop only executes in the context of a single-threaded |
| // fork child. |
| |
| MOVD $SYS_PRCTL, R8 |
| MOVD $PR_SET_PDEATHSIG, R0 |
| MOVD $SIGKILL, R1 |
| SVC |
| |
| CMN $4095, R0 |
| BCS error |
| |
| // If the parent already died before we called PR_SET_DEATHSIG then |
| // we'll have an unexpected PPID. |
| MOVD $SYS_GETPPID, R8 |
| SVC |
| |
| CMP R0, R7 |
| BNE parent_dead |
| |
| MOVD $SYS_GETPID, R8 |
| SVC |
| |
| CMP $0x0, R0 |
| BLT error |
| |
| MOVD $0, R9 |
| |
| // SIGSTOP to wait for attach. |
| // |
| // The SYSCALL instruction will be used for future syscall injection by |
| // thread.syscall. |
| MOVD $SYS_KILL, R8 |
| MOVD $SIGSTOP, R1 |
| SVC |
| |
| // The sentry sets R9 to 1 when creating stub process. |
| CMP $1, R9 |
| BEQ clone |
| |
| done: |
| // Notify the Sentry that syscall exited. |
| BRK $3 |
| B done // Be paranoid. |
| clone: |
| // subprocess.createStub clones a new stub process that is untraced, |
| // thus executing this code. We setup the PDEATHSIG before SIGSTOPing |
| // ourselves for attach by the tracer. |
| // |
| // R7 has been updated with the expected PPID. |
| CMP $0, R0 |
| BEQ begin |
| |
| // The clone system call returned a non-zero value. |
| B done |
| |
| error: |
| // Exit with -errno. |
| NEG R0, R0 |
| MOVD $SYS_EXIT, R8 |
| SVC |
| HLT |
| |
| parent_dead: |
| MOVD $SYS_EXIT, R8 |
| MOVD $1, R0 |
| SVC |
| HLT |
| |
| // stubCall calls the stub function at the given address with the given PPID. |
| // |
| // This is a distinct function because stub, above, may be mapped at any |
| // arbitrary location, and stub has a specific binary API (see above). |
| TEXT ·stubCall(SB),NOSPLIT,$0-16 |
| MOVD addr+0(FP), R0 |
| MOVD pid+8(FP), R7 |
| B (R0) |