]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
af_unix: Fix inq_len update problem in partial read
authorJianyu Li <jianyu.li@mediatek.com>
Mon, 1 Jun 2026 11:36:39 +0000 (19:36 +0800)
committerJakub Kicinski <kuba@kernel.org>
Thu, 4 Jun 2026 01:52:25 +0000 (18:52 -0700)
Currently inq_len is updated only when the whole skb is consumed.
If only part of the data is read, following SIOCINQ query would
get value greater than what actually left.

This change update inq_len timely in unix_stream_read_generic(),
and adjust unix_stream_read_skb() accordingly to prevent
repetitive update.

Fixes: f4e1fb04c123 ("af_unix: Use cached value for SOCK_STREAM in unix_inq_len().")
Signed-off-by: Jianyu Li <jianyu.li@mediatek.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Link: https://patch.msgid.link/20260601113640.231897-2-jianyu.li@mediatek.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/unix/af_unix.c

index dc71ed79be4aadae493cd06e8af3d403c1a35439..0d9cd977c7b78626f081ecee8807ae156cbe03a6 100644 (file)
@@ -2886,7 +2886,7 @@ static int unix_stream_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
                return -EAGAIN;
        }
 
-       WRITE_ONCE(u->inq_len, u->inq_len - skb->len);
+       WRITE_ONCE(u->inq_len, u->inq_len - unix_skb_len(skb));
 
 #if IS_ENABLED(CONFIG_AF_UNIX_OOB)
        if (skb == u->oob_skb) {
@@ -3063,11 +3063,12 @@ unlock:
                                unix_detach_fds(&scm, skb);
                        }
 
-                       if (unix_skb_len(skb))
-                               break;
-
                        spin_lock(&sk->sk_receive_queue.lock);
-                       WRITE_ONCE(u->inq_len, u->inq_len - skb->len);
+                       WRITE_ONCE(u->inq_len, u->inq_len - chunk);
+                       if (unix_skb_len(skb)) {
+                               spin_unlock(&sk->sk_receive_queue.lock);
+                               break;
+                       }
                        __skb_unlink(skb, &sk->sk_receive_queue);
                        spin_unlock(&sk->sk_receive_queue.lock);