aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <[email protected]>2025-03-06 17:53:25 +0000
committerLinus Torvalds <[email protected]>2025-03-06 17:53:25 +0000
commitebb0f38bb47f74b29e267babdbcd2c47d5292aa8 (patch)
tree08d5de22ef643daece4769b36c32ceab024c92c8
parentfs/pipe: do not open-code pipe head/tail logic in FIONREAD (diff)
downloadkernel-ebb0f38bb47f74b29e267babdbcd2c47d5292aa8.tar.gz
kernel-ebb0f38bb47f74b29e267babdbcd2c47d5292aa8.zip
fs/pipe: fix pipe buffer index use in FUSE
This was another case that Rasmus pointed out where the direct access to the pipe head and tail pointers broke on 32-bit configurations due to the type changes. As with the pipe FIONREAD case, fix it by using the appropriate helper functions that deal with the right pipe index sizing. Reported-by: Rasmus Villemoes <[email protected]> Link: https://lore.kernel.org/all/[email protected]/ Fixes: 3d252160b818 ("fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex")Cc: Oleg > Cc: Mateusz Guzik <[email protected]> Cc: K Prateek Nayak <[email protected]> Cc: Swapnil Sapkal <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
-rw-r--r--fs/fuse/dev.c13
1 files changed, 6 insertions, 7 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 2b2d1b755544..3c9caafca9e2 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -2107,7 +2107,7 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
struct file *out, loff_t *ppos,
size_t len, unsigned int flags)
{
- unsigned int head, tail, mask, count;
+ unsigned int head, tail, count;
unsigned nbuf;
unsigned idx;
struct pipe_buffer *bufs;
@@ -2124,8 +2124,7 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
head = pipe->head;
tail = pipe->tail;
- mask = pipe->ring_size - 1;
- count = head - tail;
+ count = pipe_occupancy(head, tail);
bufs = kvmalloc_array(count, sizeof(struct pipe_buffer), GFP_KERNEL);
if (!bufs) {
@@ -2135,8 +2134,8 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
nbuf = 0;
rem = 0;
- for (idx = tail; idx != head && rem < len; idx++)
- rem += pipe->bufs[idx & mask].len;
+ for (idx = tail; !pipe_empty(head, idx) && rem < len; idx++)
+ rem += pipe_buf(pipe, idx)->len;
ret = -EINVAL;
if (rem < len)
@@ -2147,10 +2146,10 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
struct pipe_buffer *ibuf;
struct pipe_buffer *obuf;
- if (WARN_ON(nbuf >= count || tail == head))
+ if (WARN_ON(nbuf >= count || pipe_empty(head, tail)))
goto out_free;
- ibuf = &pipe->bufs[tail & mask];
+ ibuf = pipe_buf(pipe, tail);
obuf = &bufs[nbuf];
if (rem >= ibuf->len) {