github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/sentry/platform/systrap/systrap_unsafe.go (about) 1 // Copyright 2018 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 package systrap 16 17 import ( 18 "unsafe" 19 20 "golang.org/x/sys/unix" 21 "github.com/nicocha30/gvisor-ligolo/pkg/abi/linux" 22 "github.com/nicocha30/gvisor-ligolo/pkg/hostarch" 23 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/arch" 24 ) 25 26 // getRegs gets the general purpose register set. 27 func (t *thread) getRegs(regs *arch.Registers) error { 28 iovec := unix.Iovec{ 29 Base: (*byte)(unsafe.Pointer(regs)), 30 Len: uint64(unsafe.Sizeof(*regs)), 31 } 32 _, _, errno := unix.RawSyscall6( 33 unix.SYS_PTRACE, 34 unix.PTRACE_GETREGSET, 35 uintptr(t.tid), 36 linux.NT_PRSTATUS, 37 uintptr(unsafe.Pointer(&iovec)), 38 0, 0) 39 if errno != 0 { 40 return errno 41 } 42 return nil 43 } 44 45 // setRegs sets the general purpose register set. 46 func (t *thread) setRegs(regs *arch.Registers) error { 47 iovec := unix.Iovec{ 48 Base: (*byte)(unsafe.Pointer(regs)), 49 Len: uint64(unsafe.Sizeof(*regs)), 50 } 51 _, _, errno := unix.RawSyscall6( 52 unix.SYS_PTRACE, 53 unix.PTRACE_SETREGSET, 54 uintptr(t.tid), 55 linux.NT_PRSTATUS, 56 uintptr(unsafe.Pointer(&iovec)), 57 0, 0) 58 if errno != 0 { 59 return errno 60 } 61 return nil 62 } 63 64 // getSignalInfo retrieves information about the signal that caused the stop. 65 func (t *thread) getSignalInfo(si *linux.SignalInfo) error { 66 _, _, errno := unix.RawSyscall6( 67 unix.SYS_PTRACE, 68 unix.PTRACE_GETSIGINFO, 69 uintptr(t.tid), 70 0, 71 uintptr(unsafe.Pointer(si)), 72 0, 0) 73 if errno != 0 { 74 return errno 75 } 76 return nil 77 } 78 79 // clone creates a new sysmsg thread from this one. 80 // 81 // The returned thread will be stopped and available for any system thread to 82 // call attach on it. 83 // 84 // Precondition: the OS thread must be locked and own t. 85 func (t *thread) clone() (*thread, error) { 86 r, ok := hostarch.Addr(stackPointer(&t.initRegs)).RoundUp() 87 if !ok { 88 return nil, unix.EINVAL 89 } 90 var flags uintptr 91 // Create a sysmsg thread. 92 // 93 // CLONE_THREAD isn't set, because a stub process has SIGSTOP 94 // in its queue. A sysmsg thread will not be traced by ptrace, 95 // so it will be stopped immediately if it will share signal 96 // queue with its stub process. 97 flags = uintptr( 98 unix.CLONE_FILES | 99 unix.CLONE_FS | 100 unix.CLONE_PTRACE | 101 unix.CLONE_VM) 102 rval, err := t.syscallIgnoreInterrupt( 103 &t.initRegs, 104 unix.SYS_CLONE, 105 arch.SyscallArgument{Value: flags}, 106 // The stack pointer is just made up, but we have it be 107 // something sensible so the kernel doesn't think we're 108 // up to no good. Which we are. 109 arch.SyscallArgument{Value: uintptr(r)}, 110 arch.SyscallArgument{}, 111 arch.SyscallArgument{}, 112 // We use these registers initially, but really they 113 // could be anything. We're going to stop immediately. 114 arch.SyscallArgument{Value: uintptr(unsafe.Pointer(&t.initRegs))}) 115 if err != nil { 116 return nil, err 117 } 118 119 return &thread{ 120 tgid: int32(rval), 121 tid: int32(rval), 122 }, nil 123 } 124 125 // getEventMessage retrieves a message about the ptrace event that just happened. 126 func (t *thread) getEventMessage() (uintptr, error) { 127 var msg uintptr 128 _, _, errno := unix.RawSyscall6( 129 unix.SYS_PTRACE, 130 unix.PTRACE_GETEVENTMSG, 131 uintptr(t.tid), 132 0, 133 uintptr(unsafe.Pointer(&msg)), 134 0, 0) 135 if errno != 0 { 136 return msg, errno 137 } 138 return msg, nil 139 }