summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/socket/rpcinet/socket.go
diff options
context:
space:
mode:
authorBrian Geffon <bgeffon@google.com>2018-06-06 15:52:29 -0700
committerShentubot <shentubot@google.com>2018-06-06 15:53:26 -0700
commit79fef54eb1b9e941e2c910f90b65f3cfe94e18c4 (patch)
tree27271ed00212533e0715f4b7d23cd4bd4fe4b250 /pkg/sentry/socket/rpcinet/socket.go
parent0c34b460f21d6f756b6402688203cfc5e533caa1 (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.go63
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) {