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)