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)