Commit 8288ba942cfd for kernel

commit 8288ba942cfd20621c05e16978b7c3da91513ae1
Author: Bryam Vargas <hexlabsecurity@proton.me>
Date:   Thu Oct 29 03:03:33 2026 -0500

    net/smc: don't spin in smc_rx_recvmsg() while a pipe holds spliced data

    While bytes spliced off the RMB are still in a pipe, recvmsg() waits
    for the pipe to release them before it copies the data behind them.
    The path to that wait skips the timeout and signal checks, and
    smc_rx_wait() returns at once on RCV_SHUTDOWN. With a signal pending,
    after SHUT_RD, or once the peer closes or shuts down writing,
    recvmsg() spins on a CPU until the pipe is drained, and SIGKILL cannot
    stop it. MSG_DONTWAIT and an expired SO_RCVTIMEO wait there too
    instead of returning -EAGAIN.

    Check the timeout and signals before that wait, and end it when the
    pipe releases the data or the connection is killed, not on RCV_SHUTDOWN.
    A zero-length read returns 0 without waiting for the pipe; a
    non-blocking one returns -EAGAIN while poll() still reports the socket
    readable (splice() can still take those bytes). The wait sets
    SOCKWQ_ASYNC_WAITDATA like smc_rx_wait(), so a byte arriving behind
    the pipe raises no SIGIO on a reader already asleep for it, and a full
    barrier orders its wait queue entry before its read of splice_pending,
    so no wake is lost.

    Fixes: 9014db202cb7 ("smc: add support for splice()")
    Cc: stable@vger.kernel.org
    Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
    Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
    Link: https://patch.msgid.link/20261029-b4-disp-da7f8e6a-v2-1-9052904adf72@proton.me
    Signed-off-by: Paolo Abeni <pabeni@redhat.com>

diff --git a/net/smc/smc_rx.c b/net/smc/smc_rx.c
index 197fddc6271f..63c178c10bf1 100644
--- a/net/smc/smc_rx.c
+++ b/net/smc/smc_rx.c
@@ -286,6 +286,27 @@ int smc_rx_wait(struct smc_sock *smc, long *timeo, size_t peeked,
 	return rc;
 }

+/* Wait for the pipe to release the spliced data. Unlike smc_rx_wait()
+ * it does not end on shutdown or sk_err, the data is already in the
+ * RMB; smc_conn_kill() wakes it and the caller checks conn->killed.
+ */
+static void smc_rx_wait_splice(struct smc_sock *smc, long *timeo)
+{
+	DEFINE_WAIT_FUNC(wait, woken_wake_function);
+	struct smc_connection *conn = &smc->conn;
+	struct sock *sk = &smc->sk;
+
+	sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
+	add_wait_queue(sk_sleep(sk), &wait);
+	/* pairs with the smp_mb() in wq_has_sleeper(): the release drops
+	 * splice_pending, then looks for a sleeper
+	 */
+	smp_mb();
+	sk_wait_event(sk, timeo, !atomic_read(&conn->splice_pending), &wait);
+	remove_wait_queue(sk_sleep(sk), &wait);
+	sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
+}
+
 static int smc_rx_recv_urg(struct smc_sock *smc, struct msghdr *msg, int len,
 			   int flags)
 {
@@ -443,7 +464,23 @@ int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg,
 		/* could be just 1 byte, even after waiting on data above */
 		readable = smc_rx_data_available(conn, peeked_bytes);
 		splbytes = atomic_read(&conn->splice_pending);
-		if (!readable || (msg && splbytes)) {
+		if (msg && splbytes) {
+			/* a pipe holds bytes ahead of these; the copy path
+			 * skips the timeout and signal checks
+			 */
+			if (!read_remaining)
+				break;
+			if (!timeo || signal_pending(current)) {
+				if (!read_done)
+					read_done = timeo ?
+						    sock_intr_errno(timeo) :
+						    -EAGAIN;
+				break;
+			}
+			smc_rx_wait_splice(smc, &timeo);
+			continue;
+		}
+		if (!readable) {
 			if (splbytes)
 				func = smc_rx_data_available_and_no_splice_pend;
 			else