]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 17 May 2021 10:42:58 +0000 (12:42 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 17 May 2021 10:42:58 +0000 (12:42 +0200)
added patches:
f2fs-fix-error-handling-in-f2fs_end_enable_verity.patch

queue-5.4/f2fs-fix-error-handling-in-f2fs_end_enable_verity.patch [new file with mode: 0644]
queue-5.4/series

diff --git a/queue-5.4/f2fs-fix-error-handling-in-f2fs_end_enable_verity.patch b/queue-5.4/f2fs-fix-error-handling-in-f2fs_end_enable_verity.patch
new file mode 100644 (file)
index 0000000..a693ca9
--- /dev/null
@@ -0,0 +1,135 @@
+From 3c0315424f5e3d2a4113c7272367bee1e8e6a174 Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Thu, 4 Mar 2021 21:43:10 -0800
+Subject: f2fs: fix error handling in f2fs_end_enable_verity()
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit 3c0315424f5e3d2a4113c7272367bee1e8e6a174 upstream.
+
+f2fs didn't properly clean up if verity failed to be enabled on a file:
+
+- It left verity metadata (pages past EOF) in the page cache, which
+  would be exposed to userspace if the file was later extended.
+
+- It didn't truncate the verity metadata at all (either from cache or
+  from disk) if an error occurred while setting the verity bit.
+
+Fix these bugs by adding a call to truncate_inode_pages() and ensuring
+that we truncate the verity metadata (both from cache and from disk) in
+all error paths.  Also rework the code to cleanly separate the success
+path from the error paths, which makes it much easier to understand.
+
+Finally, log a message if f2fs_truncate() fails, since it might
+otherwise fail silently.
+
+Reported-by: Yunlei He <heyunlei@hihonor.com>
+Fixes: 95ae251fe828 ("f2fs: add fs-verity support")
+Cc: <stable@vger.kernel.org> # v5.4+
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Reviewed-by: Chao Yu <yuchao0@huawei.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/verity.c |   79 ++++++++++++++++++++++++++++++++++++++-----------------
+ 1 file changed, 56 insertions(+), 23 deletions(-)
+
+--- a/fs/f2fs/verity.c
++++ b/fs/f2fs/verity.c
+@@ -150,40 +150,73 @@ static int f2fs_end_enable_verity(struct
+                                 size_t desc_size, u64 merkle_tree_size)
+ {
+       struct inode *inode = file_inode(filp);
++      struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+       u64 desc_pos = f2fs_verity_metadata_pos(inode) + merkle_tree_size;
+       struct fsverity_descriptor_location dloc = {
+               .version = cpu_to_le32(1),
+               .size = cpu_to_le32(desc_size),
+               .pos = cpu_to_le64(desc_pos),
+       };
+-      int err = 0;
++      int err = 0, err2 = 0;
+-      if (desc != NULL) {
+-              /* Succeeded; write the verity descriptor. */
+-              err = pagecache_write(inode, desc, desc_size, desc_pos);
+-
+-              /* Write all pages before clearing FI_VERITY_IN_PROGRESS. */
+-              if (!err)
+-                      err = filemap_write_and_wait(inode->i_mapping);
+-      }
+-
+-      /* If we failed, truncate anything we wrote past i_size. */
+-      if (desc == NULL || err)
+-              f2fs_truncate(inode);
++      /*
++       * If an error already occurred (which fs/verity/ signals by passing
++       * desc == NULL), then only clean-up is needed.
++       */
++      if (desc == NULL)
++              goto cleanup;
++
++      /* Append the verity descriptor. */
++      err = pagecache_write(inode, desc, desc_size, desc_pos);
++      if (err)
++              goto cleanup;
++
++      /*
++       * Write all pages (both data and verity metadata).  Note that this must
++       * happen before clearing FI_VERITY_IN_PROGRESS; otherwise pages beyond
++       * i_size won't be written properly.  For crash consistency, this also
++       * must happen before the verity inode flag gets persisted.
++       */
++      err = filemap_write_and_wait(inode->i_mapping);
++      if (err)
++              goto cleanup;
++
++      /* Set the verity xattr. */
++      err = f2fs_setxattr(inode, F2FS_XATTR_INDEX_VERITY,
++                          F2FS_XATTR_NAME_VERITY, &dloc, sizeof(dloc),
++                          NULL, XATTR_CREATE);
++      if (err)
++              goto cleanup;
++
++      /* Finally, set the verity inode flag. */
++      file_set_verity(inode);
++      f2fs_set_inode_flags(inode);
++      f2fs_mark_inode_dirty_sync(inode, true);
+       clear_inode_flag(inode, FI_VERITY_IN_PROGRESS);
++      return 0;
+-      if (desc != NULL && !err) {
+-              err = f2fs_setxattr(inode, F2FS_XATTR_INDEX_VERITY,
+-                                  F2FS_XATTR_NAME_VERITY, &dloc, sizeof(dloc),
+-                                  NULL, XATTR_CREATE);
+-              if (!err) {
+-                      file_set_verity(inode);
+-                      f2fs_set_inode_flags(inode);
+-                      f2fs_mark_inode_dirty_sync(inode, true);
+-              }
++cleanup:
++      /*
++       * Verity failed to be enabled, so clean up by truncating any verity
++       * metadata that was written beyond i_size (both from cache and from
++       * disk) and clearing FI_VERITY_IN_PROGRESS.
++       *
++       * Taking i_gc_rwsem[WRITE] is needed to stop f2fs garbage collection
++       * from re-instantiating cached pages we are truncating (since unlike
++       * normal file accesses, garbage collection isn't limited by i_size).
++       */
++      down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
++      truncate_inode_pages(inode->i_mapping, inode->i_size);
++      err2 = f2fs_truncate(inode);
++      if (err2) {
++              f2fs_err(sbi, "Truncating verity metadata failed (errno=%d)",
++                       err2);
++              set_sbi_flag(sbi, SBI_NEED_FSCK);
+       }
+-      return err;
++      up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
++      clear_inode_flag(inode, FI_VERITY_IN_PROGRESS);
++      return err ?: err2;
+ }
+ static int f2fs_get_verity_descriptor(struct inode *inode, void *buf,
index bcdf6809ad943844725ed408accb43981f794b78..09d7accae41bd08b5c7fe406d2675d548f05f4b7 100644 (file)
@@ -128,3 +128,4 @@ mips-reinstate-platform-__div64_32-handler.patch
 mips-avoid-divu-in-__div64_32-is-result-would-be-zero.patch
 mips-avoid-handcoded-divu-in-__div64_32-altogether.patch
 thermal-core-fair-share-lock-the-thermal-zone-while-looping-over-instances.patch
+f2fs-fix-error-handling-in-f2fs_end_enable_verity.patch