]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 30 Mar 2022 16:40:02 +0000 (18:40 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 30 Mar 2022 16:40:02 +0000 (18:40 +0200)
added patches:
fuse-fix-pipe-buffer-lifetime-for-direct_io.patch

queue-4.14/fuse-fix-pipe-buffer-lifetime-for-direct_io.patch [new file with mode: 0644]
queue-4.14/series

diff --git a/queue-4.14/fuse-fix-pipe-buffer-lifetime-for-direct_io.patch b/queue-4.14/fuse-fix-pipe-buffer-lifetime-for-direct_io.patch
new file mode 100644 (file)
index 0000000..33ef9d9
--- /dev/null
@@ -0,0 +1,81 @@
+From 0c4bcfdecb1ac0967619ee7ff44871d93c08c909 Mon Sep 17 00:00:00 2001
+From: Miklos Szeredi <mszeredi@redhat.com>
+Date: Mon, 7 Mar 2022 16:30:44 +0100
+Subject: fuse: fix pipe buffer lifetime for direct_io
+
+From: Miklos Szeredi <mszeredi@redhat.com>
+
+commit 0c4bcfdecb1ac0967619ee7ff44871d93c08c909 upstream.
+
+In FOPEN_DIRECT_IO mode, fuse_file_write_iter() calls
+fuse_direct_write_iter(), which normally calls fuse_direct_io(), which then
+imports the write buffer with fuse_get_user_pages(), which uses
+iov_iter_get_pages() to grab references to userspace pages instead of
+actually copying memory.
+
+On the filesystem device side, these pages can then either be read to
+userspace (via fuse_dev_read()), or splice()d over into a pipe using
+fuse_dev_splice_read() as pipe buffers with &nosteal_pipe_buf_ops.
+
+This is wrong because after fuse_dev_do_read() unlocks the FUSE request,
+the userspace filesystem can mark the request as completed, causing write()
+to return. At that point, the userspace filesystem should no longer have
+access to the pipe buffer.
+
+Fix by copying pages coming from the user address space to new pipe
+buffers.
+
+Reported-by: Jann Horn <jannh@google.com>
+Fixes: c3021629a0d8 ("fuse: support splice() reading from fuse device")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Zach O'Keefe <zokeefe@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/fuse/dev.c    |   12 +++++++++++-
+ fs/fuse/file.c   |    1 +
+ fs/fuse/fuse_i.h |    2 ++
+ 3 files changed, 14 insertions(+), 1 deletion(-)
+
+--- a/fs/fuse/dev.c
++++ b/fs/fuse/dev.c
+@@ -991,7 +991,17 @@ static int fuse_copy_page(struct fuse_co
+       while (count) {
+               if (cs->write && cs->pipebufs && page) {
+-                      return fuse_ref_page(cs, page, offset, count);
++                      /*
++                       * Can't control lifetime of pipe buffers, so always
++                       * copy user pages.
++                       */
++                      if (cs->req->user_pages) {
++                              err = fuse_copy_fill(cs);
++                              if (err)
++                                      return err;
++                      } else {
++                              return fuse_ref_page(cs, page, offset, count);
++                      }
+               } else if (!cs->len) {
+                       if (cs->move_pages && page &&
+                           offset == 0 && count == PAGE_SIZE) {
+--- a/fs/fuse/file.c
++++ b/fs/fuse/file.c
+@@ -1325,6 +1325,7 @@ static int fuse_get_user_pages(struct fu
+                       (PAGE_SIZE - ret) & (PAGE_SIZE - 1);
+       }
++      req->user_pages = true;
+       if (write)
+               req->in.argpages = 1;
+       else
+--- a/fs/fuse/fuse_i.h
++++ b/fs/fuse/fuse_i.h
+@@ -312,6 +312,8 @@ struct fuse_req {
+       /** refcount */
+       refcount_t count;
++      bool user_pages;
++
+       /** Unique ID for the interrupt request */
+       u64 intr_unique;
index 9a7065bc1c8107ef57989c162e0ad750bb8502b2..943579393aac3509ece31e54f72c97370eda3794 100644 (file)
@@ -7,3 +7,4 @@ ethernet-sun-free-the-coherent-when-failing-in-probi.patch
 spi-fix-invalid-sgs-value.patch
 spi-fix-erroneous-sgs-value-with-min_t.patch
 af_key-add-__gfp_zero-flag-for-compose_sadb_supporte.patch
+fuse-fix-pipe-buffer-lifetime-for-direct_io.patch