github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/socket/hostinet/socket_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 hostinet 16 17 import ( 18 "unsafe" 19 20 "golang.org/x/sys/unix" 21 "github.com/SagerNet/gvisor/pkg/abi/linux" 22 "github.com/SagerNet/gvisor/pkg/context" 23 "github.com/SagerNet/gvisor/pkg/hostarch" 24 "github.com/SagerNet/gvisor/pkg/sentry/arch" 25 "github.com/SagerNet/gvisor/pkg/sentry/kernel" 26 "github.com/SagerNet/gvisor/pkg/sentry/socket" 27 "github.com/SagerNet/gvisor/pkg/syserr" 28 "github.com/SagerNet/gvisor/pkg/syserror" 29 "github.com/SagerNet/gvisor/pkg/usermem" 30 ) 31 32 func firstBytePtr(bs []byte) unsafe.Pointer { 33 if bs == nil { 34 return nil 35 } 36 return unsafe.Pointer(&bs[0]) 37 } 38 39 // Preconditions: len(dsts) != 0. 40 func readv(fd int, dsts []unix.Iovec) (uint64, error) { 41 n, _, errno := unix.Syscall(unix.SYS_READV, uintptr(fd), uintptr(unsafe.Pointer(&dsts[0])), uintptr(len(dsts))) 42 if errno != 0 { 43 return 0, translateIOSyscallError(errno) 44 } 45 return uint64(n), nil 46 } 47 48 // Preconditions: len(srcs) != 0. 49 func writev(fd int, srcs []unix.Iovec) (uint64, error) { 50 n, _, errno := unix.Syscall(unix.SYS_WRITEV, uintptr(fd), uintptr(unsafe.Pointer(&srcs[0])), uintptr(len(srcs))) 51 if errno != 0 { 52 return 0, translateIOSyscallError(errno) 53 } 54 return uint64(n), nil 55 } 56 57 func ioctl(ctx context.Context, fd int, io usermem.IO, args arch.SyscallArguments) (uintptr, error) { 58 switch cmd := uintptr(args[1].Int()); cmd { 59 case unix.TIOCINQ, unix.TIOCOUTQ: 60 var val int32 61 if _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), cmd, uintptr(unsafe.Pointer(&val))); errno != 0 { 62 return 0, translateIOSyscallError(errno) 63 } 64 var buf [4]byte 65 hostarch.ByteOrder.PutUint32(buf[:], uint32(val)) 66 _, err := io.CopyOut(ctx, args[2].Pointer(), buf[:], usermem.IOOpts{ 67 AddressSpaceActive: true, 68 }) 69 return 0, err 70 case unix.SIOCGIFFLAGS: 71 cc := &usermem.IOCopyContext{ 72 Ctx: ctx, 73 IO: io, 74 Opts: usermem.IOOpts{ 75 AddressSpaceActive: true, 76 }, 77 } 78 var ifr linux.IFReq 79 if _, err := ifr.CopyIn(cc, args[2].Pointer()); err != nil { 80 return 0, err 81 } 82 if _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), cmd, uintptr(unsafe.Pointer(&ifr))); errno != 0 { 83 return 0, translateIOSyscallError(errno) 84 } 85 _, err := ifr.CopyOut(cc, args[2].Pointer()) 86 return 0, err 87 default: 88 return 0, syserror.ENOTTY 89 } 90 } 91 92 func accept4(fd int, addr *byte, addrlen *uint32, flags int) (int, error) { 93 afd, _, errno := unix.Syscall6(unix.SYS_ACCEPT4, uintptr(fd), uintptr(unsafe.Pointer(addr)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) 94 if errno != 0 { 95 return 0, translateIOSyscallError(errno) 96 } 97 return int(afd), nil 98 } 99 100 func getsockopt(fd int, level, name int, optlen int) ([]byte, error) { 101 opt := make([]byte, optlen) 102 optlen32 := int32(len(opt)) 103 _, _, errno := unix.Syscall6(unix.SYS_GETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(firstBytePtr(opt)), uintptr(unsafe.Pointer(&optlen32)), 0) 104 if errno != 0 { 105 return nil, errno 106 } 107 return opt[:optlen32], nil 108 } 109 110 // GetSockName implements socket.Socket.GetSockName. 111 func (s *socketOpsCommon) GetSockName(t *kernel.Task) (linux.SockAddr, uint32, *syserr.Error) { 112 addr := make([]byte, sizeofSockaddr) 113 addrlen := uint32(len(addr)) 114 _, _, errno := unix.Syscall(unix.SYS_GETSOCKNAME, uintptr(s.fd), uintptr(unsafe.Pointer(&addr[0])), uintptr(unsafe.Pointer(&addrlen))) 115 if errno != 0 { 116 return nil, 0, syserr.FromError(errno) 117 } 118 return socket.UnmarshalSockAddr(s.family, addr), addrlen, nil 119 } 120 121 // GetPeerName implements socket.Socket.GetPeerName. 122 func (s *socketOpsCommon) GetPeerName(t *kernel.Task) (linux.SockAddr, uint32, *syserr.Error) { 123 addr := make([]byte, sizeofSockaddr) 124 addrlen := uint32(len(addr)) 125 _, _, errno := unix.Syscall(unix.SYS_GETPEERNAME, uintptr(s.fd), uintptr(unsafe.Pointer(&addr[0])), uintptr(unsafe.Pointer(&addrlen))) 126 if errno != 0 { 127 return nil, 0, syserr.FromError(errno) 128 } 129 return socket.UnmarshalSockAddr(s.family, addr), addrlen, nil 130 } 131 132 func recvfrom(fd int, dst []byte, flags int, from *[]byte) (uint64, error) { 133 fromLen := uint32(len(*from)) 134 n, _, errno := unix.Syscall6(unix.SYS_RECVFROM, uintptr(fd), uintptr(firstBytePtr(dst)), uintptr(len(dst)), uintptr(flags), uintptr(firstBytePtr(*from)), uintptr(unsafe.Pointer(&fromLen))) 135 if errno != 0 { 136 return 0, translateIOSyscallError(errno) 137 } 138 *from = (*from)[:fromLen] 139 return uint64(n), nil 140 } 141 142 func recvmsg(fd int, msg *unix.Msghdr, flags int) (uint64, error) { 143 n, _, errno := unix.Syscall(unix.SYS_RECVMSG, uintptr(fd), uintptr(unsafe.Pointer(msg)), uintptr(flags)) 144 if errno != 0 { 145 return 0, translateIOSyscallError(errno) 146 } 147 return uint64(n), nil 148 } 149 150 func sendmsg(fd int, msg *unix.Msghdr, flags int) (uint64, error) { 151 n, _, errno := unix.Syscall(unix.SYS_SENDMSG, uintptr(fd), uintptr(unsafe.Pointer(msg)), uintptr(flags)) 152 if errno != 0 { 153 return 0, translateIOSyscallError(errno) 154 } 155 return uint64(n), nil 156 }