* [PATCH net v2 0/2] af_unix: fix inq_len accounting and consumed OOB skb handling in unix_stream_read_skb()
@ 2026-09-24 7:16 Hui Peng
2026-09-24 7:16 ` [PATCH net v2 1/2] af_unix: decrement u->inq_len when skipping unread OOB skb in manage_oob() Hui Peng
2026-09-24 7:16 ` [PATCH net v2 2/2] af_unix: skip consumed OOB skb and pull consumed bytes in unix_stream_read_skb() Hui Peng
0 siblings, 2 replies; 5+ messages in thread
From: Hui Peng @ 2026-09-24 7:16 UTC (permalink / raw)
To: kuniyu, edumazet, davem, kuba, pabeni
Cc: netdev, linux-kernel, stable, Hui Peng
This series addresses two OOB skb handling bugs in AF_UNIX stream sockets:
1. Decrement u->inq_len by 1 when manage_oob() unlinks an unread OOB skb,
preventing u->inq_len from remaining permanently inflated and causing
SIOCINQ / FIONREAD to report a stale positive byte count on an empty
socket.
2. Skip zero-length consumed OOB skbs (after releasing SCM rights via
unix_orphan_scm()) and pull UNIXCB(skb).consumed bytes via pskb_pull()
in unix_stream_read_skb(), preventing BPF sockmap from re-delivering
already consumed OOB bytes or partially consumed skb prefixes.
Changes in v2:
- Split into a 2-patch series as requested by Kuniyuki Iwashima.
- Update Fixes: tag to f4e1fb04c123 ("af_unix: Use cached value for
SOCK_STREAM in unix_inq_len().").
- Call unix_orphan_scm(sk, skb) before consume_skb(skb) and use
pskb_pull() instead of skb_pull() to safely handle non-linear paged skbs
as noted by Sashiko.
Hui Peng (2):
af_unix: decrement u->inq_len when skipping unread OOB skb in manage_oob()
af_unix: skip consumed OOB skb and pull consumed bytes in unix_stream_read_skb()
net/unix/af_unix.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH net v2 1/2] af_unix: decrement u->inq_len when skipping unread OOB skb in manage_oob() 2026-09-24 7:16 [PATCH net v2 0/2] af_unix: fix inq_len accounting and consumed OOB skb handling in unix_stream_read_skb() Hui Peng @ 2026-09-24 7:16 ` Hui Peng 2026-09-24 7:16 ` [PATCH net v2 2/2] af_unix: skip consumed OOB skb and pull consumed bytes in unix_stream_read_skb() Hui Peng 1 sibling, 0 replies; 5+ messages in thread From: Hui Peng @ 2026-09-24 7:16 UTC (permalink / raw) To: kuniyu, edumazet, davem, kuba, pabeni Cc: netdev, linux-kernel, stable, Hui Peng When a normal in-band read on an AF_UNIX stream socket (without MSG_PEEK and without SO_OOBINLINE) encounters an unread u->oob_skb in manage_oob(), manage_oob() clears u->oob_skb, unlinks the 1-byte skb from sk->sk_receive_queue, and drops it with SKB_DROP_REASON_UNIX_SKIP_OOB without decrementing u->inq_len. Because queue_oob() incremented u->inq_len by 1 when queuing the OOB skb, u->inq_len remains permanently inflated by 1 byte for each skipped unread OOB skb, causing SIOCINQ / FIONREAD to report a stale positive byte count on an empty socket. Decrement u->inq_len by 1 when unlinking the unread OOB skb in manage_oob(). Tested in QEMU against Linux 7.3.0-rc3 by sending three 1-byte MSG_OOB packets interleaved with normal stream data on an AF_UNIX SOCK_STREAM socketpair and draining all in-band data via recv(): on the unfixed kernel, ioctl(SIOCINQ) reports 3 on the empty socket; with this patch applied, ioctl(SIOCINQ) reports 0. Fixes: f4e1fb04c123 ("af_unix: Use cached value for SOCK_STREAM in unix_inq_len().") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Hui Peng <benquike@gmail.com> --- Changes in v2: - Split the manage_oob() and unix_stream_read_skb() fixes into a 2-patch series as requested by Kuniyuki Iwashima. - Update Fixes: tag to f4e1fb04c123 ("af_unix: Use cached value for SOCK_STREAM in unix_inq_len().") and clarify the commit message as noted by Sashiko. net/unix/af_unix.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 42cffeafc8c1..1770af3c2684 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -2849,6 +2849,7 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sk_buff **last, WRITE_ONCE(u->oob_skb, NULL); if (!sock_flag(sk, SOCK_URGINLINE)) { + WRITE_ONCE(u->inq_len, u->inq_len - 1); __skb_unlink(skb, &sk->sk_receive_queue); unread_skb = skb; skb = skb_peek(&sk->sk_receive_queue); -- 2.55.0.1082.g2b9226bbc0-goog ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH net v2 2/2] af_unix: skip consumed OOB skb and pull consumed bytes in unix_stream_read_skb() 2026-09-24 7:16 [PATCH net v2 0/2] af_unix: fix inq_len accounting and consumed OOB skb handling in unix_stream_read_skb() Hui Peng 2026-09-24 7:16 ` [PATCH net v2 1/2] af_unix: decrement u->inq_len when skipping unread OOB skb in manage_oob() Hui Peng @ 2026-09-24 7:16 ` Hui Peng 1 sibling, 0 replies; 5+ messages in thread From: Hui Peng @ 2026-09-24 7:16 UTC (permalink / raw) To: kuniyu, edumazet, davem, kuba, pabeni Cc: netdev, linux-kernel, stable, Hui Peng When an OOB byte is consumed via recv(MSG_OOB) in unix_stream_recv_urg(), u->oob_skb is cleared to NULL and UNIXCB(oob_skb).consumed is incremented to 1, but oob_skb remains on sk->sk_receive_queue (with unix_skb_len(skb) == 0) to preserve the OOB mark until normal reads advance past it. Similarly, a partial recv() in unix_stream_read_generic() advances UNIXCB(skb).consumed without pulling the skb header and leaves the partially consumed skb at the head of sk->sk_receive_queue. If the socket is subsequently read via unix_stream_read_skb() (used by BPF sockmap), unix_stream_read_skb() only checks skb == u->oob_skb (which is only true for an unconsumed OOB skb) and ignores UNIXCB(skb).consumed. As a result, a consumed OOB skb (unix_skb_len(skb) == 0) is handed to recv_actor() and re-delivers the already consumed OOB byte, and a partially consumed skb re-delivers its already consumed prefix. In unix_stream_read_skb(), skip and free zero-length consumed skbs (after calling unix_orphan_scm() so SCM_RIGHTS fd accounting remains balanced) and pull UNIXCB(skb).consumed bytes via pskb_pull() (which safely handles both linear and non-linear paged skbs) before invoking recv_actor(). Tested in QEMU against Linux 7.3.0-rc3 with BPF_MAP_TYPE_SOCKMAP and a BPF_SK_SKB_STREAM_VERDICT program: 1. Consuming a 1-byte MSG_OOB packet ("Z") before inserting the socket into sockmap and sending "HELLO" re-delivers "ZHELLO" on the unfixed kernel, whereas with this patch applied recv() receives "HELLO!". 2. Consuming a 3-byte prefix ("123") of "12345678" before inserting the socket into sockmap re-delivers "12345678" on the unfixed kernel, whereas with this patch applied recv() receives "45678". Fixes: 77462de14a43 ("af_unix: Add read_sock for stream socket types") Fixes: 314001f0bf92 ("af_unix: Add OOB support") Fixes: 638f32604385 ("af_unix: Disable MSG_OOB handling for sockets in sockmap/sockhash") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Hui Peng <benquike@gmail.com> --- Changes in v2: - Split out from the manage_oob() fix into patch 2/2 as requested by Kuniyuki Iwashima. - Call unix_orphan_scm(sk, skb) before consume_skb(skb) when dropping a zero-length consumed skb so u->scm_stat.nr_fds is decremented, and use pskb_pull() instead of skb_pull() to safely handle non-linear paged skbs without hitting BUG() in __skb_pull(), as noted by Sashiko. net/unix/af_unix.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 1770af3c2684..f5d64e7b5c1c 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -2885,6 +2885,7 @@ static int unix_stream_read_skb(struct sock *sk, skb_read_actor_t recv_actor) return err; mutex_lock(&u->iolock); +again: spin_lock(&queue->lock); skb = __skb_dequeue(queue); @@ -2894,6 +2895,13 @@ static int unix_stream_read_skb(struct sock *sk, skb_read_actor_t recv_actor) return -EAGAIN; } + if (!unix_skb_len(skb)) { + spin_unlock(&queue->lock); + unix_orphan_scm(sk, skb); + consume_skb(skb); + goto again; + } + WRITE_ONCE(u->inq_len, u->inq_len - unix_skb_len(skb)); #if IS_ENABLED(CONFIG_AF_UNIX_OOB) @@ -2913,6 +2921,14 @@ static int unix_stream_read_skb(struct sock *sk, skb_read_actor_t recv_actor) mutex_unlock(&u->iolock); + if (UNIXCB(skb).consumed) { + if (!pskb_pull(skb, UNIXCB(skb).consumed)) { + kfree_skb(skb); + return -ENOMEM; + } + UNIXCB(skb).consumed = 0; + } + return recv_actor(sk, skb); } -- 2.55.0.1082.g2b9226bbc0-goog ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] af_unix: fix u->inq_len accounting in manage_oob() and unix_stream_read_skb()
@ 2026-09-20 19:27 Kuniyuki Iwashima
2026-09-21 5:48 ` [PATCH net v2 1/2] af_unix: decrement u->inq_len when skipping unread OOB skb in manage_oob() Hui Peng
0 siblings, 1 reply; 5+ messages in thread
From: Kuniyuki Iwashima @ 2026-09-20 19:27 UTC (permalink / raw)
To: Hui Peng; +Cc: davem, edumazet, kuba, pabeni, horms, netdev, linux-kernel
On Sat, Sep 19, 2026 at 3:17 PM Hui Peng <benquike@gmail.com> wrote:
>
> When an old OOB skb is replaced and discarded in manage_oob(), or when a
> fully consumed OOB skb is skipped in unix_stream_read_skb(), the
> discarded byte count is not subtracted from u->inq_len (or is subtracted
> inconsistently), causing SIOCINQ / FIONREAD to report stale positive
> byte counts on an empty AF_UNIX stream socket. Properly account
> u->inq_len when dropping or skipping consumed OOB skbs.
>
> Fixes: 314001f0bf92 ("af_unix: Add OOB support")
> Assisted-by: LLM
Please tell your LLM not to mix different fixes into one.
btw I'm tempted to remove OOB support entirely.
---
pw-bot: cr
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH net v2 1/2] af_unix: decrement u->inq_len when skipping unread OOB skb in manage_oob() 2026-09-20 19:27 [PATCH] af_unix: fix u->inq_len accounting in manage_oob() and unix_stream_read_skb() Kuniyuki Iwashima @ 2026-09-21 5:48 ` Hui Peng 2026-09-21 5:48 ` [PATCH net v2 2/2] af_unix: skip consumed OOB skb and pull consumed bytes in unix_stream_read_skb() Hui Peng 0 siblings, 1 reply; 5+ messages in thread From: Hui Peng @ 2026-09-21 5:48 UTC (permalink / raw) To: kuniyu, davem, edumazet, kuba, pabeni Cc: horms, willemb, mhal, jakub, netdev, linux-kernel, stable, benquike When a normal in-band read on an AF_UNIX stream socket (without MSG_PEEK and without SO_OOBINLINE) encounters an unread u->oob_skb in manage_oob(), manage_oob() clears u->oob_skb, unlinks the 1-byte skb from sk->sk_receive_queue, and drops it with SKB_DROP_REASON_UNIX_SKIP_OOB without decrementing u->inq_len. Because queue_oob() incremented u->inq_len by 1 when queuing the OOB skb, u->inq_len remains permanently inflated by 1 byte for each skipped unread OOB skb, causing SIOCINQ / FIONREAD to report a stale positive byte count on an empty socket. Decrement u->inq_len by 1 when unlinking the unread OOB skb in manage_oob(). Tested in QEMU against Linux 7.3.0-rc3 by sending three 1-byte MSG_OOB packets interleaved with normal stream data on an AF_UNIX SOCK_STREAM socketpair and draining all in-band data via recv(): on the unfixed kernel, ioctl(SIOCINQ) reports 3 on the empty socket; with this patch applied, ioctl(SIOCINQ) reports 0. Fixes: f4e1fb04c123 ("af_unix: Use cached value for SOCK_STREAM in unix_inq_len().") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Hui Peng <benquike@gmail.com> --- Changes in v2: - Split the manage_oob() and unix_stream_read_skb() fixes into a 2-patch series as requested by Kuniyuki Iwashima. - Update Fixes: tag to f4e1fb04c123 ("af_unix: Use cached value for SOCK_STREAM in unix_inq_len().") and clarify the commit message as noted by Sashiko. net/unix/af_unix.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 42cffeafc8c1..1770af3c2684 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -2849,6 +2849,7 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sk_buff **last, WRITE_ONCE(u->oob_skb, NULL); if (!sock_flag(sk, SOCK_URGINLINE)) { + WRITE_ONCE(u->inq_len, u->inq_len - 1); __skb_unlink(skb, &sk->sk_receive_queue); unread_skb = skb; skb = skb_peek(&sk->sk_receive_queue); -- 2.49.0 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH net v2 2/2] af_unix: skip consumed OOB skb and pull consumed bytes in unix_stream_read_skb() 2026-09-21 5:48 ` [PATCH net v2 1/2] af_unix: decrement u->inq_len when skipping unread OOB skb in manage_oob() Hui Peng @ 2026-09-21 5:48 ` Hui Peng 2026-09-22 5:48 ` netdev-bot+sashiko 0 siblings, 1 reply; 5+ messages in thread From: Hui Peng @ 2026-09-21 5:48 UTC (permalink / raw) To: kuniyu, davem, edumazet, kuba, pabeni Cc: horms, willemb, mhal, jakub, netdev, linux-kernel, stable, benquike When an OOB byte is consumed via recv(MSG_OOB) in unix_stream_recv_urg(), u->oob_skb is cleared to NULL and UNIXCB(oob_skb).consumed is incremented to 1, but oob_skb remains on sk->sk_receive_queue (with unix_skb_len(skb) == 0) to preserve the OOB mark until normal reads advance past it. Similarly, a partial recv() in unix_stream_read_generic() advances UNIXCB(skb).consumed without pulling the skb header and leaves the partially consumed skb at the head of sk->sk_receive_queue. If the socket is subsequently read via unix_stream_read_skb() (used by BPF sockmap), unix_stream_read_skb() only checks skb == u->oob_skb (which is only true for an unconsumed OOB skb) and ignores UNIXCB(skb).consumed. As a result, a consumed OOB skb (unix_skb_len(skb) == 0) is handed to recv_actor() and re-delivers the already consumed OOB byte, and a partially consumed skb re-delivers its already consumed prefix. In unix_stream_read_skb(), skip and free zero-length consumed skbs (after calling unix_orphan_scm() so SCM_RIGHTS fd accounting remains balanced) and pull UNIXCB(skb).consumed bytes via pskb_pull() (which safely handles both linear and non-linear paged skbs) before invoking recv_actor(). Tested in QEMU against Linux 7.3.0-rc3 with BPF_MAP_TYPE_SOCKMAP and a BPF_SK_SKB_STREAM_VERDICT program: 1. Consuming a 1-byte MSG_OOB packet ("Z") before inserting the socket into sockmap and sending "HELLO" re-delivers "ZHELLO" on the unfixed kernel, whereas with this patch applied recv() receives "HELLO!". 2. Consuming a 3-byte prefix ("123") of "12345678" before inserting the socket into sockmap re-delivers "12345678" on the unfixed kernel, whereas with this patch applied recv() receives "45678". Fixes: 77462de14a43 ("af_unix: Add read_sock for stream socket types") Fixes: 314001f0bf92 ("af_unix: Add OOB support") Fixes: 638f32604385 ("af_unix: Disable MSG_OOB handling for sockets in sockmap/sockhash") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Hui Peng <benquike@gmail.com> --- Changes in v2: - Split out from the manage_oob() fix into patch 2/2 as requested by Kuniyuki Iwashima. - Call unix_orphan_scm(sk, skb) before consume_skb(skb) when dropping a zero-length consumed skb so u->scm_stat.nr_fds is decremented, and use pskb_pull() instead of skb_pull() to safely handle non-linear paged skbs without hitting BUG() in __skb_pull(), as noted by Sashiko. net/unix/af_unix.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 1770af3c2684..f5d64e7b5c1c 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -2885,6 +2885,7 @@ static int unix_stream_read_skb(struct sock *sk, skb_read_actor_t recv_actor) return err; mutex_lock(&u->iolock); +again: spin_lock(&queue->lock); skb = __skb_dequeue(queue); @@ -2894,6 +2895,13 @@ static int unix_stream_read_skb(struct sock *sk, skb_read_actor_t recv_actor) return -EAGAIN; } + if (!unix_skb_len(skb)) { + spin_unlock(&queue->lock); + unix_orphan_scm(sk, skb); + consume_skb(skb); + goto again; + } + WRITE_ONCE(u->inq_len, u->inq_len - unix_skb_len(skb)); #if IS_ENABLED(CONFIG_AF_UNIX_OOB) @@ -2913,6 +2921,14 @@ static int unix_stream_read_skb(struct sock *sk, skb_read_actor_t recv_actor) mutex_unlock(&u->iolock); + if (UNIXCB(skb).consumed) { + if (!pskb_pull(skb, UNIXCB(skb).consumed)) { + kfree_skb(skb); + return -ENOMEM; + } + UNIXCB(skb).consumed = 0; + } + return recv_actor(sk, skb); } -- 2.49.0 ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net v2 2/2] af_unix: skip consumed OOB skb and pull consumed bytes in unix_stream_read_skb() 2026-09-21 5:48 ` [PATCH net v2 2/2] af_unix: skip consumed OOB skb and pull consumed bytes in unix_stream_read_skb() Hui Peng @ 2026-09-22 5:48 ` netdev-bot+sashiko 0 siblings, 0 replies; 5+ messages in thread From: netdev-bot+sashiko @ 2026-09-22 5:48 UTC (permalink / raw) To: benquike Cc: kuniyu, davem, edumazet, kuba, pabeni, horms, willemb, mhal, jakub, netdev, linux-kernel, stable Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider. Critical: 0 · High: 1 · Medium: 0 (1) · Low: 0 If you believe none of the issues are legitimate, please reply to each issue of Medium severity or higher and explain why the AI is wrong. If any of them are legitimate and you plan to respin, please let patchwork know by including "pw-bot: cr" as a separate line at the end of your reply (one such reply per series is enough). - [High] net/unix/af_unix.c, unix_stream_read_skb(): the newly added pull block frees the whole SKB and returns -ENOMEM when pskb_pull(skb,… Pre-existing issues: - [Medium] Unbalanced u->scm_stat.nr_fds accounting on AF_UNIX skb drop paths. -- af_unix: skip consumed OOB skb and pull consumed bytes in unix_stream_read_skb() This changes unix_stream_read_skb() to drop zero-length skbs left behind after an OOB byte was consumed, and to pull UNIXCB(skb).consumed bytes off a partially consumed skb before handing it to recv_actor(). Without this, sockmap readers re-deliver bytes that a previous recv() already consumed. > diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c > index 0903bd587696..a1c06b9995c7 100644 > --- a/net/unix/af_unix.c > +++ b/net/unix/af_unix.c > @@ -2885,6 +2885,7 @@ static int unix_stream_read_skb(struct sock *sk, skb_read_actor_t recv_actor) > return err; > > mutex_lock(&u->iolock); > +again: > spin_lock(&queue->lock); > > skb = __skb_dequeue(queue); > @@ -2894,6 +2895,13 @@ static int unix_stream_read_skb(struct sock *sk, skb_read_actor_t recv_actor) > return -EAGAIN; > } > > + if (!unix_skb_len(skb)) { > + spin_unlock(&queue->lock); > + unix_orphan_scm(sk, skb); > + consume_skb(skb); > + goto again; > + } > + [Severity: Medium] This isn't a bug introduced by this patch, but the new block here uses the correct pairing (unix_orphan_scm() before consume_skb()) while several neighbouring free paths for the same class of skb do not, so it highlights an existing imbalance in u->scm_stat.nr_fds. scm_stat_del(), reached only from unix_orphan_scm(), is the only place that does the matching decrement: net/unix/af_unix.c:scm_stat_del() { ... if (unlikely(fp && fp->count)) { atomic_sub(fp->count, &u->scm_stat.nr_fds); unix_del_edges(fp); } ... } unix_destruct_scm() -> unix_detach_fds() -> unix_destroy_fpl() releases the files and the GC edges but never touches nr_fds. The OOB drop branch a few lines below in this same function frees a skb that may still carry UNIXCB(skb).fp without going through unix_orphan_scm(): if (skb == u->oob_skb) { WRITE_ONCE(u->oob_skb, NULL); spin_unlock(&queue->lock); mutex_unlock(&u->iolock); kfree_skb_reason(skb, SKB_DROP_REASON_UNIX_SKIP_OOB); return -EAGAIN; } manage_oob() does the same with a bare consume_skb(read_skb) / kfree_skb_reason(unread_skb), and unix_stream_recv_urg() frees a zero-length predecessor with consume_skb(read_skb). unix_stream_recv_urg() is also what creates the zero-length-with-fds state: it copies the OOB byte and bumps UNIXCB(oob_skb).consumed without detaching fds, so the leftover skb can still hold SCM_RIGHTS charged earlier by scm_stat_add() in queue_oob(). Should those paths also call unix_orphan_scm() so the nr_fds charge reported as scm_fds: in /proc/<pid>/fdinfo does not stay permanently inflated? > WRITE_ONCE(u->inq_len, u->inq_len - unix_skb_len(skb)); > > #if IS_ENABLED(CONFIG_AF_UNIX_OOB) > @@ -2913,6 +2921,14 @@ static int unix_stream_read_skb(struct sock *sk, skb_read_actor_t recv_actor) > > mutex_unlock(&u->iolock); > > + if (UNIXCB(skb).consumed) { > + if (!pskb_pull(skb, UNIXCB(skb).consumed)) { > + kfree_skb(skb); > + return -ENOMEM; > + } > + UNIXCB(skb).consumed = 0; > + } > + [Severity: High] Can this kfree_skb() discard unread stream bytes? At this point in unix_stream_read_skb() the skb has already been unlinked by __skb_dequeue(), and u->inq_len has already been reduced: WRITE_ONCE(u->inq_len, u->inq_len - unix_skb_len(skb)); so once the skb is freed the remaining unix_skb_len(skb) bytes are neither recoverable nor still accounted for in the queue length. The commit message describes pskb_pull() as the way to "safely handle both linear and non-linear paged skbs", but it can still fail. For a pull past the linear head it goes pskb_pull() -> pskb_may_pull() -> __pskb_pull_tail() -> pskb_expand_head(): net/core/skbuff.c:__pskb_pull_tail() { ... if (eat > 0 || skb_cloned(skb)) { if (pskb_expand_head(skb, 0, eat > 0 ? eat + 128 : 0, GFP_ATOMIC)) return NULL; } ... } unix_stream_sendmsg() produces exactly the skbs that reach that branch: net/unix/af_unix.c:unix_stream_sendmsg() { ... data_len = max_t(int, 0, size - SKB_MAX_HEAD(0)); data_len = min_t(size_t, size, PAGE_ALIGN(data_len)); skb = sock_alloc_send_pskb(sk, size - data_len, data_len, ...); ... } MSG_SPLICE_PAGES skbs have skb_headlen() == 0 entirely, so any partial recv() leaves UNIXCB(skb).consumed beyond the linear head and forces the fallible path with a GFP_ATOMIC expansion of up to the full frag size. The return value also does not appear to reach anyone who can retry: net/core/skmsg.c:sk_psock_verdict_data_ready() { ... copied = ops->read_skb(sk, sk_psock_verdict_recv); if (copied >= 0) { ... sk_psock_data_ready(sk, psock); } ... } The -ENOMEM is swallowed, sk_psock_data_ready() is skipped for data still queued behind the dropped skb, and the sockmap consumer sees a hole in an ordered byte stream with no error reported to userspace. Would it be better to restore the state on failure, for example __skb_queue_head() plus adding unix_skb_len(skb) back to u->inq_len, and let the caller come back later, instead of freeing the skb? > return recv_actor(sk, skb); > } > -- Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260921054823.1822122-1-benquike%40gmail.com ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-09-24 7:16 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-09-24 7:16 [PATCH net v2 0/2] af_unix: fix inq_len accounting and consumed OOB skb handling in unix_stream_read_skb() Hui Peng 2026-09-24 7:16 ` [PATCH net v2 1/2] af_unix: decrement u->inq_len when skipping unread OOB skb in manage_oob() Hui Peng 2026-09-24 7:16 ` [PATCH net v2 2/2] af_unix: skip consumed OOB skb and pull consumed bytes in unix_stream_read_skb() Hui Peng -- strict thread matches above, loose matches on Subject: below -- 2026-09-20 19:27 [PATCH] af_unix: fix u->inq_len accounting in manage_oob() and unix_stream_read_skb() Kuniyuki Iwashima 2026-09-21 5:48 ` [PATCH net v2 1/2] af_unix: decrement u->inq_len when skipping unread OOB skb in manage_oob() Hui Peng 2026-09-21 5:48 ` [PATCH net v2 2/2] af_unix: skip consumed OOB skb and pull consumed bytes in unix_stream_read_skb() Hui Peng 2026-09-22 5:48 ` netdev-bot+sashiko
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®