mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
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
This commit is contained in:
committed by
gVisor bot
parent
3ec0b64d8c
commit
502c47f7a7
@@ -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)
|
||||
|
||||
@@ -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)),
|
||||
|
||||
Reference in New Issue
Block a user