Skip to content

Commit 5cd7402

Browse files
LiBaokun96tytso
authored andcommitted
ext4: fail ext4_iget if special inode unallocated
In ext4_fill_super(), EXT4_ORPHAN_FS flag is cleared after ext4_orphan_cleanup() is executed. Therefore, when __ext4_iget() is called to get an inode whose i_nlink is 0 when the flag exists, no error is returned. If the inode is a special inode, a null pointer dereference may occur. If the value of i_nlink is 0 for any inodes (except boot loader inodes) got by using the EXT4_IGET_SPECIAL flag, the current file system is corrupted. Therefore, make the ext4_iget() function return an error if it gets such an abnormal special inode. Link: https://bugzilla.kernel.org/show_bug.cgi?id=199179 Link: https://bugzilla.kernel.org/show_bug.cgi?id=216541 Link: https://bugzilla.kernel.org/show_bug.cgi?id=216539 Reported-by: Luís Henriques <[email protected]> Suggested-by: Theodore Ts'o <[email protected]> Signed-off-by: Baokun Li <[email protected]> Reviewed-by: Jan Kara <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Theodore Ts'o <[email protected]>
1 parent d99a55a commit 5cd7402

File tree

1 file changed

+8
-10
lines changed

1 file changed

+8
-10
lines changed

fs/ext4/inode.c

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4872,13 +4872,6 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
48724872
goto bad_inode;
48734873
raw_inode = ext4_raw_inode(&iloc);
48744874

4875-
if ((ino == EXT4_ROOT_INO) && (raw_inode->i_links_count == 0)) {
4876-
ext4_error_inode(inode, function, line, 0,
4877-
"iget: root inode unallocated");
4878-
ret = -EFSCORRUPTED;
4879-
goto bad_inode;
4880-
}
4881-
48824875
if ((flags & EXT4_IGET_HANDLE) &&
48834876
(raw_inode->i_links_count == 0) && (raw_inode->i_mode == 0)) {
48844877
ret = -ESTALE;
@@ -4951,11 +4944,16 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
49514944
* NeilBrown 1999oct15
49524945
*/
49534946
if (inode->i_nlink == 0) {
4954-
if ((inode->i_mode == 0 ||
4947+
if ((inode->i_mode == 0 || flags & EXT4_IGET_SPECIAL ||
49554948
!(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) &&
49564949
ino != EXT4_BOOT_LOADER_INO) {
4957-
/* this inode is deleted */
4958-
ret = -ESTALE;
4950+
/* this inode is deleted or unallocated */
4951+
if (flags & EXT4_IGET_SPECIAL) {
4952+
ext4_error_inode(inode, function, line, 0,
4953+
"iget: special inode unallocated");
4954+
ret = -EFSCORRUPTED;
4955+
} else
4956+
ret = -ESTALE;
49594957
goto bad_inode;
49604958
}
49614959
/* The only unlinked inodes we let through here have

0 commit comments

Comments
 (0)