diff options
author | Brian Geffon <bgeffon@google.com> | 2018-06-17 17:05:36 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-06-17 17:06:40 -0700 |
commit | 563a71ef243360bc20db0e481b3adbfb07cd8702 (patch) | |
tree | c4bcfc2b58224fe879166bb1b0b5ef9401dcdb25 | |
parent | 0786707cd94b8feffaeb083077eccaf10873e682 (diff) |
Add rpcinet support for control messages.
Add support for control messages, but at this time the only
control message that the sentry will support here is SO_TIMESTAMP.
PiperOrigin-RevId: 200922230
Change-Id: I63a852d9305255625d9df1d989bd46a66e93c446
-rw-r--r-- | pkg/sentry/socket/rpcinet/socket.go | 37 | ||||
-rw-r--r-- | pkg/sentry/socket/rpcinet/syscall_rpc.proto | 2 |
2 files changed, 37 insertions, 2 deletions
diff --git a/pkg/sentry/socket/rpcinet/socket.go b/pkg/sentry/socket/rpcinet/socket.go index d8c1f2c1a..b4b380ac6 100644 --- a/pkg/sentry/socket/rpcinet/socket.go +++ b/pkg/sentry/socket/rpcinet/socket.go @@ -477,6 +477,37 @@ func rpcRecvMsg(t *kernel.Task, req *pb.SyscallRequest_Recvmsg) (*pb.RecvmsgResp return res.(*pb.RecvmsgResponse_Payload).Payload, nil } +// Because we only support SO_TIMESTAMP we will search control messages for +// that value and set it if so, all other control messages will be ignored. +func (s *socketOperations) extractControlMessages(payload *pb.RecvmsgResponse_ResultPayload) socket.ControlMessages { + c := socket.ControlMessages{} + if len(payload.GetCmsgData()) > 0 { + // Parse the control messages looking for SO_TIMESTAMP. + msgs, e := syscall.ParseSocketControlMessage(payload.GetCmsgData()) + if e != nil { + return socket.ControlMessages{} + } + for _, m := range msgs { + if m.Header.Level != linux.SOL_SOCKET || m.Header.Type != linux.SO_TIMESTAMP { + continue + } + + // Let's parse the time stamp and set it. + if len(m.Data) < linux.SizeOfTimeval { + // Give up on locating the SO_TIMESTAMP option. + return socket.ControlMessages{} + } + + var v linux.Timeval + binary.Unmarshal(m.Data[:linux.SizeOfTimeval], usermem.ByteOrder, &v) + c.IP.HasTimestamp = true + c.IP.Timestamp = v.ToNsecCapped() + break + } + } + return c +} + // RecvMsg implements socket.Socket.RecvMsg. func (s *socketOperations) RecvMsg(t *kernel.Task, dst usermem.IOSequence, flags int, haveDeadline bool, deadline ktime.Time, senderRequested bool, controlDataLen uint64) (int, interface{}, uint32, socket.ControlMessages, *syserr.Error) { req := &pb.SyscallRequest_Recvmsg{&pb.RecvmsgRequest{ @@ -497,7 +528,8 @@ func (s *socketOperations) RecvMsg(t *kernel.Task, dst usermem.IOSequence, flags panic("CopyOut failed to copy full buffer") } } - return int(res.Length), res.Address.GetAddress(), res.Address.GetLength(), socket.ControlMessages{}, syserr.FromError(e) + c := s.extractControlMessages(res) + return int(res.Length), res.Address.GetAddress(), res.Address.GetLength(), c, syserr.FromError(e) } if err != syserr.ErrWouldBlock && err != syserr.ErrTryAgain || flags&linux.MSG_DONTWAIT != 0 { return 0, nil, 0, socket.ControlMessages{}, err @@ -520,7 +552,8 @@ func (s *socketOperations) RecvMsg(t *kernel.Task, dst usermem.IOSequence, flags panic("CopyOut failed to copy full buffer") } } - return int(res.Length), res.Address.GetAddress(), res.Address.GetLength(), socket.ControlMessages{}, syserr.FromError(e) + c := s.extractControlMessages(res) + return int(res.Length), res.Address.GetAddress(), res.Address.GetLength(), c, syserr.FromError(e) } if err != syserr.ErrWouldBlock && err != syserr.ErrTryAgain { return 0, nil, 0, socket.ControlMessages{}, err diff --git a/pkg/sentry/socket/rpcinet/syscall_rpc.proto b/pkg/sentry/socket/rpcinet/syscall_rpc.proto index 996962aae..c056e4c9d 100644 --- a/pkg/sentry/socket/rpcinet/syscall_rpc.proto +++ b/pkg/sentry/socket/rpcinet/syscall_rpc.proto @@ -40,6 +40,7 @@ message RecvmsgRequest { bool sender = 3; bool peek = 4; bool trunc = 5; + uint32 cmsg_length = 6; } message OpenRequest { @@ -110,6 +111,7 @@ message RecvmsgResponse { bytes data = 1 [ctype = CORD]; AddressResponse address = 2; uint32 length = 3; + bytes cmsg_data = 4; } oneof result { uint32 error_number = 1; |