]> www.infradead.org Git - users/willy/pagecache.git/commitdiff
fs/pipe: fix pipe buffer index use in FUSE
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 6 Mar 2025 17:53:25 +0000 (07:53 -1000)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 6 Mar 2025 17:53:25 +0000 (07:53 -1000)
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 <ravi@prevas.dk>
Link: https://lore.kernel.org/all/878qpi5wz4.fsf@prevas.dk/
Fixes: 3d252160b818 ("fs/pipe: Read pipe->{head,tail} atomically outside pipe->mutex")Cc: Oleg >
Cc: Mateusz Guzik <mjguzik@gmail.com>
Cc: K Prateek Nayak <kprateek.nayak@amd.com>
Cc: Swapnil Sapkal <swapnil.sapkal@amd.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
fs/fuse/dev.c

index 2b2d1b75554445bd13efd6eb96885d23cd58b4a3..3c9caafca9e29fd38fc922d6900947d2ff99064b 100644 (file)
@@ -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) {