]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
io_uring/zcrx: return early from io_zcrx_recv_skb if readlen is 0
authorDavid Wei <dw@davidwei.uk>
Tue, 1 Apr 2025 19:53:55 +0000 (12:53 -0700)
committerJens Axboe <axboe@kernel.dk>
Tue, 1 Apr 2025 20:00:46 +0000 (14:00 -0600)
When readlen is set for a recvzc request, tcp_read_sock() will call
io_zcrx_recv_skb() one final time with len == desc->count == 0. This is
caused by the !desc->count check happening too late. The offset + 1 !=
skb->len happens earlier and causes the while loop to continue.

Fix this in io_zcrx_recv_skb() instead of tcp_read_sock(). Return early
if len is 0 i.e. the read is done.

Fixes: 6699ec9a23f8 ("io_uring/zcrx: add a read limit to recvzc requests")
Signed-off-by: David Wei <dw@davidwei.uk>
Link: https://lore.kernel.org/r/20250401195355.1613813-1-dw@davidwei.uk
Signed-off-by: Jens Axboe <axboe@kernel.dk>
io_uring/zcrx.c

index 9c95b5b6ec4eb497885c47aae37753b89c1b5b21..80d4a6f71d2931223c2a932e34d38a37a1df8efe 100644 (file)
@@ -818,6 +818,14 @@ io_zcrx_recv_skb(read_descriptor_t *desc, struct sk_buff *skb,
        int ret = 0;
 
        len = min_t(size_t, len, desc->count);
+       /*
+        * __tcp_read_sock() always calls io_zcrx_recv_skb one last time, even
+        * if desc->count is already 0. This is caused by the if (offset + 1 !=
+        * skb->len) check. Return early in this case to break out of
+        * __tcp_read_sock().
+        */
+       if (!len)
+               return 0;
        if (unlikely(args->nr_skbs++ > IO_SKBS_PER_CALL_LIMIT))
                return -EAGAIN;