github.com/sagernet/gvisor@v0.0.0-20240428053021-e691de28565f/pkg/tcpip/link/sharedmem/sharedmem_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 sharedmem 16 17 import ( 18 "fmt" 19 "reflect" 20 "unsafe" 21 22 "golang.org/x/sys/unix" 23 "github.com/sagernet/gvisor/pkg/atomicbitops" 24 "github.com/sagernet/gvisor/pkg/memutil" 25 ) 26 27 // sharedDataPointer converts the shared data slice into a pointer so that it 28 // can be used in atomic operations. 29 func sharedDataPointer(sharedData []byte) *atomicbitops.Uint32 { 30 return (*atomicbitops.Uint32)(unsafe.Pointer(&sharedData[0:4][0])) 31 } 32 33 // getBuffer returns a memory region mapped to the full contents of the given 34 // file descriptor. 35 func getBuffer(fd int) ([]byte, error) { 36 var s unix.Stat_t 37 if err := unix.Fstat(fd, &s); err != nil { 38 return nil, err 39 } 40 41 // Check that size doesn't overflow an int. 42 if s.Size > int64(^uint(0)>>1) { 43 return nil, unix.EDOM 44 } 45 46 addr, err := memutil.MapFile(0 /* addr */, uintptr(s.Size), unix.PROT_READ|unix.PROT_WRITE, unix.MAP_SHARED|unix.MAP_FILE, uintptr(fd), 0 /*offset*/) 47 if err != nil { 48 return nil, fmt.Errorf("failed to map memory for buffer fd: %d, error: %s", fd, err) 49 } 50 51 // Use unsafe to convert addr into a []byte. 52 var b []byte 53 hdr := (*reflect.SliceHeader)(unsafe.Pointer(&b)) 54 hdr.Data = addr 55 hdr.Len = int(s.Size) 56 hdr.Cap = int(s.Size) 57 58 return b, nil 59 }