* [PATCH net] net/smc: do not credit bytes that splice() did not take
@ 2026-08-20 8:55 Hidayath Khan
2026-08-21 8:56 ` sashiko-bot
0 siblings, 1 reply; 2+ messages in thread
From: Hidayath Khan @ 2026-08-20 8:55 UTC (permalink / raw)
To: alibuda, dust.li, sidraya, mjambigi, andrew+netdev
Cc: tonylu, guwen, davem, edumazet, kuba, pabeni, horms, pasic,
hidayath, linux-s390, netdev, linux-rdma
smc_rx_recvmsg() offers a chunk of the RMB to splice_to_pipe() and then
credits the whole chunk regardless of what was taken.
splice_to_pipe() takes only what the pipe has room for. A short count and
a zero count are both non-negative, so both fall through as success: the
call returns more than it delivered, and the consumer cursor and
bytes_to_rcv are advanced by copylen rather than by what the reader
received. The skipped bytes are never handed to anyone.
A pipe that is not empty is enough to hit this; SPLICE_F_NONBLOCK on a
full pipe produces the zero case.
Account what splice_to_pipe() actually took, and stop there rather than
continuing to the second chunk of a wrapped read. When it took nothing,
return -EAGAIN instead of reporting a length that was not delivered.
Fixes: 9014db202cb7 ("smc: add support for splice()")
Cc: stable@vger.kernel.org
Reviewed-by: Sidraya Jayagond <sidraya@linux.ibm.com>
Signed-off-by: Hidayath Khan <hidayath@linux.ibm.com>
---
net/smc/smc_rx.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/net/smc/smc_rx.c b/net/smc/smc_rx.c
index 5c9e4d8b57de..d951dbe8eec3 100644
--- a/net/smc/smc_rx.c
+++ b/net/smc/smc_rx.c
@@ -488,6 +488,24 @@ int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg,
read_done = -EFAULT;
goto out;
}
+ /* splice_to_pipe() takes only what the pipe
+ * has room for, which may be less than was
+ * offered, or nothing. Account what it took
+ * and stop: crediting the whole chunk would
+ * advance the consumer past data the reader
+ * never received.
+ */
+ if (!msg && rc < chunk_len) {
+ if (!rc) {
+ if (!read_done)
+ read_done = -EAGAIN;
+ goto out;
+ }
+ copylen = chunk_len_sum - chunk_len + rc;
+ read_remaining -= rc;
+ read_done += rc;
+ break;
+ }
}
read_remaining -= chunk_len;
read_done += chunk_len;
base-commit: d3083202a78cd0040be6a88953f728b0d3db1990
--
2.52.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH net] net/smc: do not credit bytes that splice() did not take
2026-08-20 8:55 [PATCH net] net/smc: do not credit bytes that splice() did not take Hidayath Khan
@ 2026-08-21 8:56 ` sashiko-bot
0 siblings, 0 replies; 2+ messages in thread
From: sashiko-bot @ 2026-08-21 8:56 UTC (permalink / raw)
To: Hidayath Khan
Cc: linux-s390, Heiko Carstens, Alexander Gordeev,
Christian Borntraeger, Vasily Gorbik
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] Error paths and early exits during the second chunk of a wrapped read skip trailing socket state updates, causing data duplication and leaking `bytes_to_rcv`.
- [High] The patch fails to handle a full pipe correctly, introducing dead code because `splice_to_pipe()` returns `-EAGAIN`, which is intercepted by the preexisting `rc < 0` handler and mapped to `-EFAULT`.
--
--- Patch [1]: [PATCH net] net/smc: do not credit bytes that splice() did not take ---
commit 13a906bee6c672b72e5c22c2fd7111bc713c0c62
Author: Hidayath Khan <hidayath@linux.ibm.com>
net/smc: do not credit bytes that splice() did not take
This patch modifies smc_rx_recvmsg() to account for the actual number of
bytes consumed by splice_to_pipe(). It prevents advancing the consumer cursor
when splice_to_pipe() takes less data than offered, and stops processing
if the pipe is full.
> A pipe that is not empty is enough to hit this; SPLICE_F_NONBLOCK on a
> full pipe produces the zero case.
>
> Account what splice_to_pipe() actually took, and stop there rather than
> continuing to the second chunk of a wrapped read. When it took nothing,
> return -EAGAIN instead of reporting a length that was not delivered.
Is this description accurate?
splice_to_pipe() natively returns -EAGAIN when the pipe is full and the call
is non-blocking. Since -EAGAIN is negative, it gets intercepted by the
pre-existing error handler which maps it to -EFAULT when read_done is 0.
Does this mean the zero-case handling added in this patch is unreachable?
> diff --git a/net/smc/smc_rx.c b/net/smc/smc_rx.c
> index 5c9e4d8b57de4..d951dbe8eec3c 100644
> --- a/net/smc/smc_rx.c
> +++ b/net/smc/smc_rx.c
> @@ -488,6 +488,24 @@ int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg,
> read_done = -EFAULT;
> goto out;
> }
[Severity: High]
This isn't a bug introduced by this patch, but does this error handler
unintentionally map -EAGAIN to -EFAULT?
If smc_rx_splice() returns -EAGAIN on a full pipe, this block catches the
negative return value and changes it to -EFAULT when read_done is 0,
completely bypassing the new logic below.
> + /* splice_to_pipe() takes only what the pipe
> + * has room for, which may be less than was
> + * offered, or nothing. Account what it took
> + * and stop: crediting the whole chunk would
> + * advance the consumer past data the reader
> + * never received.
> + */
> + if (!msg && rc < chunk_len) {
> + if (!rc) {
> + if (!read_done)
> + read_done = -EAGAIN;
> + goto out;
> + }
[Severity: High]
This is a pre-existing issue, but does using 'goto out' here skip trailing
socket state updates?
If a ring buffer wrap occurs requiring two chunks, and the first chunk is
successfully processed (read_done > 0), but the second chunk encounters an
error or returns 0, jumping to 'out' bypasses the batched cursor update:
net/smc/smc_rx.c:smc_rx_recvmsg() {
...
/* update cursors */
if (!(flags & MSG_PEEK)) {
...
atomic_sub(copylen, &conn->bytes_to_rcv);
...
if (msg && smc_rx_update_consumer(smc, cons, copylen))
goto out;
}
...
}
Does this leave the socket state permanently corrupted by leaking
bytes_to_rcv and duplicating data on the next read?
> + copylen = chunk_len_sum - chunk_len + rc;
> + read_remaining -= rc;
> + read_done += rc;
> + break;
> + }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260820085543.967490-1-hidayath@linux.ibm.com?part=1
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-08-21 8:56 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-20 8:55 [PATCH net] net/smc: do not credit bytes that splice() did not take Hidayath Khan
2026-08-21 8:56 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox