From: Greg Kroah-Hartman Date: Thu, 15 Nov 2018 01:07:34 +0000 (-0800) Subject: 4.9-stable patches X-Git-Tag: v4.19.3~43 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=dbb950e8cabb53a00240371e4597f0e26b9de5cf;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: fuse-fix-blocked_waitq-wakeup.patch fuse-fix-use-after-free-in-fuse_dev_do_read.patch fuse-fix-use-after-free-in-fuse_dev_do_write.patch fuse-set-fr_sent-while-locked.patch --- diff --git a/queue-4.9/fuse-fix-blocked_waitq-wakeup.patch b/queue-4.9/fuse-fix-blocked_waitq-wakeup.patch new file mode 100644 index 00000000000..ffc4b6f7d4d --- /dev/null +++ b/queue-4.9/fuse-fix-blocked_waitq-wakeup.patch @@ -0,0 +1,49 @@ +From 908a572b80f6e9577b45e81b3dfe2e22111286b8 Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Fri, 28 Sep 2018 16:43:22 +0200 +Subject: fuse: fix blocked_waitq wakeup + +From: Miklos Szeredi + +commit 908a572b80f6e9577b45e81b3dfe2e22111286b8 upstream. + +Using waitqueue_active() is racy. Make sure we issue a wake_up() +unconditionally after storing into fc->blocked. After that it's okay to +optimize with waitqueue_active() since the first wake up provides the +necessary barrier for all waiters, not the just the woken one. + +Signed-off-by: Miklos Szeredi +Fixes: 3c18ef8117f0 ("fuse: optimize wake_up") +Cc: # v3.10 +Signed-off-by: Greg Kroah-Hartman + +--- + fs/fuse/dev.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +--- a/fs/fuse/dev.c ++++ b/fs/fuse/dev.c +@@ -383,12 +383,19 @@ static void request_end(struct fuse_conn + if (test_bit(FR_BACKGROUND, &req->flags)) { + spin_lock(&fc->lock); + clear_bit(FR_BACKGROUND, &req->flags); +- if (fc->num_background == fc->max_background) ++ if (fc->num_background == fc->max_background) { + fc->blocked = 0; +- +- /* Wake up next waiter, if any */ +- if (!fc->blocked && waitqueue_active(&fc->blocked_waitq)) + wake_up(&fc->blocked_waitq); ++ } else if (!fc->blocked) { ++ /* ++ * Wake up next waiter, if any. It's okay to use ++ * waitqueue_active(), as we've already synced up ++ * fc->blocked with waiters with the wake_up() call ++ * above. ++ */ ++ if (waitqueue_active(&fc->blocked_waitq)) ++ wake_up(&fc->blocked_waitq); ++ } + + if (fc->num_background == fc->congestion_threshold && + fc->connected && fc->bdi_initialized) { diff --git a/queue-4.9/fuse-fix-use-after-free-in-fuse_dev_do_read.patch b/queue-4.9/fuse-fix-use-after-free-in-fuse_dev_do_read.patch new file mode 100644 index 00000000000..00a918cb426 --- /dev/null +++ b/queue-4.9/fuse-fix-use-after-free-in-fuse_dev_do_read.patch @@ -0,0 +1,50 @@ +From bc78abbd55dd28e2287ec6d6502b842321a17c87 Mon Sep 17 00:00:00 2001 +From: Kirill Tkhai +Date: Tue, 25 Sep 2018 12:28:55 +0300 +Subject: fuse: Fix use-after-free in fuse_dev_do_read() + +From: Kirill Tkhai + +commit bc78abbd55dd28e2287ec6d6502b842321a17c87 upstream. + +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 +Signed-off-by: Miklos Szeredi +Fixes: 46c34a348b0a ("fuse: no fc->lock for pqueue parts") +Cc: # v4.2 +Signed-off-by: Greg Kroah-Hartman + +--- + fs/fuse/dev.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/fuse/dev.c ++++ b/fs/fuse/dev.c +@@ -1303,12 +1303,14 @@ static ssize_t fuse_dev_do_read(struct f + goto out_end; + } + list_move_tail(&req->list, &fpq->processing); ++ __fuse_get_request(req); + spin_unlock(&fpq->lock); + set_bit(FR_SENT, &req->flags); + /* matches barrier in request_wait_answer() */ + smp_mb__after_atomic(); + if (test_bit(FR_INTERRUPTED, &req->flags)) + queue_interrupt(fiq, req); ++ fuse_put_request(fc, req); + + return reqsize; + diff --git a/queue-4.9/fuse-fix-use-after-free-in-fuse_dev_do_write.patch b/queue-4.9/fuse-fix-use-after-free-in-fuse_dev_do_write.patch new file mode 100644 index 00000000000..3f5c997ef40 --- /dev/null +++ b/queue-4.9/fuse-fix-use-after-free-in-fuse_dev_do_write.patch @@ -0,0 +1,60 @@ +From d2d2d4fb1f54eff0f3faa9762d84f6446a4bc5d0 Mon Sep 17 00:00:00 2001 +From: Kirill Tkhai +Date: Tue, 25 Sep 2018 12:52:42 +0300 +Subject: fuse: Fix use-after-free in fuse_dev_do_write() + +From: Kirill Tkhai + +commit d2d2d4fb1f54eff0f3faa9762d84f6446a4bc5d0 upstream. + +After we found req in request_find() and released the lock, +everything may happen with the req in parallel: + +cpu0 cpu1 +fuse_dev_do_write() fuse_dev_do_write() + req = request_find(fpq, ...) ... + spin_unlock(&fpq->lock) ... + ... req = request_find(fpq, oh.unique) + ... spin_unlock(&fpq->lock) + queue_interrupt(&fc->iq, req); ... + ... ... + ... ... + request_end(fc, req); + fuse_put_request(fc, req); + ... queue_interrupt(&fc->iq, req); + + +Signed-off-by: Kirill Tkhai +Signed-off-by: Miklos Szeredi +Fixes: 46c34a348b0a ("fuse: no fc->lock for pqueue parts") +Cc: # v4.2 +Signed-off-by: Greg Kroah-Hartman + +--- + fs/fuse/dev.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/fs/fuse/dev.c ++++ b/fs/fuse/dev.c +@@ -1868,16 +1868,20 @@ static ssize_t fuse_dev_do_write(struct + + /* Is it an interrupt reply? */ + if (req->intr_unique == oh.unique) { ++ __fuse_get_request(req); + spin_unlock(&fpq->lock); + + err = -EINVAL; +- if (nbytes != sizeof(struct fuse_out_header)) ++ if (nbytes != sizeof(struct fuse_out_header)) { ++ fuse_put_request(fc, req); + goto err_finish; ++ } + + if (oh.error == -ENOSYS) + fc->no_interrupt = 1; + else if (oh.error == -EAGAIN) + queue_interrupt(&fc->iq, req); ++ fuse_put_request(fc, req); + + fuse_copy_finish(cs); + return nbytes; diff --git a/queue-4.9/fuse-set-fr_sent-while-locked.patch b/queue-4.9/fuse-set-fr_sent-while-locked.patch new file mode 100644 index 00000000000..4781cb2cdcf --- /dev/null +++ b/queue-4.9/fuse-set-fr_sent-while-locked.patch @@ -0,0 +1,35 @@ +From 4c316f2f3ff315cb48efb7435621e5bfb81df96d Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Fri, 28 Sep 2018 16:43:22 +0200 +Subject: fuse: set FR_SENT while locked + +From: Miklos Szeredi + +commit 4c316f2f3ff315cb48efb7435621e5bfb81df96d upstream. + +Otherwise fuse_dev_do_write() could come in and finish off the request, and +the set_bit(FR_SENT, ...) could trigger the WARN_ON(test_bit(FR_SENT, ...)) +in request_end(). + +Signed-off-by: Miklos Szeredi +Reported-by: syzbot+ef054c4d3f64cd7f7cec@syzkaller.appspotmai +Fixes: 46c34a348b0a ("fuse: no fc->lock for pqueue parts") +Cc: # v4.2 +Signed-off-by: Greg Kroah-Hartman + +--- + fs/fuse/dev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/fuse/dev.c ++++ b/fs/fuse/dev.c +@@ -1311,8 +1311,8 @@ static ssize_t fuse_dev_do_read(struct f + } + list_move_tail(&req->list, &fpq->processing); + __fuse_get_request(req); +- spin_unlock(&fpq->lock); + set_bit(FR_SENT, &req->flags); ++ spin_unlock(&fpq->lock); + /* matches barrier in request_wait_answer() */ + smp_mb__after_atomic(); + if (test_bit(FR_INTERRUPTED, &req->flags)) diff --git a/queue-4.9/series b/queue-4.9/series index e2980083ea0..ad295be262a 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -15,3 +15,7 @@ powerpc-selftests-wait-all-threads-to-join.patch cdrom-fix-improper-type-cast-which-can-leat-to-information-leak.patch scsi-qla2xxx-fix-incorrect-port-speed-being-set-for-fc-adapters.patch scsi-qla2xxx-shutdown-chip-if-reset-fail.patch +fuse-fix-use-after-free-in-fuse_dev_do_read.patch +fuse-fix-use-after-free-in-fuse_dev_do_write.patch +fuse-fix-blocked_waitq-wakeup.patch +fuse-set-fr_sent-while-locked.patch