mirror of
https://github.com/torvalds/linux.git
synced 2025-11-01 00:58:39 +02:00
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