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  }