]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 15 Mar 2023 08:18:31 +0000 (09:18 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 15 Mar 2023 08:18:31 +0000 (09:18 +0100)
added patches:
ext4-add-strict-range-checks-while-freeing-blocks.patch
ext4-block-range-must-be-validated-before-use-in-ext4_mb_clear_bb.patch

queue-5.10/ext4-add-strict-range-checks-while-freeing-blocks.patch [new file with mode: 0644]
queue-5.10/ext4-block-range-must-be-validated-before-use-in-ext4_mb_clear_bb.patch [new file with mode: 0644]
queue-5.10/series

diff --git a/queue-5.10/ext4-add-strict-range-checks-while-freeing-blocks.patch b/queue-5.10/ext4-add-strict-range-checks-while-freeing-blocks.patch
new file mode 100644 (file)
index 0000000..6750acf
--- /dev/null
@@ -0,0 +1,66 @@
+From a00b482b82fb098956a5bed22bd7873e56f152f1 Mon Sep 17 00:00:00 2001
+From: Ritesh Harjani <riteshh@linux.ibm.com>
+Date: Wed, 16 Feb 2022 12:32:50 +0530
+Subject: ext4: add strict range checks while freeing blocks
+
+From: Ritesh Harjani <riteshh@linux.ibm.com>
+
+commit a00b482b82fb098956a5bed22bd7873e56f152f1 upstream.
+
+Currently ext4_mb_clear_bb() & ext4_group_add_blocks() only checks
+whether the given block ranges (which is to be freed) belongs to any FS
+metadata blocks or not, of the block's respective block group.
+But to detect any FS error early, it is better to add more strict
+checkings in those functions which checks whether the given blocks
+belongs to any critical FS metadata or not within system-zone.
+
+Suggested-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Ritesh Harjani <riteshh@linux.ibm.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/ddd9143d064774e32d6364a99667817c6e8bfdc0.1644992610.git.riteshh@linux.ibm.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/mballoc.c |   16 +++-------------
+ 1 file changed, 3 insertions(+), 13 deletions(-)
+
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -5361,13 +5361,7 @@ do_more:
+               goto error_return;
+       }
+-      if (in_range(ext4_block_bitmap(sb, gdp), block, count) ||
+-          in_range(ext4_inode_bitmap(sb, gdp), block, count) ||
+-          in_range(block, ext4_inode_table(sb, gdp),
+-                   sbi->s_itb_per_group) ||
+-          in_range(block + count - 1, ext4_inode_table(sb, gdp),
+-                   sbi->s_itb_per_group)) {
+-
++      if (!ext4_inode_block_valid(inode, block, count)) {
+               ext4_error(sb, "Freeing blocks in system zone - "
+                          "Block = %llu, count = %lu", block, count);
+               /* err = 0. ext4_std_error should be a no op */
+@@ -5437,7 +5431,7 @@ do_more:
+                                                NULL);
+                       if (err && err != -EOPNOTSUPP)
+                               ext4_msg(sb, KERN_WARNING, "discard request in"
+-                                       " group:%d block:%d count:%lu failed"
++                                       " group:%u block:%d count:%lu failed"
+                                        " with %d", block_group, bit, count,
+                                        err);
+               } else
+@@ -5650,11 +5644,7 @@ int ext4_group_add_blocks(handle_t *hand
+               goto error_return;
+       }
+-      if (in_range(ext4_block_bitmap(sb, desc), block, count) ||
+-          in_range(ext4_inode_bitmap(sb, desc), block, count) ||
+-          in_range(block, ext4_inode_table(sb, desc), sbi->s_itb_per_group) ||
+-          in_range(block + count - 1, ext4_inode_table(sb, desc),
+-                   sbi->s_itb_per_group)) {
++      if (!ext4_sb_block_valid(sb, NULL, block, count)) {
+               ext4_error(sb, "Adding blocks in system zones - "
+                          "Block = %llu, count = %lu",
+                          block, count);
diff --git a/queue-5.10/ext4-block-range-must-be-validated-before-use-in-ext4_mb_clear_bb.patch b/queue-5.10/ext4-block-range-must-be-validated-before-use-in-ext4_mb_clear_bb.patch
new file mode 100644 (file)
index 0000000..3a5421e
--- /dev/null
@@ -0,0 +1,143 @@
+From 1e1c2b86ef86a8477fd9b9a4f48a6bfe235606f6 Mon Sep 17 00:00:00 2001
+From: Lukas Czerner <lczerner@redhat.com>
+Date: Thu, 14 Jul 2022 18:59:03 +0200
+Subject: ext4: block range must be validated before use in ext4_mb_clear_bb()
+
+From: Lukas Czerner <lczerner@redhat.com>
+
+commit 1e1c2b86ef86a8477fd9b9a4f48a6bfe235606f6 upstream.
+
+Block range to free is validated in ext4_free_blocks() using
+ext4_inode_block_valid() and then it's passed to ext4_mb_clear_bb().
+However in some situations on bigalloc file system the range might be
+adjusted after the validation in ext4_free_blocks() which can lead to
+troubles on corrupted file systems such as one found by syzkaller that
+resulted in the following BUG
+
+kernel BUG at fs/ext4/ext4.h:3319!
+PREEMPT SMP NOPTI
+CPU: 28 PID: 4243 Comm: repro Kdump: loaded Not tainted 5.19.0-rc6+ #1
+Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.15.0-1.fc35 04/01/2014
+RIP: 0010:ext4_free_blocks+0x95e/0xa90
+Call Trace:
+ <TASK>
+ ? lock_timer_base+0x61/0x80
+ ? __es_remove_extent+0x5a/0x760
+ ? __mod_timer+0x256/0x380
+ ? ext4_ind_truncate_ensure_credits+0x90/0x220
+ ext4_clear_blocks+0x107/0x1b0
+ ext4_free_data+0x15b/0x170
+ ext4_ind_truncate+0x214/0x2c0
+ ? _raw_spin_unlock+0x15/0x30
+ ? ext4_discard_preallocations+0x15a/0x410
+ ? ext4_journal_check_start+0xe/0x90
+ ? __ext4_journal_start_sb+0x2f/0x110
+ ext4_truncate+0x1b5/0x460
+ ? __ext4_journal_start_sb+0x2f/0x110
+ ext4_evict_inode+0x2b4/0x6f0
+ evict+0xd0/0x1d0
+ ext4_enable_quotas+0x11f/0x1f0
+ ext4_orphan_cleanup+0x3de/0x430
+ ? proc_create_seq_private+0x43/0x50
+ ext4_fill_super+0x295f/0x3ae0
+ ? snprintf+0x39/0x40
+ ? sget_fc+0x19c/0x330
+ ? ext4_reconfigure+0x850/0x850
+ get_tree_bdev+0x16d/0x260
+ vfs_get_tree+0x25/0xb0
+ path_mount+0x431/0xa70
+ __x64_sys_mount+0xe2/0x120
+ do_syscall_64+0x5b/0x80
+ ? do_user_addr_fault+0x1e2/0x670
+ ? exc_page_fault+0x70/0x170
+ entry_SYSCALL_64_after_hwframe+0x46/0xb0
+RIP: 0033:0x7fdf4e512ace
+
+Fix it by making sure that the block range is properly validated before
+used every time it changes in ext4_free_blocks() or ext4_mb_clear_bb().
+
+Link: https://syzkaller.appspot.com/bug?id=5266d464285a03cee9dbfda7d2452a72c3c2ae7c
+Reported-by: syzbot+15cd994e273307bf5cfa@syzkaller.appspotmail.com
+Signed-off-by: Lukas Czerner <lczerner@redhat.com>
+Cc: Tadeusz Struk <tadeusz.struk@linaro.org>
+Tested-by: Tadeusz Struk <tadeusz.struk@linaro.org>
+Link: https://lore.kernel.org/r/20220714165903.58260-1-lczerner@redhat.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/mballoc.c |   21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -5331,6 +5331,15 @@ static void ext4_mb_clear_bb(handle_t *h
+       sbi = EXT4_SB(sb);
++      if (!(flags & EXT4_FREE_BLOCKS_VALIDATED) &&
++          !ext4_inode_block_valid(inode, block, count)) {
++              ext4_error(sb, "Freeing blocks in system zone - "
++                         "Block = %llu, count = %lu", block, count);
++              /* err = 0. ext4_std_error should be a no op */
++              goto error_return;
++      }
++      flags |= EXT4_FREE_BLOCKS_VALIDATED;
++
+ do_more:
+       overflow = 0;
+       ext4_get_group_no_and_offset(sb, block, &block_group, &bit);
+@@ -5347,6 +5356,8 @@ do_more:
+               overflow = EXT4_C2B(sbi, bit) + count -
+                       EXT4_BLOCKS_PER_GROUP(sb);
+               count -= overflow;
++              /* The range changed so it's no longer validated */
++              flags &= ~EXT4_FREE_BLOCKS_VALIDATED;
+       }
+       count_clusters = EXT4_NUM_B2C(sbi, count);
+       bitmap_bh = ext4_read_block_bitmap(sb, block_group);
+@@ -5361,7 +5372,8 @@ do_more:
+               goto error_return;
+       }
+-      if (!ext4_inode_block_valid(inode, block, count)) {
++      if (!(flags & EXT4_FREE_BLOCKS_VALIDATED) &&
++          !ext4_inode_block_valid(inode, block, count)) {
+               ext4_error(sb, "Freeing blocks in system zone - "
+                          "Block = %llu, count = %lu", block, count);
+               /* err = 0. ext4_std_error should be a no op */
+@@ -5483,6 +5495,8 @@ do_more:
+               block += count;
+               count = overflow;
+               put_bh(bitmap_bh);
++              /* The range changed so it's no longer validated */
++              flags &= ~EXT4_FREE_BLOCKS_VALIDATED;
+               goto do_more;
+       }
+ error_return:
+@@ -5529,6 +5543,7 @@ void ext4_free_blocks(handle_t *handle,
+                          "block = %llu, count = %lu", block, count);
+               return;
+       }
++      flags |= EXT4_FREE_BLOCKS_VALIDATED;
+       ext4_debug("freeing block %llu\n", block);
+       trace_ext4_free_blocks(inode, block, count, flags);
+@@ -5560,6 +5575,8 @@ void ext4_free_blocks(handle_t *handle,
+                       block -= overflow;
+                       count += overflow;
+               }
++              /* The range changed so it's no longer validated */
++              flags &= ~EXT4_FREE_BLOCKS_VALIDATED;
+       }
+       overflow = EXT4_LBLK_COFF(sbi, count);
+       if (overflow) {
+@@ -5570,6 +5587,8 @@ void ext4_free_blocks(handle_t *handle,
+                               return;
+               } else
+                       count += sbi->s_cluster_ratio - overflow;
++              /* The range changed so it's no longer validated */
++              flags &= ~EXT4_FREE_BLOCKS_VALIDATED;
+       }
+       if (!bh && (flags & EXT4_FREE_BLOCKS_FORGET)) {
index ef5fd32b0dfa7724303568118558259a5f6af28f..cd0a2fbb6899dc3e1c4a8daa45e60e2ecb493ec0 100644 (file)
@@ -99,3 +99,5 @@ sched-uclamp-fix-a-uninitialized-variable-warnings.patch
 sched-fair-fixes-for-capacity-inversion-detection.patch
 ext4-refactor-ext4_free_blocks-to-pull-out-ext4_mb_clear_bb.patch
 ext4-add-ext4_sb_block_valid-refactored-out-of-ext4_inode_block_valid.patch
+ext4-add-strict-range-checks-while-freeing-blocks.patch
+ext4-block-range-must-be-validated-before-use-in-ext4_mb_clear_bb.patch