From: Greg Kroah-Hartman Date: Wed, 4 Jan 2023 14:59:00 +0000 (+0100) Subject: 4.9-stable patches X-Git-Tag: v6.1.4~34 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=969e6b94b1f718c4802e08c007a98f84822aa71d;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: ext4-add-inode-table-check-in-__ext4_get_inode_loc-to-aovid-possible-infinite-loop.patch ext4-fix-bug_on-in-__es_tree_search-caused-by-bad-boot-loader-inode.patch ext4-fix-undefined-behavior-in-bit-shift-for-ext4_check_flag_values.patch --- diff --git a/queue-4.9/ext4-add-inode-table-check-in-__ext4_get_inode_loc-to-aovid-possible-infinite-loop.patch b/queue-4.9/ext4-add-inode-table-check-in-__ext4_get_inode_loc-to-aovid-possible-infinite-loop.patch new file mode 100644 index 00000000000..f2bdc111aeb --- /dev/null +++ b/queue-4.9/ext4-add-inode-table-check-in-__ext4_get_inode_loc-to-aovid-possible-infinite-loop.patch @@ -0,0 +1,83 @@ +From eee22187b53611e173161e38f61de1c7ecbeb876 Mon Sep 17 00:00:00 2001 +From: Baokun Li +Date: Wed, 17 Aug 2022 21:27:01 +0800 +Subject: ext4: add inode table check in __ext4_get_inode_loc to aovid possible infinite loop + +From: Baokun Li + +commit eee22187b53611e173161e38f61de1c7ecbeb876 upstream. + +In do_writepages, if the value returned by ext4_writepages is "-ENOMEM" +and "wbc->sync_mode == WB_SYNC_ALL", retry until the condition is not met. + +In __ext4_get_inode_loc, if the bh returned by sb_getblk is NULL, +the function returns -ENOMEM. + +In __getblk_slow, if the return value of grow_buffers is less than 0, +the function returns NULL. + +When the three processes are connected in series like the following stack, +an infinite loop may occur: + +do_writepages <--- keep retrying + ext4_writepages + mpage_map_and_submit_extent + mpage_map_one_extent + ext4_map_blocks + ext4_ext_map_blocks + ext4_ext_handle_unwritten_extents + ext4_ext_convert_to_initialized + ext4_split_extent + ext4_split_extent_at + __ext4_ext_dirty + __ext4_mark_inode_dirty + ext4_reserve_inode_write + ext4_get_inode_loc + __ext4_get_inode_loc <--- return -ENOMEM + sb_getblk + __getblk_gfp + __getblk_slow <--- return NULL + grow_buffers + grow_dev_page <--- return -ENXIO + ret = (block < end_block) ? 1 : -ENXIO; + +In this issue, bg_inode_table_hi is overwritten as an incorrect value. +As a result, `block < end_block` cannot be met in grow_dev_page. +Therefore, __ext4_get_inode_loc always returns '-ENOMEM' and do_writepages +keeps retrying. As a result, the writeback process is in the D state due +to an infinite loop. + +Add a check on inode table block in the __ext4_get_inode_loc function by +referring to ext4_read_inode_bitmap to avoid this infinite loop. + +Cc: stable@kernel.org +Signed-off-by: Baokun Li +Reviewed-by: Ritesh Harjani (IBM) +Link: https://lore.kernel.org/r/20220817132701.3015912-3-libaokun1@huawei.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/inode.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -4321,9 +4321,17 @@ static int __ext4_get_inode_loc(struct i + inodes_per_block = EXT4_SB(sb)->s_inodes_per_block; + inode_offset = ((inode->i_ino - 1) % + EXT4_INODES_PER_GROUP(sb)); +- block = ext4_inode_table(sb, gdp) + (inode_offset / inodes_per_block); + iloc->offset = (inode_offset % inodes_per_block) * EXT4_INODE_SIZE(sb); + ++ block = ext4_inode_table(sb, gdp); ++ if ((block <= le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block)) || ++ (block >= ext4_blocks_count(EXT4_SB(sb)->s_es))) { ++ ext4_error(sb, "Invalid inode table block %llu in " ++ "block_group %u", block, iloc->block_group); ++ return -EFSCORRUPTED; ++ } ++ block += (inode_offset / inodes_per_block); ++ + bh = sb_getblk(sb, block); + if (unlikely(!bh)) + return -ENOMEM; diff --git a/queue-4.9/ext4-fix-bug_on-in-__es_tree_search-caused-by-bad-boot-loader-inode.patch b/queue-4.9/ext4-fix-bug_on-in-__es_tree_search-caused-by-bad-boot-loader-inode.patch new file mode 100644 index 00000000000..61ec8f8348d --- /dev/null +++ b/queue-4.9/ext4-fix-bug_on-in-__es_tree_search-caused-by-bad-boot-loader-inode.patch @@ -0,0 +1,96 @@ +From 991ed014de0840c5dc405b679168924afb2952ac Mon Sep 17 00:00:00 2001 +From: Baokun Li +Date: Wed, 26 Oct 2022 12:23:10 +0800 +Subject: ext4: fix bug_on in __es_tree_search caused by bad boot loader inode + +From: Baokun Li + +commit 991ed014de0840c5dc405b679168924afb2952ac upstream. + +We got a issue as fllows: +================================================================== + kernel BUG at fs/ext4/extents_status.c:203! + invalid opcode: 0000 [#1] PREEMPT SMP + CPU: 1 PID: 945 Comm: cat Not tainted 6.0.0-next-20221007-dirty #349 + RIP: 0010:ext4_es_end.isra.0+0x34/0x42 + RSP: 0018:ffffc9000143b768 EFLAGS: 00010203 + RAX: 0000000000000000 RBX: ffff8881769cd0b8 RCX: 0000000000000000 + RDX: 0000000000000000 RSI: ffffffff8fc27cf7 RDI: 00000000ffffffff + RBP: ffff8881769cd0bc R08: 0000000000000000 R09: ffffc9000143b5f8 + R10: 0000000000000001 R11: 0000000000000001 R12: ffff8881769cd0a0 + R13: ffff8881768e5668 R14: 00000000768e52f0 R15: 0000000000000000 + FS: 00007f359f7f05c0(0000)GS:ffff88842fd00000(0000)knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00007f359f5a2000 CR3: 000000017130c000 CR4: 00000000000006e0 + DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 + DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 + Call Trace: + + __es_tree_search.isra.0+0x6d/0xf5 + ext4_es_cache_extent+0xfa/0x230 + ext4_cache_extents+0xd2/0x110 + ext4_find_extent+0x5d5/0x8c0 + ext4_ext_map_blocks+0x9c/0x1d30 + ext4_map_blocks+0x431/0xa50 + ext4_mpage_readpages+0x48e/0xe40 + ext4_readahead+0x47/0x50 + read_pages+0x82/0x530 + page_cache_ra_unbounded+0x199/0x2a0 + do_page_cache_ra+0x47/0x70 + page_cache_ra_order+0x242/0x400 + ondemand_readahead+0x1e8/0x4b0 + page_cache_sync_ra+0xf4/0x110 + filemap_get_pages+0x131/0xb20 + filemap_read+0xda/0x4b0 + generic_file_read_iter+0x13a/0x250 + ext4_file_read_iter+0x59/0x1d0 + vfs_read+0x28f/0x460 + ksys_read+0x73/0x160 + __x64_sys_read+0x1e/0x30 + do_syscall_64+0x35/0x80 + entry_SYSCALL_64_after_hwframe+0x63/0xcd + +================================================================== + +In the above issue, ioctl invokes the swap_inode_boot_loader function to +swap inode<5> and inode<12>. However, inode<5> contain incorrect imode and +disordered extents, and i_nlink is set to 1. The extents check for inode in +the ext4_iget function can be bypassed bacause 5 is EXT4_BOOT_LOADER_INO. +While links_count is set to 1, the extents are not initialized in +swap_inode_boot_loader. After the ioctl command is executed successfully, +the extents are swapped to inode<12>, in this case, run the `cat` command +to view inode<12>. And Bug_ON is triggered due to the incorrect extents. + +When the boot loader inode is not initialized, its imode can be one of the +following: +1) the imode is a bad type, which is marked as bad_inode in ext4_iget and + set to S_IFREG. +2) the imode is good type but not S_IFREG. +3) the imode is S_IFREG. + +The BUG_ON may be triggered by bypassing the check in cases 1 and 2. +Therefore, when the boot loader inode is bad_inode or its imode is not +S_IFREG, initialize the inode to avoid triggering the BUG. + +Signed-off-by: Baokun Li +Reviewed-by: Jason Yan +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20221026042310.3839669-5-libaokun1@huawei.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/ioctl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/ext4/ioctl.c ++++ b/fs/ext4/ioctl.c +@@ -134,7 +134,7 @@ static long swap_inode_boot_loader(struc + /* Protect extent tree against block allocations via delalloc */ + ext4_double_down_write_data_sem(inode, inode_bl); + +- if (inode_bl->i_nlink == 0) { ++ if (is_bad_inode(inode_bl) || !S_ISREG(inode_bl->i_mode)) { + /* this inode has never been used as a BOOT_LOADER */ + set_nlink(inode_bl, 1); + i_uid_write(inode_bl, 0); diff --git a/queue-4.9/ext4-fix-undefined-behavior-in-bit-shift-for-ext4_check_flag_values.patch b/queue-4.9/ext4-fix-undefined-behavior-in-bit-shift-for-ext4_check_flag_values.patch new file mode 100644 index 00000000000..f24b4314c1f --- /dev/null +++ b/queue-4.9/ext4-fix-undefined-behavior-in-bit-shift-for-ext4_check_flag_values.patch @@ -0,0 +1,48 @@ +From 3bf678a0f9c017c9ba7c581541dbc8453452a7ae Mon Sep 17 00:00:00 2001 +From: Gaosheng Cui +Date: Mon, 31 Oct 2022 13:58:33 +0800 +Subject: ext4: fix undefined behavior in bit shift for ext4_check_flag_values + +From: Gaosheng Cui + +commit 3bf678a0f9c017c9ba7c581541dbc8453452a7ae upstream. + +Shifting signed 32-bit value by 31 bits is undefined, so changing +significant bit to unsigned. The UBSAN warning calltrace like below: + +UBSAN: shift-out-of-bounds in fs/ext4/ext4.h:591:2 +left shift of 1 by 31 places cannot be represented in type 'int' +Call Trace: + + dump_stack_lvl+0x7d/0xa5 + dump_stack+0x15/0x1b + ubsan_epilogue+0xe/0x4e + __ubsan_handle_shift_out_of_bounds+0x1e7/0x20c + ext4_init_fs+0x5a/0x277 + do_one_initcall+0x76/0x430 + kernel_init_freeable+0x3b3/0x422 + kernel_init+0x24/0x1e0 + ret_from_fork+0x1f/0x30 + + +Fixes: 9a4c80194713 ("ext4: ensure Inode flags consistency are checked at build time") +Signed-off-by: Gaosheng Cui +Link: https://lore.kernel.org/r/20221031055833.3966222-1-cuigaosheng1@huawei.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/ext4.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -476,7 +476,7 @@ enum { + * + * It's not paranoia if the Murphy's Law really *is* out to get you. :-) + */ +-#define TEST_FLAG_VALUE(FLAG) (EXT4_##FLAG##_FL == (1 << EXT4_INODE_##FLAG)) ++#define TEST_FLAG_VALUE(FLAG) (EXT4_##FLAG##_FL == (1U << EXT4_INODE_##FLAG)) + #define CHECK_FLAG_VALUE(FLAG) BUILD_BUG_ON(!TEST_FLAG_VALUE(FLAG)) + + static inline void ext4_check_flag_values(void) diff --git a/queue-4.9/series b/queue-4.9/series index 9920849e614..a2588f0c1f6 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -242,3 +242,6 @@ parisc-led-fix-potential-null-ptr-deref-in-start_task.patch device_cgroup-roll-back-to-original-exceptions-after-copy-failure.patch drm-connector-send-hotplug-uevent-on-connector-cleanup.patch drm-vmwgfx-validate-the-box-size-for-the-snooped-cursor.patch +ext4-add-inode-table-check-in-__ext4_get_inode_loc-to-aovid-possible-infinite-loop.patch +ext4-fix-undefined-behavior-in-bit-shift-for-ext4_check_flag_values.patch +ext4-fix-bug_on-in-__es_tree_search-caused-by-bad-boot-loader-inode.patch