forked from mirrors/linux
		
	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 <ravi@prevas.dk>
Link: https://lore.kernel.org/all/878qpi5wz4.fsf@prevas.dk/
Fixes: 3d252160b8 ("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>
			
			
This commit is contained in:
		
							parent
							
								
									d810d4c27b
								
							
						
					
					
						commit
						ebb0f38bb4
					
				
					 1 changed files with 6 additions and 7 deletions
				
			
		| 
						 | 
					@ -2107,7 +2107,7 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
 | 
				
			||||||
				     struct file *out, loff_t *ppos,
 | 
									     struct file *out, loff_t *ppos,
 | 
				
			||||||
				     size_t len, unsigned int flags)
 | 
									     size_t len, unsigned int flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned int head, tail, mask, count;
 | 
						unsigned int head, tail, count;
 | 
				
			||||||
	unsigned nbuf;
 | 
						unsigned nbuf;
 | 
				
			||||||
	unsigned idx;
 | 
						unsigned idx;
 | 
				
			||||||
	struct pipe_buffer *bufs;
 | 
						struct pipe_buffer *bufs;
 | 
				
			||||||
| 
						 | 
					@ -2124,8 +2124,7 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	head = pipe->head;
 | 
						head = pipe->head;
 | 
				
			||||||
	tail = pipe->tail;
 | 
						tail = pipe->tail;
 | 
				
			||||||
	mask = pipe->ring_size - 1;
 | 
						count = pipe_occupancy(head, tail);
 | 
				
			||||||
	count = head - tail;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bufs = kvmalloc_array(count, sizeof(struct pipe_buffer), GFP_KERNEL);
 | 
						bufs = kvmalloc_array(count, sizeof(struct pipe_buffer), GFP_KERNEL);
 | 
				
			||||||
	if (!bufs) {
 | 
						if (!bufs) {
 | 
				
			||||||
| 
						 | 
					@ -2135,8 +2134,8 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nbuf = 0;
 | 
						nbuf = 0;
 | 
				
			||||||
	rem = 0;
 | 
						rem = 0;
 | 
				
			||||||
	for (idx = tail; idx != head && rem < len; idx++)
 | 
						for (idx = tail; !pipe_empty(head, idx) && rem < len; idx++)
 | 
				
			||||||
		rem += pipe->bufs[idx & mask].len;
 | 
							rem += pipe_buf(pipe, idx)->len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = -EINVAL;
 | 
						ret = -EINVAL;
 | 
				
			||||||
	if (rem < len)
 | 
						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 *ibuf;
 | 
				
			||||||
		struct pipe_buffer *obuf;
 | 
							struct pipe_buffer *obuf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (WARN_ON(nbuf >= count || tail == head))
 | 
							if (WARN_ON(nbuf >= count || pipe_empty(head, tail)))
 | 
				
			||||||
			goto out_free;
 | 
								goto out_free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ibuf = &pipe->bufs[tail & mask];
 | 
							ibuf = pipe_buf(pipe, tail);
 | 
				
			||||||
		obuf = &bufs[nbuf];
 | 
							obuf = &bufs[nbuf];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (rem >= ibuf->len) {
 | 
							if (rem >= ibuf->len) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue