From: Greg Kroah-Hartman Date: Mon, 25 Apr 2022 11:59:18 +0000 (+0200) Subject: 5.4-stable patches X-Git-Tag: v4.9.312~28 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=05434a59a92a7b72145a8e05ff57c45ce678d400;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: ext4-doc-fix-incorrect-h_reserved-size.patch ext4-fix-overhead-calculation-to-account-for-the-reserved-gdt-blocks.patch ext4-fix-symlink-file-size-not-match-to-file-content.patch ext4-fix-use-after-free-in-ext4_search_dir.patch ext4-force-overhead-calculation-if-the-s_overhead_cluster-makes-no-sense.patch ext4-limit-length-to-bitmap_maxbytes-blocksize-in-punch_hole.patch --- diff --git a/queue-5.4/ext4-doc-fix-incorrect-h_reserved-size.patch b/queue-5.4/ext4-doc-fix-incorrect-h_reserved-size.patch new file mode 100644 index 00000000000..57555832853 --- /dev/null +++ b/queue-5.4/ext4-doc-fix-incorrect-h_reserved-size.patch @@ -0,0 +1,32 @@ +From 7102ffe4c166ca0f5e35137e9f9de83768c2d27d Mon Sep 17 00:00:00 2001 +From: "wangjianjian (C)" +Date: Fri, 1 Apr 2022 20:07:35 +0800 +Subject: ext4, doc: fix incorrect h_reserved size + +From: wangjianjian (C) + +commit 7102ffe4c166ca0f5e35137e9f9de83768c2d27d upstream. + +According to document and code, ext4_xattr_header's size is 32 bytes, so +h_reserved size should be 3. + +Signed-off-by: Wang Jianjian +Link: https://lore.kernel.org/r/92fcc3a6-7d77-8c09-4126-377fcb4c46a5@huawei.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + Documentation/filesystems/ext4/attributes.rst | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/Documentation/filesystems/ext4/attributes.rst ++++ b/Documentation/filesystems/ext4/attributes.rst +@@ -76,7 +76,7 @@ The beginning of an extended attribute b + - Checksum of the extended attribute block. + * - 0x14 + - \_\_u32 +- - h\_reserved[2] ++ - h\_reserved[3] + - Zero. + + The checksum is calculated against the FS UUID, the 64-bit block number diff --git a/queue-5.4/ext4-fix-overhead-calculation-to-account-for-the-reserved-gdt-blocks.patch b/queue-5.4/ext4-fix-overhead-calculation-to-account-for-the-reserved-gdt-blocks.patch new file mode 100644 index 00000000000..8b190fa0735 --- /dev/null +++ b/queue-5.4/ext4-fix-overhead-calculation-to-account-for-the-reserved-gdt-blocks.patch @@ -0,0 +1,35 @@ +From 10b01ee92df52c8d7200afead4d5e5f55a5c58b1 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Thu, 14 Apr 2022 21:31:27 -0400 +Subject: ext4: fix overhead calculation to account for the reserved gdt blocks + +From: Theodore Ts'o + +commit 10b01ee92df52c8d7200afead4d5e5f55a5c58b1 upstream. + +The kernel calculation was underestimating the overhead by not taking +into account the reserved gdt blocks. With this change, the overhead +calculated by the kernel matches the overhead calculation in mke2fs. + +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/super.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -3485,9 +3485,11 @@ static int count_overhead(struct super_b + ext4_fsblk_t first_block, last_block, b; + ext4_group_t i, ngroups = ext4_get_groups_count(sb); + int s, j, count = 0; ++ int has_super = ext4_bg_has_super(sb, grp); + + if (!ext4_has_feature_bigalloc(sb)) +- return (ext4_bg_has_super(sb, grp) + ext4_bg_num_gdb(sb, grp) + ++ return (has_super + ext4_bg_num_gdb(sb, grp) + ++ (has_super ? le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) : 0) + + sbi->s_itb_per_group + 2); + + first_block = le32_to_cpu(sbi->s_es->s_first_data_block) + diff --git a/queue-5.4/ext4-fix-symlink-file-size-not-match-to-file-content.patch b/queue-5.4/ext4-fix-symlink-file-size-not-match-to-file-content.patch new file mode 100644 index 00000000000..1b42efa0cf4 --- /dev/null +++ b/queue-5.4/ext4-fix-symlink-file-size-not-match-to-file-content.patch @@ -0,0 +1,51 @@ +From a2b0b205d125f27cddfb4f7280e39affdaf46686 Mon Sep 17 00:00:00 2001 +From: Ye Bin +Date: Mon, 21 Mar 2022 22:44:38 +0800 +Subject: ext4: fix symlink file size not match to file content + +From: Ye Bin + +commit a2b0b205d125f27cddfb4f7280e39affdaf46686 upstream. + +We got issue as follows: +[home]# fsck.ext4 -fn ram0yb +e2fsck 1.45.6 (20-Mar-2020) +Pass 1: Checking inodes, blocks, and sizes +Pass 2: Checking directory structure +Symlink /p3/d14/d1a/l3d (inode #3494) is invalid. +Clear? no +Entry 'l3d' in /p3/d14/d1a (3383) has an incorrect filetype (was 7, should be 0). +Fix? no + +As the symlink file size does not match the file content. If the writeback +of the symlink data block failed, ext4_finish_bio() handles the end of IO. +However this function fails to mark the buffer with BH_write_io_error and +so when unmount does journal checkpoint it cannot detect the writeback +error and will cleanup the journal. Thus we've lost the correct data in the +journal area. To solve this issue, mark the buffer as BH_write_io_error in +ext4_finish_bio(). + +Cc: stable@kernel.org +Signed-off-by: Ye Bin +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20220321144438.201685-1-yebin10@huawei.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/page-io.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/fs/ext4/page-io.c ++++ b/fs/ext4/page-io.c +@@ -100,8 +100,10 @@ static void ext4_finish_bio(struct bio * + continue; + } + clear_buffer_async_write(bh); +- if (bio->bi_status) ++ if (bio->bi_status) { ++ set_buffer_write_io_error(bh); + buffer_io_error(bh); ++ } + } while ((bh = bh->b_this_page) != head); + bit_spin_unlock(BH_Uptodate_Lock, &head->b_state); + local_irq_restore(flags); diff --git a/queue-5.4/ext4-fix-use-after-free-in-ext4_search_dir.patch b/queue-5.4/ext4-fix-use-after-free-in-ext4_search_dir.patch new file mode 100644 index 00000000000..ad99e5f8cd5 --- /dev/null +++ b/queue-5.4/ext4-fix-use-after-free-in-ext4_search_dir.patch @@ -0,0 +1,125 @@ +From c186f0887fe7061a35cebef024550ec33ef8fbd8 Mon Sep 17 00:00:00 2001 +From: Ye Bin +Date: Thu, 24 Mar 2022 14:48:16 +0800 +Subject: ext4: fix use-after-free in ext4_search_dir + +From: Ye Bin + +commit c186f0887fe7061a35cebef024550ec33ef8fbd8 upstream. + +We got issue as follows: +EXT4-fs (loop0): mounted filesystem without journal. Opts: ,errors=continue +================================================================== +BUG: KASAN: use-after-free in ext4_search_dir fs/ext4/namei.c:1394 [inline] +BUG: KASAN: use-after-free in search_dirblock fs/ext4/namei.c:1199 [inline] +BUG: KASAN: use-after-free in __ext4_find_entry+0xdca/0x1210 fs/ext4/namei.c:1553 +Read of size 1 at addr ffff8881317c3005 by task syz-executor117/2331 + +CPU: 1 PID: 2331 Comm: syz-executor117 Not tainted 5.10.0+ #1 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org 04/01/2014 +Call Trace: + __dump_stack lib/dump_stack.c:83 [inline] + dump_stack+0x144/0x187 lib/dump_stack.c:124 + print_address_description+0x7d/0x630 mm/kasan/report.c:387 + __kasan_report+0x132/0x190 mm/kasan/report.c:547 + kasan_report+0x47/0x60 mm/kasan/report.c:564 + ext4_search_dir fs/ext4/namei.c:1394 [inline] + search_dirblock fs/ext4/namei.c:1199 [inline] + __ext4_find_entry+0xdca/0x1210 fs/ext4/namei.c:1553 + ext4_lookup_entry fs/ext4/namei.c:1622 [inline] + ext4_lookup+0xb8/0x3a0 fs/ext4/namei.c:1690 + __lookup_hash+0xc5/0x190 fs/namei.c:1451 + do_rmdir+0x19e/0x310 fs/namei.c:3760 + do_syscall_64+0x33/0x40 arch/x86/entry/common.c:46 + entry_SYSCALL_64_after_hwframe+0x44/0xa9 +RIP: 0033:0x445e59 +Code: 4d c7 fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 1b c7 fb ff c3 66 2e 0f 1f 84 00 00 00 00 +RSP: 002b:00007fff2277fac8 EFLAGS: 00000246 ORIG_RAX: 0000000000000054 +RAX: ffffffffffffffda RBX: 0000000000400280 RCX: 0000000000445e59 +RDX: 0000000000000000 RSI: 0000000000000000 RDI: 00000000200000c0 +RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000002 +R10: 00007fff2277f990 R11: 0000000000000246 R12: 0000000000000000 +R13: 431bde82d7b634db R14: 0000000000000000 R15: 0000000000000000 + +The buggy address belongs to the page: +page:0000000048cd3304 refcount:0 mapcount:0 mapping:0000000000000000 index:0x1 pfn:0x1317c3 +flags: 0x200000000000000() +raw: 0200000000000000 ffffea0004526588 ffffea0004528088 0000000000000000 +raw: 0000000000000001 0000000000000000 00000000ffffffff 0000000000000000 +page dumped because: kasan: bad access detected + +Memory state around the buggy address: + ffff8881317c2f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ffff8881317c2f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +>ffff8881317c3000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ^ + ffff8881317c3080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ffff8881317c3100: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff +================================================================== + +ext4_search_dir: + ... + de = (struct ext4_dir_entry_2 *)search_buf; + dlimit = search_buf + buf_size; + while ((char *) de < dlimit) { + ... + if ((char *) de + de->name_len <= dlimit && + ext4_match(dir, fname, de)) { + ... + } + ... + de_len = ext4_rec_len_from_disk(de->rec_len, dir->i_sb->s_blocksize); + if (de_len <= 0) + return -1; + offset += de_len; + de = (struct ext4_dir_entry_2 *) ((char *) de + de_len); + } + +Assume: +de=0xffff8881317c2fff +dlimit=0x0xffff8881317c3000 + +If read 'de->name_len' which address is 0xffff8881317c3005, obviously is +out of range, then will trigger use-after-free. +To solve this issue, 'dlimit' must reserve 8 bytes, as we will read +'de->name_len' to judge if '(char *) de + de->name_len' out of range. + +Signed-off-by: Ye Bin +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20220324064816.1209985-1-yebin10@huawei.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/ext4.h | 4 ++++ + fs/ext4/namei.c | 4 ++-- + 2 files changed, 6 insertions(+), 2 deletions(-) + +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -1966,6 +1966,10 @@ static inline int ext4_forced_shutdown(s + * Structure of a directory entry + */ + #define EXT4_NAME_LEN 255 ++/* ++ * Base length of the ext4 directory entry excluding the name length ++ */ ++#define EXT4_BASE_DIR_LEN (sizeof(struct ext4_dir_entry_2) - EXT4_NAME_LEN) + + struct ext4_dir_entry { + __le32 inode; /* Inode number */ +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -1385,10 +1385,10 @@ int ext4_search_dir(struct buffer_head * + + de = (struct ext4_dir_entry_2 *)search_buf; + dlimit = search_buf + buf_size; +- while ((char *) de < dlimit) { ++ while ((char *) de < dlimit - EXT4_BASE_DIR_LEN) { + /* this code is executed quadratically often */ + /* do minimal checking `by hand' */ +- if ((char *) de + de->name_len <= dlimit && ++ if (de->name + de->name_len <= dlimit && + ext4_match(dir, fname, de)) { + /* found a match - just to be sure, do + * a full check */ diff --git a/queue-5.4/ext4-force-overhead-calculation-if-the-s_overhead_cluster-makes-no-sense.patch b/queue-5.4/ext4-force-overhead-calculation-if-the-s_overhead_cluster-makes-no-sense.patch new file mode 100644 index 00000000000..2f3f35b4725 --- /dev/null +++ b/queue-5.4/ext4-force-overhead-calculation-if-the-s_overhead_cluster-makes-no-sense.patch @@ -0,0 +1,44 @@ +From 85d825dbf4899a69407338bae462a59aa9a37326 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Thu, 14 Apr 2022 21:57:49 -0400 +Subject: ext4: force overhead calculation if the s_overhead_cluster makes no sense + +From: Theodore Ts'o + +commit 85d825dbf4899a69407338bae462a59aa9a37326 upstream. + +If the file system does not use bigalloc, calculating the overhead is +cheap, so force the recalculation of the overhead so we don't have to +trust the precalculated overhead in the superblock. + +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/super.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -4514,9 +4514,18 @@ no_journal: + * Get the # of file system overhead blocks from the + * superblock if present. + */ +- if (es->s_overhead_clusters) +- sbi->s_overhead = le32_to_cpu(es->s_overhead_clusters); +- else { ++ sbi->s_overhead = le32_to_cpu(es->s_overhead_clusters); ++ /* ignore the precalculated value if it is ridiculous */ ++ if (sbi->s_overhead > ext4_blocks_count(es)) ++ sbi->s_overhead = 0; ++ /* ++ * If the bigalloc feature is not enabled recalculating the ++ * overhead doesn't take long, so we might as well just redo ++ * it to make sure we are using the correct value. ++ */ ++ if (!ext4_has_feature_bigalloc(sb)) ++ sbi->s_overhead = 0; ++ if (sbi->s_overhead == 0) { + err = ext4_calculate_overhead(sb); + if (err) + goto failed_mount_wq; diff --git a/queue-5.4/ext4-limit-length-to-bitmap_maxbytes-blocksize-in-punch_hole.patch b/queue-5.4/ext4-limit-length-to-bitmap_maxbytes-blocksize-in-punch_hole.patch new file mode 100644 index 00000000000..e621b89a4e6 --- /dev/null +++ b/queue-5.4/ext4-limit-length-to-bitmap_maxbytes-blocksize-in-punch_hole.patch @@ -0,0 +1,60 @@ +From 2da376228a2427501feb9d15815a45dbdbdd753e Mon Sep 17 00:00:00 2001 +From: Tadeusz Struk +Date: Thu, 31 Mar 2022 13:05:15 -0700 +Subject: ext4: limit length to bitmap_maxbytes - blocksize in punch_hole + +From: Tadeusz Struk + +commit 2da376228a2427501feb9d15815a45dbdbdd753e upstream. + +Syzbot found an issue [1] in ext4_fallocate(). +The C reproducer [2] calls fallocate(), passing size 0xffeffeff000ul, +and offset 0x1000000ul, which, when added together exceed the +bitmap_maxbytes for the inode. This triggers a BUG in +ext4_ind_remove_space(). According to the comments in this function +the 'end' parameter needs to be one block after the last block to be +removed. In the case when the BUG is triggered it points to the last +block. Modify the ext4_punch_hole() function and add constraint that +caps the length to satisfy the one before laster block requirement. + +LINK: [1] https://syzkaller.appspot.com/bug?id=b80bd9cf348aac724a4f4dff251800106d721331 +LINK: [2] https://syzkaller.appspot.com/text?tag=ReproC&x=14ba0238700000 + +Fixes: a4bb6b64e39a ("ext4: enable "punch hole" functionality") +Reported-by: syzbot+7a806094edd5d07ba029@syzkaller.appspotmail.com +Signed-off-by: Tadeusz Struk +Link: https://lore.kernel.org/r/20220331200515.153214-1-tadeusz.struk@linaro.org +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/inode.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -4311,7 +4311,8 @@ int ext4_punch_hole(struct inode *inode, + struct super_block *sb = inode->i_sb; + ext4_lblk_t first_block, stop_block; + struct address_space *mapping = inode->i_mapping; +- loff_t first_block_offset, last_block_offset; ++ loff_t first_block_offset, last_block_offset, max_length; ++ struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); + handle_t *handle; + unsigned int credits; + int ret = 0; +@@ -4357,6 +4358,14 @@ int ext4_punch_hole(struct inode *inode, + offset; + } + ++ /* ++ * For punch hole the length + offset needs to be within one block ++ * before last range. Adjust the length if it goes beyond that limit. ++ */ ++ max_length = sbi->s_bitmap_maxbytes - inode->i_sb->s_blocksize; ++ if (offset + length > max_length) ++ length = max_length - offset; ++ + if (offset & (sb->s_blocksize - 1) || + (offset + length) & (sb->s_blocksize - 1)) { + /* diff --git a/queue-5.4/series b/queue-5.4/series index e2849c5498c..1d4013fa388 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -49,3 +49,9 @@ asoc-soc-dapm-fix-two-incorrect-uses-of-list-iterator.patch e1000e-fix-possible-overflow-in-ltr-decoding.patch arc-entry-fix-syscall_trace_exit-argument.patch arm_pmu-validate-single-group-leader-events.patch +ext4-fix-symlink-file-size-not-match-to-file-content.patch +ext4-fix-use-after-free-in-ext4_search_dir.patch +ext4-limit-length-to-bitmap_maxbytes-blocksize-in-punch_hole.patch +ext4-doc-fix-incorrect-h_reserved-size.patch +ext4-fix-overhead-calculation-to-account-for-the-reserved-gdt-blocks.patch +ext4-force-overhead-calculation-if-the-s_overhead_cluster-makes-no-sense.patch