Commit ebb0f38b authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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: default avatarRasmus Villemoes <ravi@prevas.dk>
Link: https://lore.kernel.org/all/878qpi5wz4.fsf@prevas.dk/


Fixes: 3d252160 ("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: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent d810d4c2
Loading
Loading
Loading
Loading
+6 −7
Original line number Diff line number Diff line
@@ -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) {