diff options
author | Ian Lewis <ianlewis@google.com> | 2020-01-08 16:35:43 -0800 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2020-01-08 17:24:05 -0800 |
commit | fbb2c008e26a7e9d860f6cbf796ea7c375858502 (patch) | |
tree | 698e17f595ea9a689579cf009011171c4bbdcf9a /pkg/sentry/socket/unix/unix.go | |
parent | 565b64148314018e1234196182b55c4f01772e77 (diff) |
Return correct length with MSG_TRUNC for unix sockets.
This change calls a new Truncate method on the EndpointReader in RecvMsg for
both netlink and unix sockets. This allows readers such as sockets to peek at
the length of data without actually reading it to a buffer.
Fixes #993 #1240
PiperOrigin-RevId: 288800167
Diffstat (limited to 'pkg/sentry/socket/unix/unix.go')
-rw-r--r-- | pkg/sentry/socket/unix/unix.go | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/pkg/sentry/socket/unix/unix.go b/pkg/sentry/socket/unix/unix.go index 885758054..91effe89a 100644 --- a/pkg/sentry/socket/unix/unix.go +++ b/pkg/sentry/socket/unix/unix.go @@ -544,8 +544,27 @@ func (s *SocketOperations) RecvMsg(t *kernel.Task, dst usermem.IOSequence, flags if senderRequested { r.From = &tcpip.FullAddress{} } + + doRead := func() (int64, error) { + return dst.CopyOutFrom(t, &r) + } + + // If MSG_TRUNC is set with a zero byte destination then we still need + // to read the message and discard it, or in the case where MSG_PEEK is + // set, leave it be. In both cases the full message length must be + // returned. + if trunc && dst.Addrs.NumBytes() == 0 { + doRead = func() (int64, error) { + err := r.Truncate() + // Always return zero for bytes read since the destination size is + // zero. + return 0, err + } + + } + var total int64 - if n, err := dst.CopyOutFrom(t, &r); err != syserror.ErrWouldBlock || dontWait { + if n, err := doRead(); err != syserror.ErrWouldBlock || dontWait { var from linux.SockAddr var fromLen uint32 if r.From != nil && len([]byte(r.From.Addr)) != 0 { @@ -580,7 +599,7 @@ func (s *SocketOperations) RecvMsg(t *kernel.Task, dst usermem.IOSequence, flags defer s.EventUnregister(&e) for { - if n, err := dst.CopyOutFrom(t, &r); err != syserror.ErrWouldBlock { + if n, err := doRead(); err != syserror.ErrWouldBlock { var from linux.SockAddr var fromLen uint32 if r.From != nil { |