summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/socket
diff options
context:
space:
mode:
authorBrian Geffon <bgeffon@google.com>2018-06-17 17:05:36 -0700
committerShentubot <shentubot@google.com>2018-06-17 17:06:40 -0700
commit563a71ef243360bc20db0e481b3adbfb07cd8702 (patch)
treec4bcfc2b58224fe879166bb1b0b5ef9401dcdb25 /pkg/sentry/socket
parent0786707cd94b8feffaeb083077eccaf10873e682 (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
Diffstat (limited to 'pkg/sentry/socket')
-rw-r--r--pkg/sentry/socket/rpcinet/socket.go37
-rw-r--r--pkg/sentry/socket/rpcinet/syscall_rpc.proto2
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;