public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] net: datagram: Drain queue before reporting EOF or ENOTCONN
@ 2026-04-28  5:23 Petr Malat
  2026-04-28  5:58 ` Kuniyuki Iwashima
  0 siblings, 1 reply; 4+ messages in thread
From: Petr Malat @ 2026-04-28  5:23 UTC (permalink / raw)
  To: netdev, linux-kernel; +Cc: davem, kuba, ebiggers, Petr Malat

If a packet is queued and RCV_SHUTDOWN flag is set after the function
__skb_wait_for_more_packets() checked the queue, the function returns
EOF, which is then propagated by __unix_dgram_recvmsg() and the user
reads EOF although there is a message or messages still pending.

The function should check if the queue is empty before returning EOF.
As the same is true for disconnect and it's also reasonable for a pending
signal, check in a common place before returning from the function.

Signed-off-by: Petr Malat <oss@malat.biz>
---
 net/core/datagram.c | 38 +++++++++++++++++++++-----------------
 1 file changed, 21 insertions(+), 17 deletions(-)

diff --git a/net/core/datagram.c b/net/core/datagram.c
index c285c6465923..5952950f7233 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -98,40 +98,44 @@ int __skb_wait_for_more_packets(struct sock *sk,
struct sk_buff_head *queue,
 	/* Socket errors? */
 	error = sock_error(sk);
 	if (error)
-		goto out_err;
+		goto out;

 	if (READ_ONCE(queue->prev) != skb)
 		goto out;

 	/* Socket shut down? */
-	if (sk->sk_shutdown & RCV_SHUTDOWN)
-		goto out_noerr;
+	if (sk->sk_shutdown & RCV_SHUTDOWN) {
+		error = 1;
+		goto check_queue;
+	}

 	/* Sequenced packets can come disconnected.
 	 * If so we report the problem
 	 */
-	error = -ENOTCONN;
 	if (connection_based(sk) &&
-	    !(sk->sk_state == TCP_ESTABLISHED || sk->sk_state == TCP_LISTEN))
-		goto out_err;
+	    !(sk->sk_state == TCP_ESTABLISHED || sk->sk_state == TCP_LISTEN)) {
+		error = -ENOTCONN;
+		goto check_queue;
+	}

 	/* handle signals */
-	if (signal_pending(current))
-		goto interrupted;
+	if (signal_pending(current)) {
+		error = sock_intr_errno(*timeo_p);
+		goto check_queue;
+	}

-	error = 0;
 	*timeo_p = schedule_timeout(*timeo_p);
 out:
+	*err = error < 0 ? error : 0;
 	finish_wait(sk_sleep(sk), &wait);
 	return error;
-interrupted:
-	error = sock_intr_errno(*timeo_p);
-out_err:
-	*err = error;
-	goto out;
-out_noerr:
-	*err = 0;
-	error = 1;
+check_queue:
+	/* A packet may have arrived between the initial queue check and any
+	 * of the early-exit conditions above.  Return 0 to let the caller
+	 * drain the queue before acting on the shutdown / disconnect / signal.
+	 */
+	if (READ_ONCE(queue->prev) != skb)
+		error = 0;
 	goto out;
 }
 EXPORT_SYMBOL(__skb_wait_for_more_packets);
-- 
2.47.3

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-04-28 19:45 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-28  5:23 [PATCH] net: datagram: Drain queue before reporting EOF or ENOTCONN Petr Malat
2026-04-28  5:58 ` Kuniyuki Iwashima
2026-04-28  6:49   ` Petr Malat
2026-04-28 19:45     ` Kuniyuki Iwashima

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox