]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.19-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 19 Aug 2020 11:41:28 +0000 (13:41 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 19 Aug 2020 11:41:28 +0000 (13:41 +0200)
added patches:
btrfs-fix-memory-leaks-after-failure-to-lookup-checksums-during-inode-logging.patch
btrfs-fix-messages-after-changing-compression-level-by-remount.patch
btrfs-fix-return-value-mixup-in-btrfs_get_extent.patch
btrfs-only-search-for-left_info-if-there-is-no-right_info-in-try_merge_free_space.patch

queue-4.19/btrfs-fix-memory-leaks-after-failure-to-lookup-checksums-during-inode-logging.patch [new file with mode: 0644]
queue-4.19/btrfs-fix-messages-after-changing-compression-level-by-remount.patch [new file with mode: 0644]
queue-4.19/btrfs-fix-return-value-mixup-in-btrfs_get_extent.patch [new file with mode: 0644]
queue-4.19/btrfs-only-search-for-left_info-if-there-is-no-right_info-in-try_merge_free_space.patch [new file with mode: 0644]
queue-4.19/series

diff --git a/queue-4.19/btrfs-fix-memory-leaks-after-failure-to-lookup-checksums-during-inode-logging.patch b/queue-4.19/btrfs-fix-memory-leaks-after-failure-to-lookup-checksums-during-inode-logging.patch
new file mode 100644 (file)
index 0000000..0463b6f
--- /dev/null
@@ -0,0 +1,54 @@
+From 4f26433e9b3eb7a55ed70d8f882ae9cd48ba448b Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Wed, 29 Jul 2020 10:17:50 +0100
+Subject: btrfs: fix memory leaks after failure to lookup checksums during inode logging
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit 4f26433e9b3eb7a55ed70d8f882ae9cd48ba448b upstream.
+
+While logging an inode, at copy_items(), if we fail to lookup the checksums
+for an extent we release the destination path, free the ins_data array and
+then return immediately. However a previous iteration of the for loop may
+have added checksums to the ordered_sums list, in which case we leak the
+memory used by them.
+
+So fix this by making sure we iterate the ordered_sums list and free all
+its checksums before returning.
+
+Fixes: 3650860b90cc2a ("Btrfs: remove almost all of the BUG()'s from tree-log.c")
+CC: stable@vger.kernel.org # 4.4+
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/tree-log.c |    8 ++------
+ 1 file changed, 2 insertions(+), 6 deletions(-)
+
+--- a/fs/btrfs/tree-log.c
++++ b/fs/btrfs/tree-log.c
+@@ -3988,11 +3988,8 @@ static noinline int copy_items(struct bt
+                                               fs_info->csum_root,
+                                               ds + cs, ds + cs + cl - 1,
+                                               &ordered_sums, 0);
+-                              if (ret) {
+-                                      btrfs_release_path(dst_path);
+-                                      kfree(ins_data);
+-                                      return ret;
+-                              }
++                              if (ret)
++                                      break;
+                       }
+               }
+       }
+@@ -4005,7 +4002,6 @@ static noinline int copy_items(struct bt
+        * we have to do this after the loop above to avoid changing the
+        * log tree while trying to change the log tree.
+        */
+-      ret = 0;
+       while (!list_empty(&ordered_sums)) {
+               struct btrfs_ordered_sum *sums = list_entry(ordered_sums.next,
+                                                  struct btrfs_ordered_sum,
diff --git a/queue-4.19/btrfs-fix-messages-after-changing-compression-level-by-remount.patch b/queue-4.19/btrfs-fix-messages-after-changing-compression-level-by-remount.patch
new file mode 100644 (file)
index 0000000..843d463
--- /dev/null
@@ -0,0 +1,84 @@
+From 27942c9971cc405c60432eca9395e514a2ae9f5e Mon Sep 17 00:00:00 2001
+From: David Sterba <dsterba@suse.com>
+Date: Thu, 23 Jul 2020 19:08:55 +0200
+Subject: btrfs: fix messages after changing compression level by remount
+
+From: David Sterba <dsterba@suse.com>
+
+commit 27942c9971cc405c60432eca9395e514a2ae9f5e upstream.
+
+Reported by Forza on IRC that remounting with compression options does
+not reflect the change in level, or at least it does not appear to do so
+according to the messages:
+
+  mount -o compress=zstd:1 /dev/sda /mnt
+  mount -o remount,compress=zstd:15 /mnt
+
+does not print the change to the level to syslog:
+
+  [   41.366060] BTRFS info (device vda): use zstd compression, level 1
+  [   41.368254] BTRFS info (device vda): disk space caching is enabled
+  [   41.390429] BTRFS info (device vda): disk space caching is enabled
+
+What really happens is that the message is lost but the level is actualy
+changed.
+
+There's another weird output, if compression is reset to 'no':
+
+  [   45.413776] BTRFS info (device vda): use no compression, level 4
+
+To fix that, save the previous compression level and print the message
+in that case too and use separate message for 'no' compression.
+
+CC: stable@vger.kernel.org # 4.19+
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/super.c |   14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+--- a/fs/btrfs/super.c
++++ b/fs/btrfs/super.c
+@@ -432,6 +432,7 @@ int btrfs_parse_options(struct btrfs_fs_
+       char *compress_type;
+       bool compress_force = false;
+       enum btrfs_compression_type saved_compress_type;
++      int saved_compress_level;
+       bool saved_compress_force;
+       int no_compress = 0;
+@@ -514,6 +515,7 @@ int btrfs_parse_options(struct btrfs_fs_
+                               info->compress_type : BTRFS_COMPRESS_NONE;
+                       saved_compress_force =
+                               btrfs_test_opt(info, FORCE_COMPRESS);
++                      saved_compress_level = info->compress_level;
+                       if (token == Opt_compress ||
+                           token == Opt_compress_force ||
+                           strncmp(args[0].from, "zlib", 4) == 0) {
+@@ -552,6 +554,8 @@ int btrfs_parse_options(struct btrfs_fs_
+                               no_compress = 0;
+                       } else if (strncmp(args[0].from, "no", 2) == 0) {
+                               compress_type = "no";
++                              info->compress_level = 0;
++                              info->compress_type = 0;
+                               btrfs_clear_opt(info->mount_opt, COMPRESS);
+                               btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS);
+                               compress_force = false;
+@@ -572,11 +576,11 @@ int btrfs_parse_options(struct btrfs_fs_
+                                */
+                               btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS);
+                       }
+-                      if ((btrfs_test_opt(info, COMPRESS) &&
+-                           (info->compress_type != saved_compress_type ||
+-                            compress_force != saved_compress_force)) ||
+-                          (!btrfs_test_opt(info, COMPRESS) &&
+-                           no_compress == 1)) {
++                      if (no_compress == 1) {
++                              btrfs_info(info, "use no compression");
++                      } else if ((info->compress_type != saved_compress_type) ||
++                                 (compress_force != saved_compress_force) ||
++                                 (info->compress_level != saved_compress_level)) {
+                               btrfs_info(info, "%s %s compression, level %d",
+                                          (compress_force) ? "force" : "use",
+                                          compress_type, info->compress_level);
diff --git a/queue-4.19/btrfs-fix-return-value-mixup-in-btrfs_get_extent.patch b/queue-4.19/btrfs-fix-return-value-mixup-in-btrfs_get_extent.patch
new file mode 100644 (file)
index 0000000..0d93dc8
--- /dev/null
@@ -0,0 +1,35 @@
+From 881a3a11c2b858fe9b69ef79ac5ee9978a266dc9 Mon Sep 17 00:00:00 2001
+From: Pavel Machek <pavel@denx.de>
+Date: Mon, 3 Aug 2020 11:35:06 +0200
+Subject: btrfs: fix return value mixup in btrfs_get_extent
+
+From: Pavel Machek <pavel@denx.de>
+
+commit 881a3a11c2b858fe9b69ef79ac5ee9978a266dc9 upstream.
+
+btrfs_get_extent() sets variable ret, but out: error path expect error
+to be in variable err so the error code is lost.
+
+Fixes: 6bf9e4bd6a27 ("btrfs: inode: Verify inode mode to avoid NULL pointer dereference")
+CC: stable@vger.kernel.org # 5.4+
+Reviewed-by: Nikolay Borisov <nborisov@suse.com>
+Signed-off-by: Pavel Machek (CIP) <pavel@denx.de>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/inode.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -7014,7 +7014,7 @@ struct extent_map *btrfs_get_extent(stru
+           found_type == BTRFS_FILE_EXTENT_PREALLOC) {
+               /* Only regular file could have regular/prealloc extent */
+               if (!S_ISREG(inode->vfs_inode.i_mode)) {
+-                      ret = -EUCLEAN;
++                      err = -EUCLEAN;
+                       btrfs_crit(fs_info,
+               "regular/prealloc extent found for non-regular inode %llu",
+                                  btrfs_ino(inode));
diff --git a/queue-4.19/btrfs-only-search-for-left_info-if-there-is-no-right_info-in-try_merge_free_space.patch b/queue-4.19/btrfs-only-search-for-left_info-if-there-is-no-right_info-in-try_merge_free_space.patch
new file mode 100644 (file)
index 0000000..620d238
--- /dev/null
@@ -0,0 +1,64 @@
+From bf53d4687b8f3f6b752f091eb85f62369a515dfd Mon Sep 17 00:00:00 2001
+From: Josef Bacik <josef@toxicpanda.com>
+Date: Mon, 27 Jul 2020 10:28:05 -0400
+Subject: btrfs: only search for left_info if there is no right_info in try_merge_free_space
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+commit bf53d4687b8f3f6b752f091eb85f62369a515dfd upstream.
+
+In try_to_merge_free_space we attempt to find entries to the left and
+right of the entry we are adding to see if they can be merged.  We
+search for an entry past our current info (saved into right_info), and
+then if right_info exists and it has a rb_prev() we save the rb_prev()
+into left_info.
+
+However there's a slight problem in the case that we have a right_info,
+but no entry previous to that entry.  At that point we will search for
+an entry just before the info we're attempting to insert.  This will
+simply find right_info again, and assign it to left_info, making them
+both the same pointer.
+
+Now if right_info _can_ be merged with the range we're inserting, we'll
+add it to the info and free right_info.  However further down we'll
+access left_info, which was right_info, and thus get a use-after-free.
+
+Fix this by only searching for the left entry if we don't find a right
+entry at all.
+
+The CVE referenced had a specially crafted file system that could
+trigger this use-after-free. However with the tree checker improvements
+we no longer trigger the conditions for the UAF.  But the original
+conditions still apply, hence this fix.
+
+Reference: CVE-2019-19448
+Fixes: 963030817060 ("Btrfs: use hybrid extents+bitmap rb tree for free space")
+CC: stable@vger.kernel.org # 4.4+
+Signed-off-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/free-space-cache.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/btrfs/free-space-cache.c
++++ b/fs/btrfs/free-space-cache.c
+@@ -2169,7 +2169,7 @@ out:
+ static bool try_merge_free_space(struct btrfs_free_space_ctl *ctl,
+                         struct btrfs_free_space *info, bool update_stat)
+ {
+-      struct btrfs_free_space *left_info;
++      struct btrfs_free_space *left_info = NULL;
+       struct btrfs_free_space *right_info;
+       bool merged = false;
+       u64 offset = info->offset;
+@@ -2184,7 +2184,7 @@ static bool try_merge_free_space(struct
+       if (right_info && rb_prev(&right_info->offset_index))
+               left_info = rb_entry(rb_prev(&right_info->offset_index),
+                                    struct btrfs_free_space, offset_index);
+-      else
++      else if (!right_info)
+               left_info = tree_search_offset(ctl, offset - 1, 0, 0);
+       if (right_info && !right_info->bitmap) {
index 0ad98c2b3d006e45e99a8a6fdd2a510becbcad1b..783cfe96ed0129c28d745f9a5b6e57346e8fd032 100644 (file)
@@ -11,3 +11,7 @@ btrfs-don-t-allocate-anonymous-block-device-for-user-invisible-roots.patch
 btrfs-ref-verify-fix-memory-leak-in-add_block_entry.patch
 btrfs-don-t-traverse-into-the-seed-devices-in-show_devname.patch
 btrfs-open-device-without-device_list_mutex.patch
+btrfs-fix-messages-after-changing-compression-level-by-remount.patch
+btrfs-only-search-for-left_info-if-there-is-no-right_info-in-try_merge_free_space.patch
+btrfs-fix-memory-leaks-after-failure-to-lookup-checksums-during-inode-logging.patch
+btrfs-fix-return-value-mixup-in-btrfs_get_extent.patch