This is a note to let you know that I've just added the patch titled ext4: add EXT4_IGET_BAD flag to prevent unexpected bad inode to the 5.4-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: ext4-add-ext4_iget_bad-flag-to-prevent-unexpected-bad-inode.patch and it can be found in the queue-5.4 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From 63b1e9bccb71fe7d7e3ddc9877dbdc85e5d2d023 Mon Sep 17 00:00:00 2001 From: Baokun Li <libaokun1@xxxxxxxxxx> Date: Wed, 26 Oct 2022 12:23:09 +0800 Subject: ext4: add EXT4_IGET_BAD flag to prevent unexpected bad inode From: Baokun Li <libaokun1@xxxxxxxxxx> commit 63b1e9bccb71fe7d7e3ddc9877dbdc85e5d2d023 upstream. There are many places that will get unhappy (and crash) when ext4_iget() returns a bad inode. However, if iget the boot loader inode, allows a bad inode to be returned, because the inode may not be initialized. This mechanism can be used to bypass some checks and cause panic. To solve this problem, we add a special iget flag EXT4_IGET_BAD. Only with this flag we'd be returning bad inode from ext4_iget(), otherwise we always return the error code if the inode is bad inode.(suggested by Jan Kara) Signed-off-by: Baokun Li <libaokun1@xxxxxxxxxx> Reviewed-by: Jason Yan <yanaijie@xxxxxxxxxx> Reviewed-by: Jan Kara <jack@xxxxxxx> Link: https://lore.kernel.org/r/20221026042310.3839669-4-libaokun1@xxxxxxxxxx Signed-off-by: Theodore Ts'o <tytso@xxxxxxx> Cc: stable@xxxxxxxxxx Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- fs/ext4/ext4.h | 3 ++- fs/ext4/inode.c | 8 +++++++- fs/ext4/ioctl.c | 3 ++- 3 files changed, 11 insertions(+), 3 deletions(-) --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -2608,7 +2608,8 @@ int do_journal_get_write_access(handle_t typedef enum { EXT4_IGET_NORMAL = 0, EXT4_IGET_SPECIAL = 0x0001, /* OK to iget a system inode */ - EXT4_IGET_HANDLE = 0x0002 /* Inode # is from a handle */ + EXT4_IGET_HANDLE = 0x0002, /* Inode # is from a handle */ + EXT4_IGET_BAD = 0x0004 /* Allow to iget a bad inode */ } ext4_iget_flags; extern struct inode *__ext4_iget(struct super_block *sb, unsigned long ino, --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -5192,8 +5192,14 @@ struct inode *__ext4_iget(struct super_b if (IS_CASEFOLDED(inode) && !ext4_has_feature_casefold(inode->i_sb)) ext4_error_inode(inode, function, line, 0, "casefold flag without casefold feature"); - brelse(iloc.bh); + if (is_bad_inode(inode) && !(flags & EXT4_IGET_BAD)) { + ext4_error_inode(inode, function, line, 0, + "bad inode without EXT4_IGET_BAD flag"); + ret = -EUCLEAN; + goto bad_inode; + } + brelse(iloc.bh); unlock_new_inode(inode); return inode; --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -121,7 +121,8 @@ static long swap_inode_boot_loader(struc blkcnt_t blocks; unsigned short bytes; - inode_bl = ext4_iget(sb, EXT4_BOOT_LOADER_INO, EXT4_IGET_SPECIAL); + inode_bl = ext4_iget(sb, EXT4_BOOT_LOADER_INO, + EXT4_IGET_SPECIAL | EXT4_IGET_BAD); if (IS_ERR(inode_bl)) return PTR_ERR(inode_bl); ei_bl = EXT4_I(inode_bl); Patches currently in stable-queue which might be from libaokun1@xxxxxxxxxx are queue-5.4/ext4-fix-bug_on-in-__es_tree_search-caused-by-bad-boot-loader-inode.patch queue-5.4/ext4-add-inode-table-check-in-__ext4_get_inode_loc-to-aovid-possible-infinite-loop.patch queue-5.4/ext4-add-helper-to-check-quota-inums.patch queue-5.4/ext4-add-ext4_iget_bad-flag-to-prevent-unexpected-bad-inode.patch