From 7ee1c71aa8e9fe1ee151d2f3665c22261dea330a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 29 Jul 2024 12:19:17 +0200 Subject: [PATCH] 4.19-stable patches added patches: ext4-check-dot-and-dotdot-of-dx_root-before-making-dir-indexed.patch ext4-make-sure-the-first-directory-block-is-not-a-hole.patch m68k-amiga-turn-off-warp1260-interrupts-during-boot.patch --- ...of-dx_root-before-making-dir-indexed.patch | 151 ++++++++++++++++++ ...-first-directory-block-is-not-a-hole.patch | 85 ++++++++++ ...-off-warp1260-interrupts-during-boot.patch | 57 +++++++ queue-4.19/series | 3 + 4 files changed, 296 insertions(+) create mode 100644 queue-4.19/ext4-check-dot-and-dotdot-of-dx_root-before-making-dir-indexed.patch create mode 100644 queue-4.19/ext4-make-sure-the-first-directory-block-is-not-a-hole.patch create mode 100644 queue-4.19/m68k-amiga-turn-off-warp1260-interrupts-during-boot.patch diff --git a/queue-4.19/ext4-check-dot-and-dotdot-of-dx_root-before-making-dir-indexed.patch b/queue-4.19/ext4-check-dot-and-dotdot-of-dx_root-before-making-dir-indexed.patch new file mode 100644 index 00000000000..20fec957d9c --- /dev/null +++ b/queue-4.19/ext4-check-dot-and-dotdot-of-dx_root-before-making-dir-indexed.patch @@ -0,0 +1,151 @@ +From 50ea741def587a64e08879ce6c6a30131f7111e7 Mon Sep 17 00:00:00 2001 +From: Baokun Li +Date: Tue, 2 Jul 2024 21:23:48 +0800 +Subject: ext4: check dot and dotdot of dx_root before making dir indexed + +From: Baokun Li + +commit 50ea741def587a64e08879ce6c6a30131f7111e7 upstream. + +Syzbot reports a issue as follows: +============================================ +BUG: unable to handle page fault for address: ffffed11022e24fe +PGD 23ffee067 P4D 23ffee067 PUD 0 +Oops: Oops: 0000 [#1] PREEMPT SMP KASAN PTI +CPU: 0 PID: 5079 Comm: syz-executor306 Not tainted 6.10.0-rc5-g55027e689933 #0 +Call Trace: + + make_indexed_dir+0xdaf/0x13c0 fs/ext4/namei.c:2341 + ext4_add_entry+0x222a/0x25d0 fs/ext4/namei.c:2451 + ext4_rename fs/ext4/namei.c:3936 [inline] + ext4_rename2+0x26e5/0x4370 fs/ext4/namei.c:4214 +[...] +============================================ + +The immediate cause of this problem is that there is only one valid dentry +for the block to be split during do_split, so split==0 results in out of +bounds accesses to the map triggering the issue. + + do_split + unsigned split + dx_make_map + count = 1 + split = count/2 = 0; + continued = hash2 == map[split - 1].hash; + ---> map[4294967295] + +The maximum length of a filename is 255 and the minimum block size is 1024, +so it is always guaranteed that the number of entries is greater than or +equal to 2 when do_split() is called. + +But syzbot's crafted image has no dot and dotdot in dir, and the dentry +distribution in dirblock is as follows: + + bus dentry1 hole dentry2 free +|xx--|xx-------------|...............|xx-------------|...............| +0 12 (8+248)=256 268 256 524 (8+256)=264 788 236 1024 + +So when renaming dentry1 increases its name_len length by 1, neither hole +nor free is sufficient to hold the new dentry, and make_indexed_dir() is +called. + +In make_indexed_dir() it is assumed that the first two entries of the +dirblock must be dot and dotdot, so bus and dentry1 are left in dx_root +because they are treated as dot and dotdot, and only dentry2 is moved +to the new leaf block. That's why count is equal to 1. + +Therefore add the ext4_check_dx_root() helper function to add more sanity +checks to dot and dotdot before starting the conversion to avoid the above +issue. + +Reported-by: syzbot+ae688d469e36fb5138d0@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=ae688d469e36fb5138d0 +Fixes: ac27a0ec112a ("[PATCH] ext4: initial copy of files from ext3") +Cc: stable@kernel.org +Signed-off-by: Baokun Li +Reviewed-by: Jan Kara +Link: https://patch.msgid.link/20240702132349.2600605-2-libaokun@huaweicloud.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/namei.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 51 insertions(+), 5 deletions(-) + +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -1997,6 +1997,52 @@ static int add_dirent_to_buf(handle_t *h + return 0; + } + ++static bool ext4_check_dx_root(struct inode *dir, struct dx_root *root) ++{ ++ struct fake_dirent *fde; ++ const char *error_msg; ++ unsigned int rlen; ++ unsigned int blocksize = dir->i_sb->s_blocksize; ++ char *blockend = (char *)root + dir->i_sb->s_blocksize; ++ ++ fde = &root->dot; ++ if (unlikely(fde->name_len != 1)) { ++ error_msg = "invalid name_len for '.'"; ++ goto corrupted; ++ } ++ if (unlikely(strncmp(root->dot_name, ".", fde->name_len))) { ++ error_msg = "invalid name for '.'"; ++ goto corrupted; ++ } ++ rlen = ext4_rec_len_from_disk(fde->rec_len, blocksize); ++ if (unlikely((char *)fde + rlen >= blockend)) { ++ error_msg = "invalid rec_len for '.'"; ++ goto corrupted; ++ } ++ ++ fde = &root->dotdot; ++ if (unlikely(fde->name_len != 2)) { ++ error_msg = "invalid name_len for '..'"; ++ goto corrupted; ++ } ++ if (unlikely(strncmp(root->dotdot_name, "..", fde->name_len))) { ++ error_msg = "invalid name for '..'"; ++ goto corrupted; ++ } ++ rlen = ext4_rec_len_from_disk(fde->rec_len, blocksize); ++ if (unlikely((char *)fde + rlen >= blockend)) { ++ error_msg = "invalid rec_len for '..'"; ++ goto corrupted; ++ } ++ ++ return true; ++ ++corrupted: ++ EXT4_ERROR_INODE(dir, "Corrupt dir, %s, running e2fsck is recommended", ++ error_msg); ++ return false; ++} ++ + /* + * This converts a one block unindexed directory to a 3 block indexed + * directory, and adds the dentry to the indexed directory. +@@ -2031,17 +2077,17 @@ static int make_indexed_dir(handle_t *ha + brelse(bh); + return retval; + } ++ + root = (struct dx_root *) bh->b_data; ++ if (!ext4_check_dx_root(dir, root)) { ++ brelse(bh); ++ return -EFSCORRUPTED; ++ } + + /* The 0th block becomes the root, move the dirents out */ + fde = &root->dotdot; + de = (struct ext4_dir_entry_2 *)((char *)fde + + ext4_rec_len_from_disk(fde->rec_len, blocksize)); +- if ((char *) de >= (((char *) root) + blocksize)) { +- EXT4_ERROR_INODE(dir, "invalid rec_len for '..'"); +- brelse(bh); +- return -EFSCORRUPTED; +- } + len = ((char *) root) + (blocksize - csum_size) - (char *) de; + + /* Allocate new block for the 0th block's dirents */ diff --git a/queue-4.19/ext4-make-sure-the-first-directory-block-is-not-a-hole.patch b/queue-4.19/ext4-make-sure-the-first-directory-block-is-not-a-hole.patch new file mode 100644 index 00000000000..0aa692f193a --- /dev/null +++ b/queue-4.19/ext4-make-sure-the-first-directory-block-is-not-a-hole.patch @@ -0,0 +1,85 @@ +From f9ca51596bbfd0f9c386dd1c613c394c78d9e5e6 Mon Sep 17 00:00:00 2001 +From: Baokun Li +Date: Tue, 2 Jul 2024 21:23:49 +0800 +Subject: ext4: make sure the first directory block is not a hole + +From: Baokun Li + +commit f9ca51596bbfd0f9c386dd1c613c394c78d9e5e6 upstream. + +The syzbot constructs a directory that has no dirblock but is non-inline, +i.e. the first directory block is a hole. And no errors are reported when +creating files in this directory in the following flow. + + ext4_mknod + ... + ext4_add_entry + // Read block 0 + ext4_read_dirblock(dir, block, DIRENT) + bh = ext4_bread(NULL, inode, block, 0) + if (!bh && (type == INDEX || type == DIRENT_HTREE)) + // The first directory block is a hole + // But type == DIRENT, so no error is reported. + +After that, we get a directory block without '.' and '..' but with a valid +dentry. This may cause some code that relies on dot or dotdot (such as +make_indexed_dir()) to crash. + +Therefore when ext4_read_dirblock() finds that the first directory block +is a hole report that the filesystem is corrupted and return an error to +avoid loading corrupted data from disk causing something bad. + +Reported-by: syzbot+ae688d469e36fb5138d0@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=ae688d469e36fb5138d0 +Fixes: 4e19d6b65fb4 ("ext4: allow directory holes") +Cc: stable@kernel.org +Signed-off-by: Baokun Li +Reviewed-by: Jan Kara +Link: https://patch.msgid.link/20240702132349.2600605-3-libaokun@huaweicloud.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/namei.c | 17 ++++++----------- + 1 file changed, 6 insertions(+), 11 deletions(-) + +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -134,10 +134,11 @@ static struct buffer_head *__ext4_read_d + + return bh; + } +- if (!bh && (type == INDEX || type == DIRENT_HTREE)) { ++ /* The first directory block must not be a hole. */ ++ if (!bh && (type == INDEX || type == DIRENT_HTREE || block == 0)) { + ext4_error_inode(inode, func, line, block, +- "Directory hole found for htree %s block", +- (type == INDEX) ? "index" : "leaf"); ++ "Directory hole found for htree %s block %u", ++ (type == INDEX) ? "index" : "leaf", block); + return ERR_PTR(-EFSCORRUPTED); + } + if (!bh) +@@ -2850,10 +2851,7 @@ bool ext4_empty_dir(struct inode *inode) + EXT4_ERROR_INODE(inode, "invalid size"); + return true; + } +- /* The first directory block must not be a hole, +- * so treat it as DIRENT_HTREE +- */ +- bh = ext4_read_dirblock(inode, 0, DIRENT_HTREE); ++ bh = ext4_read_dirblock(inode, 0, EITHER); + if (IS_ERR(bh)) + return true; + +@@ -3425,10 +3423,7 @@ static struct buffer_head *ext4_get_firs + struct ext4_dir_entry_2 *de; + unsigned int offset; + +- /* The first directory block must not be a hole, so +- * treat it as DIRENT_HTREE +- */ +- bh = ext4_read_dirblock(inode, 0, DIRENT_HTREE); ++ bh = ext4_read_dirblock(inode, 0, EITHER); + if (IS_ERR(bh)) { + *retval = PTR_ERR(bh); + return NULL; diff --git a/queue-4.19/m68k-amiga-turn-off-warp1260-interrupts-during-boot.patch b/queue-4.19/m68k-amiga-turn-off-warp1260-interrupts-during-boot.patch new file mode 100644 index 00000000000..b28fe489b0e --- /dev/null +++ b/queue-4.19/m68k-amiga-turn-off-warp1260-interrupts-during-boot.patch @@ -0,0 +1,57 @@ +From 1d8491d3e726984343dd8c3cdbe2f2b47cfdd928 Mon Sep 17 00:00:00 2001 +From: Paolo Pisati +Date: Sat, 1 Jun 2024 17:32:54 +0200 +Subject: m68k: amiga: Turn off Warp1260 interrupts during boot + +From: Paolo Pisati + +commit 1d8491d3e726984343dd8c3cdbe2f2b47cfdd928 upstream. + +On an Amiga 1200 equipped with a Warp1260 accelerator, an interrupt +storm coming from the accelerator board causes the machine to crash in +local_irq_enable() or auto_irq_enable(). Disabling interrupts for the +Warp1260 in amiga_parse_bootinfo() fixes the problem. + +Link: https://lore.kernel.org/r/ZkjwzVwYeQtyAPrL@amaterasu.local +Cc: stable +Signed-off-by: Paolo Pisati +Reviewed-by: Michael Schmitz +Reviewed-by: Geert Uytterhoeven +Link: https://lore.kernel.org/r/20240601153254.186225-1-p.pisati@gmail.com +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Greg Kroah-Hartman +--- + arch/m68k/amiga/config.c | 9 +++++++++ + include/uapi/linux/zorro_ids.h | 3 +++ + 2 files changed, 12 insertions(+) + +--- a/arch/m68k/amiga/config.c ++++ b/arch/m68k/amiga/config.c +@@ -181,6 +181,15 @@ int __init amiga_parse_bootinfo(const st + dev->slotsize = be16_to_cpu(cd->cd_SlotSize); + dev->boardaddr = be32_to_cpu(cd->cd_BoardAddr); + dev->boardsize = be32_to_cpu(cd->cd_BoardSize); ++ ++ /* CS-LAB Warp 1260 workaround */ ++ if (be16_to_cpu(dev->rom.er_Manufacturer) == ZORRO_MANUF(ZORRO_PROD_CSLAB_WARP_1260) && ++ dev->rom.er_Product == ZORRO_PROD(ZORRO_PROD_CSLAB_WARP_1260)) { ++ ++ /* turn off all interrupts */ ++ pr_info("Warp 1260 card detected: applying interrupt storm workaround\n"); ++ *(uint32_t *)(dev->boardaddr + 0x1000) = 0xfff; ++ } + } else + pr_warn("amiga_parse_bootinfo: too many AutoConfig devices\n"); + #endif /* CONFIG_ZORRO */ +--- a/include/uapi/linux/zorro_ids.h ++++ b/include/uapi/linux/zorro_ids.h +@@ -449,6 +449,9 @@ + #define ZORRO_PROD_VMC_ISDN_BLASTER_Z2 ZORRO_ID(VMC, 0x01, 0) + #define ZORRO_PROD_VMC_HYPERCOM_4 ZORRO_ID(VMC, 0x02, 0) + ++#define ZORRO_MANUF_CSLAB 0x1400 ++#define ZORRO_PROD_CSLAB_WARP_1260 ZORRO_ID(CSLAB, 0x65, 0) ++ + #define ZORRO_MANUF_INFORMATION 0x157C + #define ZORRO_PROD_INFORMATION_ISDN_ENGINE_I ZORRO_ID(INFORMATION, 0x64, 0) + diff --git a/queue-4.19/series b/queue-4.19/series index 0a413f3a6c8..8de79130e2a 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -68,3 +68,6 @@ media-venus-fix-use-after-free-in-vdec_close.patch hfs-fix-to-initialize-fields-of-hfs_inode_info-after-hfs_alloc_inode.patch drm-gma500-fix-null-pointer-dereference-in-cdv_intel_lvds_get_modes.patch drm-gma500-fix-null-pointer-dereference-in-psb_intel_lvds_get_modes.patch +m68k-amiga-turn-off-warp1260-interrupts-during-boot.patch +ext4-check-dot-and-dotdot-of-dx_root-before-making-dir-indexed.patch +ext4-make-sure-the-first-directory-block-is-not-a-hole.patch -- 2.47.3