gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/sentry/platform/systrap/syscall_thread_unsafe.go (about) 1 // Copyright 2021 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 "fmt" 19 "sync/atomic" 20 "unsafe" 21 22 "golang.org/x/sys/unix" 23 "gvisor.dev/gvisor/pkg/abi/linux" 24 ) 25 26 func (t *syscallThread) initRequestReplyAddresses(sentryStackAddr uintptr) { 27 // These are safe as these addresses are mmapped and never moved/gced. 28 sentryMessage := (*syscallSentryMessage)(unsafe.Pointer(sentryStackAddr)) 29 stubMessage := (*syscallStubMessage)(unsafe.Pointer(sentryStackAddr + syscallStubMessageOffset)) 30 atomic.StoreUint32(&sentryMessage.state, 0) 31 32 t.sentryMessage = sentryMessage 33 t.stubMessage = stubMessage 34 } 35 36 // maskAllSignals blocks all signals. 37 func (t *syscallThread) maskAllSignalsAttached() { 38 p := t.thread 39 40 mask := ^uint64(0) 41 if _, _, errno := unix.RawSyscall6(unix.SYS_PTRACE, linux.PTRACE_SETSIGMASK, uintptr(p.tid), 8, uintptr(unsafe.Pointer(&mask)), 0, 0); errno != 0 { 42 panic(fmt.Sprintf("unable to setmask: %v", errno)) 43 } 44 } 45 46 // unmaskAllSignals unblocks all signals. 47 func (t *syscallThread) unmaskAllSignalsAttached() { 48 p := t.thread 49 mask := uint64(0) 50 if _, _, errno := unix.RawSyscall6(unix.SYS_PTRACE, linux.PTRACE_SETSIGMASK, uintptr(p.tid), 8, uintptr(unsafe.Pointer(&mask)), 0, 0); errno != 0 { 51 panic(fmt.Sprintf("unable to setmask: %v", errno)) 52 } 53 } 54 55 func futexWakeUint32(addr *uint32) error { 56 if _, _, e := unix.RawSyscall6(unix.SYS_FUTEX, uintptr(unsafe.Pointer(addr)), linux.FUTEX_WAKE, 1, 0, 0, 0); e != 0 { 57 return fmt.Errorf("failed to FUTEX_WAKE: %v", e) 58 } 59 return nil 60 } 61 62 func futexWaitForUint32(addr *uint32, targetValue uint32) error { 63 for { 64 val := atomic.LoadUint32(addr) 65 if val == targetValue { 66 break 67 } 68 69 _, _, e := unix.Syscall6(unix.SYS_FUTEX, uintptr(unsafe.Pointer(addr)), linux.FUTEX_WAIT, uintptr(val), 0, 0, 0) 70 if e != 0 && e != unix.EAGAIN && e != unix.EINTR { 71 return fmt.Errorf("failed to FUTEX_WAIT: %v", e) 72 } 73 } 74 return nil 75 } 76 77 // futexWaitWake waits when other side will call FUTEX_WAKE. A value of the 78 // futex word has to be equal to futexValue and it must not be changed. 79 func futexWaitWake(futexAddr *uint32, futexValue uint32) error { 80 for { 81 _, _, e := unix.Syscall6(unix.SYS_FUTEX, uintptr(unsafe.Pointer(futexAddr)), linux.FUTEX_WAIT, uintptr(futexValue), 0, 0, 0) 82 if e == 0 { 83 break 84 } 85 if e != unix.EAGAIN && e != unix.EINTR { 86 return fmt.Errorf("failed to FUTEX_WAIT: %v", e) 87 } 88 } 89 90 return nil 91 } 92 93 func (t *syscallThread) kickSeccompNotify() unix.Errno { 94 _, _, errno := unix.RawSyscall(unix.SYS_IOCTL, uintptr(t.seccompNotify.Fd()), 95 uintptr(linux.SECCOMP_IOCTL_NOTIF_SEND), 96 uintptr(unsafe.Pointer(&t.seccompNotifyResp))) 97 return errno 98 } 99 100 func (t *syscallThread) waitForSeccompNotify() error { 101 for { 102 req := linux.SeccompNotif{} 103 _, _, errno := unix.RawSyscall(unix.SYS_IOCTL, uintptr(t.seccompNotify.Fd()), 104 uintptr(linux.SECCOMP_IOCTL_NOTIF_RECV), 105 uintptr(unsafe.Pointer(&req))) 106 if errno == 0 { 107 t.seccompNotifyResp.ID = req.ID 108 break 109 } 110 if errno == unix.EINTR && t.subproc.alive() { 111 continue 112 } 113 t.thread.kill() 114 return fmt.Errorf("failed getting response from syscall thread : %w", errno) 115 } 116 return nil 117 }