OSDN Git Service

fuse: fix unlocked access to processing queue
authorMiklos Szeredi <mszeredi@redhat.com>
Thu, 26 Jul 2018 14:13:11 +0000 (16:13 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 5 Sep 2018 07:18:39 +0000 (09:18 +0200)
commit 45ff350bbd9d0f0977ff270a0d427c71520c0c37 upstream.

fuse_dev_release() assumes that it's the only one referencing the
fpq->processing list, but that's not true, since fuse_abort_conn() can be
doing the same without any serialization between the two.

Fixes: c3696046beb3 ("fuse: separate pqueue for clones")
Cc: <stable@vger.kernel.org> # v4.2
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/fuse/dev.c

index 42a6263..5fc7521 100644 (file)
@@ -2199,9 +2199,15 @@ int fuse_dev_release(struct inode *inode, struct file *file)
        if (fud) {
                struct fuse_conn *fc = fud->fc;
                struct fuse_pqueue *fpq = &fud->pq;
+               LIST_HEAD(to_end);
 
+               spin_lock(&fpq->lock);
                WARN_ON(!list_empty(&fpq->io));
-               end_requests(fc, &fpq->processing);
+               list_splice_init(&fpq->processing, &to_end);
+               spin_unlock(&fpq->lock);
+
+               end_requests(fc, &to_end);
+
                /* Are we the last open device? */
                if (atomic_dec_and_test(&fc->dev_count)) {
                        WARN_ON(fc->iq.fasync != NULL);