summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorFabricio Voznika <fvoznika@google.com>2019-08-30 17:17:45 -0700
committergVisor bot <gvisor-bot@google.com>2019-08-30 17:19:09 -0700
commit502c47f7a70a088213faf27b60e6f62ece4dd765 (patch)
tree13b73dc3c16828fbaa029d73e944f16ef7fc161b
parent3ec0b64d8c7d1649fd06291f3b5d0a3ca6db98d6 (diff)
Return correct buffer size for ioctl(socket, FIONREAD)
Ioctl was returning just the buffer size from epsocket.endpoint and it was not considering data from epsocket.SocketOperations that was read from the endpoint, but not yet sent to the caller. PiperOrigin-RevId: 266485461
-rw-r--r--pkg/sentry/socket/epsocket/epsocket.go22
-rw-r--r--test/syscalls/linux/tcp_socket.cc21
2 files changed, 41 insertions, 2 deletions
diff --git a/pkg/sentry/socket/epsocket/epsocket.go b/pkg/sentry/socket/epsocket/epsocket.go
index def29646e..0e37ce61b 100644
--- a/pkg/sentry/socket/epsocket/epsocket.go
+++ b/pkg/sentry/socket/epsocket/epsocket.go
@@ -2104,7 +2104,8 @@ func (s *SocketOperations) Ioctl(ctx context.Context, _ *fs.File, io usermem.IO,
// SIOCGSTAMP is implemented by epsocket rather than all commonEndpoint
// sockets.
// TODO(b/78348848): Add a commonEndpoint method to support SIOCGSTAMP.
- if int(args[1].Int()) == syscall.SIOCGSTAMP {
+ switch args[1].Int() {
+ case syscall.SIOCGSTAMP:
s.readMu.Lock()
defer s.readMu.Unlock()
if !s.timestampValid {
@@ -2116,6 +2117,25 @@ func (s *SocketOperations) Ioctl(ctx context.Context, _ *fs.File, io usermem.IO,
AddressSpaceActive: true,
})
return 0, err
+
+ case linux.TIOCINQ:
+ v, terr := s.Endpoint.GetSockOptInt(tcpip.ReceiveQueueSizeOption)
+ if terr != nil {
+ return 0, syserr.TranslateNetstackError(terr).ToError()
+ }
+
+ // Add bytes removed from the endpoint but not yet sent to the caller.
+ v += len(s.readView)
+
+ if v > math.MaxInt32 {
+ v = math.MaxInt32
+ }
+
+ // Copy result to user-space.
+ _, err := usermem.CopyObjectOut(ctx, io, args[2].Pointer(), int32(v), usermem.IOOpts{
+ AddressSpaceActive: true,
+ })
+ return 0, err
}
return Ioctl(ctx, s.Endpoint, io, args)
diff --git a/test/syscalls/linux/tcp_socket.cc b/test/syscalls/linux/tcp_socket.cc
index 8f4d3f386..bfa031bce 100644
--- a/test/syscalls/linux/tcp_socket.cc
+++ b/test/syscalls/linux/tcp_socket.cc
@@ -579,7 +579,7 @@ TEST_P(TcpSocketTest, TcpInq) {
if (size == sizeof(buf)) {
break;
}
- usleep(10000);
+ absl::SleepFor(absl::Milliseconds(10));
}
struct msghdr msg = {};
@@ -610,6 +610,25 @@ TEST_P(TcpSocketTest, TcpInq) {
}
}
+TEST_P(TcpSocketTest, Tiocinq) {
+ char buf[1024];
+ size_t size = sizeof(buf);
+ ASSERT_THAT(RetryEINTR(write)(s_, buf, size), SyscallSucceedsWithValue(size));
+
+ uint32_t seed = time(nullptr);
+ const size_t max_chunk = size / 10;
+ while (size > 0) {
+ size_t chunk = (rand_r(&seed) % max_chunk) + 1;
+ ssize_t read = RetryEINTR(recvfrom)(t_, buf, chunk, 0, nullptr, nullptr);
+ ASSERT_THAT(read, SyscallSucceeds());
+ size -= read;
+
+ int inq = 0;
+ ASSERT_THAT(ioctl(t_, TIOCINQ, &inq), SyscallSucceeds());
+ ASSERT_EQ(inq, size);
+ }
+}
+
TEST_P(TcpSocketTest, TcpSCMPriority) {
char buf[1024];
ASSERT_THAT(RetryEINTR(write)(s_, buf, sizeof(buf)),