All of lore.kernel.org
 help / color / mirror / Atom feed
From: netdev-bot+sashiko@kernel.org
To: kuniyu@google.com
Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, horms@kernel.org, fahad@codepure.com,
	kuni1840@gmail.com, netdev@vger.kernel.org
Subject: Re: [PATCH v1 net 2/3] af_unix: Return immediately when manage_oob() returns NULL for 0-length buffer.
Date: Fri, 04 Sep 2026 08:25:13 +0000	[thread overview]
Message-ID: <178851031352.4131868.6534018713303595286@kernel.org> (raw)
In-Reply-To: <20260902202202.892676-3-kuniyu@google.com>

Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider:

Critical: 0 · High: 0 · Medium: 1 · Low: 0

- [Medium] Zero-size early return is placed after the queue-mutating
  manage_oob() call: recv(fd, buf, 0, 0) (zero-length, no MSG_PEEK) on…

--

af_unix: Return immediately when manage_oob() returns NULL for 0-length buffer.

This makes unix_stream_read_generic() break out of the receive loop when
manage_oob() returns NULL and the user supplied a zero-length buffer, so a
blocking recv() with a trailing MSG_OOB skb no longer busy-waits.  The stated
goal is to match TCP, which returns 0 immediately in that situation.

> diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
> index 6861370062df..2da1017f8873 100644
> --- a/net/unix/af_unix.c
> +++ b/net/unix/af_unix.c
> @@ -2976,7 +2976,7 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
>  #if IS_ENABLED(CONFIG_AF_UNIX_OOB)
>  		if (skb) {
>  			skb = manage_oob(skb, &last, sk, flags, copied);
> -			if (!skb && copied) {
> +			if (!skb && (copied || !state->size)) {

[Severity: Medium]
The new !state->size condition applies to every zero-length read, not only
the MSG_PEEK case described in the commit message.  Since it is evaluated
after manage_oob() has already run, does a plain recv(fd, buf, 0, 0) now
destroy the pending OOB byte and still report success?

With queue == [oob skb] and SO_OOBINLINE off, manage_oob() takes the
non-peek branch:

net/unix/af_unix.c:manage_oob() {
	...
	} else if (!(flags & MSG_PEEK)) {
		WRITE_ONCE(u->oob_skb, NULL);

		if (!sock_flag(sk, SOCK_URGINLINE)) {
			__skb_unlink(skb, &sk->sk_receive_queue);
			unread_skb = skb;
			skb = skb_peek(&sk->sk_receive_queue);
			*last = skb;
		}
	...
unlock:
	...
	kfree_skb_reason(unread_skb, SKB_DROP_REASON_UNIX_SKIP_OOB);

	return skb;
}

so u->oob_skb is cleared and the byte is freed before the caller ever looks
at state->size.  The loop then breaks and unix_stream_read_generic() returns
0, after which recv(MSG_OOB) returns -EINVAL and SIOCATMARK/EPOLLPRI report
no urgent data.

The commit message says:

    In such a situation, TCP returns 0 immediately regardless of
    blocking or non-blocking.

    Let's follow the behaviour.

Is that comparison exact for the non-peek case?  In tcp_recvmsg_locked() the
found_ok_skb path computes:

net/ipv4/tcp.c:tcp_recvmsg_locked() {
	...
	used = skb->len - offset;
	if (len < used)
		used = len;

	if (unlikely(tp->urg_data)) {
		u32 urg_offset = tp->urg_seq - *seq;
		if (urg_offset < used) {
	...
}

With len == 0 used is 0, so the urgent-skip is not taken and tp->urg_data
survives the zero-length read.  TCP returns 0 without consuming or
invalidating the urgent byte, while AF_UNIX now returns 0 having dropped it.

Would it be equivalent, and non-destructive, to test the zero-length case
before manage_oob() mutates the queue, e.g. break out when
skb && !state->size, so the empty-queue case still blocks the same way as
TCP?

One more note on the selftest added later in this series:

tools/testing/selftests/net/af_unix/msg_oob.c:zero_buf_oob() {
	sendpair("a", 1, MSG_OOB);
	recvpair("", 0, 0, 0);
}

This exercises exactly the destructive non-peek path, but only compares
return values with TCP, so the difference in the resulting socket state is
not detected.

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260902202202.892676-1-kuniyu%40google.com

  reply	other threads:[~2026-09-04  8:25 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-02 20:21 [PATCH v1 net 0/3] af_unix: Minor fixes for MSG_OOB and MSG_PEEK Kuniyuki Iwashima
2026-09-02 20:21 ` [PATCH v1 net 1/3] af_unix: Update last skb marker in manage_oob() Kuniyuki Iwashima
2026-09-04  8:25   ` netdev-bot+sashiko
2026-09-07 23:56     ` Kuniyuki Iwashima
2026-09-02 20:21 ` [PATCH v1 net 2/3] af_unix: Return immediately when manage_oob() returns NULL for 0-length buffer Kuniyuki Iwashima
2026-09-04  8:25   ` netdev-bot+sashiko [this message]
2026-09-08  0:02     ` Kuniyuki Iwashima
2026-09-02 20:21 ` [PATCH v1 net 3/3] selftest: af_unix: Add zero-buffer test for msg_oob.c Kuniyuki Iwashima
2026-09-04  8:25   ` netdev-bot+sashiko
2026-09-08  0:10 ` [PATCH v1 net 0/3] af_unix: Minor fixes for MSG_OOB and MSG_PEEK patchwork-bot+netdevbpf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=178851031352.4131868.6534018713303595286@kernel.org \
    --to=netdev-bot+sashiko@kernel.org \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=fahad@codepure.com \
    --cc=horms@kernel.org \
    --cc=kuba@kernel.org \
    --cc=kuni1840@gmail.com \
    --cc=kuniyu@google.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.