Skip to content

Commit

Permalink
ext4: add EXT4_IGET_BAD flag to prevent unexpected bad inode
Browse files Browse the repository at this point in the history
commit 63b1e9b 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@huawei.com>
Reviewed-by: Jason Yan <yanaijie@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Link: https://lore.kernel.org/r/20221026042310.3839669-4-libaokun1@huawei.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Cc: stable@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Baokun Li authored and gregkh committed Jan 7, 2023
1 parent 7753d66 commit 488a5c2
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 3 deletions.
3 changes: 2 additions & 1 deletion fs/ext4/ext4.h
Expand Up @@ -2964,7 +2964,8 @@ int do_journal_get_write_access(handle_t *handle, struct inode *inode,
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,
Expand Down
8 changes: 7 additions & 1 deletion fs/ext4/inode.c
Expand Up @@ -5053,8 +5053,14 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
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;

Expand Down
3 changes: 2 additions & 1 deletion fs/ext4/ioctl.c
Expand Up @@ -374,7 +374,8 @@ static long swap_inode_boot_loader(struct super_block *sb,
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);
Expand Down

0 comments on commit 488a5c2

Please sign in to comment.