[PATCH] fs/splice: clamp an over-reported write_iter result
From: Cheng Yongkang
Date: Thu Oct 29 2026 - 10:13:11 EST
iter_file_splice_write() builds a bvec iterator of at most
sd.total_len - left bytes and passes it to ->write_iter(). It then
subtracts the returned length from sd.total_len and walks the pipe
buffers by that length. A ->write_iter() implementation that reports
more bytes than the iterator held makes sd.total_len underflow and the
dismissal loop advance pipe->tail past pipe->head, releasing a zeroed
pipe buffer:
Splice Exceeded! ret=7 tot=1 left=0
Oops: general protection fault
RIP: 0010:iter_file_splice_write+0xb6f/0x1170
Commit a3de58b12ce0 ("netfs: Fix unbuffered write error handling")
added the warning for this condition but only reports it. Clamp the
return value to the size of the iterator that was actually handed to
->write_iter(), so the pipe accounting stays consistent even when a
producer violates the iterator contract.
Fixes: 8d0207652cbe ("->splice_write() via ->write_iter()")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: LLM
Signed-off-by: Cheng Yongkang <teel4res@xxxxxxxxx>
---
fs/splice.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/fs/splice.c b/fs/splice.c
index bc243ab..3ac1d4d 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -737,9 +737,12 @@ iter_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
sd.pos = kiocb.ki_pos;
if (ret <= 0)
break;
- WARN_ONCE(ret > sd.total_len - left,
- "Splice Exceeded! ret=%zd tot=%zu left=%zu\n",
- ret, sd.total_len, left);
+ if (unlikely(ret > sd.total_len - left)) {
+ WARN_ONCE(1,
+ "Splice Exceeded! ret=%zd tot=%zu left=%zu\n",
+ ret, sd.total_len, left);
+ ret = sd.total_len - left;
+ }
sd.num_spliced += ret;
sd.total_len -= ret;
--
2.34.1