diff options
author | Brian Geffon <bgeffon@google.com> | 2018-06-06 15:52:29 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-06-06 15:53:26 -0700 |
commit | 79fef54eb1b9e941e2c910f90b65f3cfe94e18c4 (patch) | |
tree | 27271ed00212533e0715f4b7d23cd4bd4fe4b250 /pkg/sentry/socket/rpcinet/socket.go | |
parent | 0c34b460f21d6f756b6402688203cfc5e533caa1 (diff) |
Add support for rpcinet ioctl(2).
This change will add support for ioctls that have previously
been supported by netstack.
LINE_LENGTH_IGNORE
PiperOrigin-RevId: 199544114
Change-Id: I3769202c19502c3b7d05e06ea9552acfd9255893
Diffstat (limited to 'pkg/sentry/socket/rpcinet/socket.go')
-rw-r--r-- | pkg/sentry/socket/rpcinet/socket.go | 63 |
1 files changed, 61 insertions, 2 deletions
diff --git a/pkg/sentry/socket/rpcinet/socket.go b/pkg/sentry/socket/rpcinet/socket.go index 74cb84927..3356f7804 100644 --- a/pkg/sentry/socket/rpcinet/socket.go +++ b/pkg/sentry/socket/rpcinet/socket.go @@ -56,6 +56,10 @@ type socketOperations struct { // Verify that we actually implement socket.Socket. var _ = socket.Socket(&socketOperations{}) +const ( + sizeOfIfReq = 40 +) + // New creates a new RPC socket. func newSocketFile(ctx context.Context, stack *Stack, family int, skType int, protocol int) (*fs.File, *syserr.Error) { id, c := stack.rpcConn.NewRequest(pb.SyscallRequest{Args: &pb.SyscallRequest_Socket{&pb.SocketRequest{Family: int64(family), Type: int64(skType | syscall.SOCK_NONBLOCK), Protocol: int64(protocol)}}}, false /* ignoreResult */) @@ -290,7 +294,11 @@ func (s *socketOperations) Accept(t *kernel.Task, peerRequested bool, flags int, return 0, nil, 0, syserr.FromError(err) } - return fd, payload.Address.Address, payload.Address.Length, nil + if peerRequested { + return fd, payload.Address.Address, payload.Address.Length, nil + } + + return fd, nil, 0, nil } // Bind implements socket.Socket.Bind. @@ -385,9 +393,60 @@ func (s *socketOperations) GetSockName(t *kernel.Task) (interface{}, uint32, *sy return addr.Address, addr.Length, nil } +func rpcIoctl(t *kernel.Task, fd, cmd uint32, arg []byte) ([]byte, error) { + stack := t.NetworkContext().(*Stack) + + id, c := stack.rpcConn.NewRequest(pb.SyscallRequest{Args: &pb.SyscallRequest_Ioctl{&pb.IOCtlRequest{Fd: fd, Cmd: cmd, Arg: arg}}}, false /* ignoreResult */) + <-c + + res := stack.rpcConn.Request(id).Result.(*pb.SyscallResponse_Ioctl).Ioctl.Result + if e, ok := res.(*pb.IOCtlResponse_ErrorNumber); ok { + return nil, syscall.Errno(e.ErrorNumber) + } + + return res.(*pb.IOCtlResponse_Value).Value, nil +} + // Ioctl implements fs.FileOperations.Ioctl. func (s *socketOperations) Ioctl(ctx context.Context, io usermem.IO, args arch.SyscallArguments) (uintptr, error) { - return 0, syserror.ENOTTY + t := ctx.(*kernel.Task) + + cmd := uint32(args[1].Int()) + arg := args[2].Pointer() + + var buf []byte + switch cmd { + // The following ioctls take 4 byte argument parameters. + case syscall.TIOCINQ, syscall.TIOCOUTQ: + buf = make([]byte, 4) + // The following ioctls have args which are sizeof(struct ifreq). + case syscall.SIOCGIFINDEX, syscall.SIOCGIFNETMASK, syscall.SIOCGIFHWADDR, syscall.SIOCGIFNAME, syscall.SIOCGIFFLAGS: + buf = make([]byte, sizeOfIfReq) + default: + return 0, syserror.ENOTTY + } + + _, err := io.CopyIn(ctx, arg, buf, usermem.IOOpts{ + AddressSpaceActive: true, + }) + + if err != nil { + return 0, err + } + + v, err := rpcIoctl(t, s.fd, cmd, buf) + if err != nil { + return 0, err + } + + if len(v) != len(buf) { + return 0, syserror.EINVAL + } + + _, err = io.CopyOut(ctx, arg, v, usermem.IOOpts{ + AddressSpaceActive: true, + }) + return 0, err } func rpcRecvMsg(t *kernel.Task, req *pb.SyscallRequest_Recvmsg) (*pb.RecvmsgResponse_ResultPayload, *syserr.Error) { |