| From a2477b0e67c52f4364a47c3ad70902bc2a61bd4c Mon Sep 17 00:00:00 2001 |
| From: Andrey Ryabinin <aryabinin@virtuozzo.com> |
| Date: Tue, 17 Jul 2018 19:00:33 +0300 |
| Subject: fuse: Don't access pipe->buffers without pipe_lock() |
| |
| From: Andrey Ryabinin <aryabinin@virtuozzo.com> |
| |
| commit a2477b0e67c52f4364a47c3ad70902bc2a61bd4c upstream. |
| |
| fuse_dev_splice_write() reads pipe->buffers to determine the size of |
| 'bufs' array before taking the pipe_lock(). This is not safe as |
| another thread might change the 'pipe->buffers' between the allocation |
| and taking the pipe_lock(). So we end up with too small 'bufs' array. |
| |
| Move the bufs allocations inside pipe_lock()/pipe_unlock() to fix this. |
| |
| Fixes: dd3bb14f44a6 ("fuse: support splice() writing to fuse device") |
| Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com> |
| Cc: <stable@vger.kernel.org> # v2.6.35 |
| Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/fuse/dev.c | 7 +++++-- |
| 1 file changed, 5 insertions(+), 2 deletions(-) |
| |
| --- a/fs/fuse/dev.c |
| +++ b/fs/fuse/dev.c |
| @@ -1941,11 +1941,14 @@ static ssize_t fuse_dev_splice_write(str |
| if (!fud) |
| return -EPERM; |
| |
| + pipe_lock(pipe); |
| + |
| bufs = kmalloc(pipe->buffers * sizeof(struct pipe_buffer), GFP_KERNEL); |
| - if (!bufs) |
| + if (!bufs) { |
| + pipe_unlock(pipe); |
| return -ENOMEM; |
| + } |
| |
| - pipe_lock(pipe); |
| nbuf = 0; |
| rem = 0; |
| for (idx = 0; idx < pipe->nrbufs && rem < len; idx++) |