[RHEL7,COMMIT] ms/fuse: Fix use-after-free in fuse_dev_do_read()

Submitted by Konstantin Khorenko on Oct. 4, 2018, 9:12 a.m.


Message ID 201810040912.w949CYPo022526@finist_ce7.work
State New
Series "ms/fuse: Fix use-after-free in fuse_dev_do_read()"
Headers show

Commit Message

Konstantin Khorenko Oct. 4, 2018, 9:12 a.m.
The commit is pushed to "branch-rh7-3.10.0-862.14.4.vz7.72.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-862.14.4.vz7.72.2
commit 0f92066eef6e2a15f3ae82c882fd1b09415493ee
Author: Kirill Tkhai <ktkhai@virtuozzo.com>
Date:   Mon Oct 1 18:17:58 2018 +0300

    ms/fuse: Fix use-after-free in fuse_dev_do_read()
    We may pick freed req in this way:
    [cpu0]                                  [cpu1]
    fuse_dev_do_read()                      fuse_dev_do_write()
       list_move_tail(&req->list, ...);     ...
       spin_unlock(&fpq->lock);             ...
       ...                                  request_end(fc, req);
       ...                                    fuse_put_request(fc, req);
       if (test_bit(FR_INTERRUPTED, ...))
             queue_interrupt(fiq, req);
    Fix that by keeping req alive until we finish all manipulations.
    Reported-by: syzbot+4e975615ca01f2277bdd@syzkaller.appspotmail.com
    Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
    Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
    Fixes: 46c34a348b0a ("fuse: no fc->lock for pqueue parts")
    Cc: <stable@vger.kernel.org> # v4.2
    Patchset description:
    Relax lock contention and ms fixes
    Port some ms fixes and begin first round of relaxing fc->lock contention.
    Kirill Tkhai (5):
          fuse: Fix use-after-free in fuse_dev_do_read()
          fuse: Fix use-after-free in fuse_dev_do_write()
          fuse: use list_first_entry() in flush_bg_queue()
          fuse: use READ_ONCE on congestion_threshold and max_background
          fuse: add locking to max_background and congestion_threshold changes
    Miklos Szeredi (2):
          fuse: set FR_SENT while locked
          fuse: fix blocked_waitq wakeup
 fs/fuse/dev.c | 2 ++
 1 file changed, 2 insertions(+)

Patch hide | download patch | download mbox

diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index ba21fe75e82c..7457ce96a4e0 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1378,12 +1378,14 @@  static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
 		goto out_end;
 	list_move_tail(&req->list, &fpq->processing[fuse_req_hash(req)]);
+	__fuse_get_request(req);
 	set_bit(FR_SENT, &req->flags);
 	/* matches barrier in request_wait_answer() */
 	if (test_bit(FR_INTERRUPTED, &req->flags))
 		queue_interrupt(fiq, req);
+	fuse_put_request(fc, req);
 	return reqsize;