github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/sentry/platform/systrap/subprocess_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 //go:build go1.18 16 // +build go1.18 17 18 // //go:linkname directives type-checked by checklinkname. Any other 19 // non-linkname assumptions outside the Go 1 compatibility guarantee should 20 // have an accompanied vet check or version guard build tag. 21 22 package systrap 23 24 import ( 25 "fmt" 26 "unsafe" 27 28 "golang.org/x/sys/unix" 29 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/arch" 30 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/memmap" 31 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/pgalloc" 32 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/platform/systrap/sysmsg" 33 ) 34 35 //go:linkname beforeFork syscall.runtime_BeforeFork 36 func beforeFork() 37 38 //go:linkname afterFork syscall.runtime_AfterFork 39 func afterFork() 40 41 //go:linkname afterForkInChild syscall.runtime_AfterForkInChild 42 func afterForkInChild() 43 44 //go:linkname cputicks runtime.cputicks 45 func cputicks() int64 46 47 // spinloop is implemented in assembly. 48 func spinloop() 49 50 // getThreadContextFromID returns a ThreadContext struct that corresponds to the 51 // given ID. 52 // 53 // Precondition: cid must be a valid thread context ID that has a mapping for it 54 // that exists in s.contexts. 55 func (s *subprocess) getThreadContextFromID(cid uint64) *sysmsg.ThreadContext { 56 tcSlot := s.threadContextRegion + uintptr(cid)*sysmsg.AllocatedSizeofThreadContextStruct 57 return (*sysmsg.ThreadContext)(unsafe.Pointer(tcSlot)) 58 } 59 60 func mmapContextQueueForSentry(memoryFile *pgalloc.MemoryFile, opts pgalloc.AllocOpts) (memmap.FileRange, *contextQueue) { 61 fr, err := memoryFile.Allocate(uint64(stubContextQueueRegionLen), opts) 62 if err != nil { 63 panic(fmt.Sprintf("failed to allocate a new subprocess context memory region")) 64 } 65 addr, _, errno := unix.RawSyscall6( 66 unix.SYS_MMAP, 67 0, 68 uintptr(fr.Length()), 69 unix.PROT_WRITE|unix.PROT_READ, 70 unix.MAP_SHARED|unix.MAP_FILE, 71 uintptr(memoryFile.FD()), uintptr(fr.Start)) 72 if errno != 0 { 73 panic(fmt.Sprintf("mmap failed for subprocess context memory region: %v", errno)) 74 } 75 76 return fr, (*contextQueue)(unsafe.Pointer(addr)) 77 } 78 79 func saveFPState(ctx *sharedContext, ac *arch.Context64) { 80 fpState := ac.FloatingPointData().BytePointer() 81 dst := unsafeSlice(uintptr(unsafe.Pointer(fpState)), archState.FpLen()) 82 src := ctx.shared.FPState[:] 83 copy(dst, src) 84 } 85 86 // restoreFPStateDecoupledContext writes FPState from c to the thread context 87 // shared memory region if there is any need to do so. 88 func restoreFPState(ctx *sharedContext, c *context, ac *arch.Context64) { 89 if !c.needRestoreFPState { 90 return 91 } 92 c.needRestoreFPState = false 93 ctx.setFPStateChanged() 94 95 fpState := ac.FloatingPointData().BytePointer() 96 src := unsafeSlice(uintptr(unsafe.Pointer(fpState)), archState.FpLen()) 97 dst := ctx.shared.FPState[:] 98 copy(dst, src) 99 }