]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 15 Nov 2018 01:07:34 +0000 (17:07 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 15 Nov 2018 01:07:34 +0000 (17:07 -0800)
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

queue-4.9/fuse-fix-blocked_waitq-wakeup.patch [new file with mode: 0644]
queue-4.9/fuse-fix-use-after-free-in-fuse_dev_do_read.patch [new file with mode: 0644]
queue-4.9/fuse-fix-use-after-free-in-fuse_dev_do_write.patch [new file with mode: 0644]
queue-4.9/fuse-set-fr_sent-while-locked.patch [new file with mode: 0644]
queue-4.9/series

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 (file)
index 0000000..ffc4b6f
--- /dev/null
@@ -0,0 +1,49 @@
+From 908a572b80f6e9577b45e81b3dfe2e22111286b8 Mon Sep 17 00:00:00 2001
+From: Miklos Szeredi <mszeredi@redhat.com>
+Date: Fri, 28 Sep 2018 16:43:22 +0200
+Subject: fuse: fix blocked_waitq wakeup
+
+From: Miklos Szeredi <mszeredi@redhat.com>
+
+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 <mszeredi@redhat.com>
+Fixes: 3c18ef8117f0 ("fuse: optimize wake_up")
+Cc: <stable@vger.kernel.org> # v3.10
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..00a918c
--- /dev/null
@@ -0,0 +1,50 @@
+From bc78abbd55dd28e2287ec6d6502b842321a17c87 Mon Sep 17 00:00:00 2001
+From: Kirill Tkhai <ktkhai@virtuozzo.com>
+Date: Tue, 25 Sep 2018 12:28:55 +0300
+Subject: fuse: Fix use-after-free in fuse_dev_do_read()
+
+From: Kirill Tkhai <ktkhai@virtuozzo.com>
+
+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 <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
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..3f5c997
--- /dev/null
@@ -0,0 +1,60 @@
+From d2d2d4fb1f54eff0f3faa9762d84f6446a4bc5d0 Mon Sep 17 00:00:00 2001
+From: Kirill Tkhai <ktkhai@virtuozzo.com>
+Date: Tue, 25 Sep 2018 12:52:42 +0300
+Subject: fuse: Fix use-after-free in fuse_dev_do_write()
+
+From: Kirill Tkhai <ktkhai@virtuozzo.com>
+
+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 <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
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..4781cb2
--- /dev/null
@@ -0,0 +1,35 @@
+From 4c316f2f3ff315cb48efb7435621e5bfb81df96d Mon Sep 17 00:00:00 2001
+From: Miklos Szeredi <mszeredi@redhat.com>
+Date: Fri, 28 Sep 2018 16:43:22 +0200
+Subject: fuse: set FR_SENT while locked
+
+From: Miklos Szeredi <mszeredi@redhat.com>
+
+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 <mszeredi@redhat.com>
+Reported-by: syzbot+ef054c4d3f64cd7f7cec@syzkaller.appspotmai
+Fixes: 46c34a348b0a ("fuse: no fc->lock for pqueue parts")
+Cc: <stable@vger.kernel.org> # v4.2
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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))
index e2980083ea065db2f3b4bb4a1c3d54e9a4c71f51..ad295be262a0eabc1a30bfaffcb1c968749d79b4 100644 (file)
@@ -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