ext4: add more inode number paranoia checks
authorTheodore Ts'o <tytso@mit.edu>
Sun, 17 Jun 2018 04:41:14 +0000 (00:41 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Sun, 17 Jun 2018 04:41:14 +0000 (00:41 -0400)
If there is a directory entry pointing to a system inode (such as a
journal inode), complain and declare the file system to be corrupted.

Also, if the superblock's first inode number field is too small,
refuse to mount the file system.

This addresses CVE-2018-10882.

https://bugzilla.kernel.org/show_bug.cgi?id=200069

Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Cc: stable@kernel.org
fs/ext4/ext4.h
fs/ext4/inode.c
fs/ext4/super.c

index 859d6433dcc1e4826a273b21961ce68ae35a5127..4bd69649a0487e5b6b5f58850205d4d6f1d30573 100644 (file)
@@ -1502,11 +1502,6 @@ static inline struct ext4_inode_info *EXT4_I(struct inode *inode)
 static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
 {
        return ino == EXT4_ROOT_INO ||
-               ino == EXT4_USR_QUOTA_INO ||
-               ino == EXT4_GRP_QUOTA_INO ||
-               ino == EXT4_BOOT_LOADER_INO ||
-               ino == EXT4_JOURNAL_INO ||
-               ino == EXT4_RESIZE_INO ||
                (ino >= EXT4_FIRST_INO(sb) &&
                 ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count));
 }
index c2f4ccb880c43a5203d7393b3639a6a589a7b99f..7d6c10017bdf5910a655d9f005a65c5b190f727a 100644 (file)
@@ -4506,7 +4506,8 @@ static int __ext4_get_inode_loc(struct inode *inode,
        int                     inodes_per_block, inode_offset;
 
        iloc->bh = NULL;
-       if (!ext4_valid_inum(sb, inode->i_ino))
+       if (inode->i_ino < EXT4_ROOT_INO ||
+           inode->i_ino > le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count))
                return -EFSCORRUPTED;
 
        iloc->block_group = (inode->i_ino - 1) / EXT4_INODES_PER_GROUP(sb);
index 4d34430d75f61b05a790fb3b938c42e63d14babd..1f955c128e0d24e801316c5f58741b6ce07aa659 100644 (file)
@@ -3858,6 +3858,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        } else {
                sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
                sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
+               if (sbi->s_first_ino < EXT4_GOOD_OLD_FIRST_INO) {
+                       ext4_msg(sb, KERN_ERR, "invalid first ino: %u",
+                                sbi->s_first_ino);
+                       goto failed_mount;
+               }
                if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) ||
                    (!is_power_of_2(sbi->s_inode_size)) ||
                    (sbi->s_inode_size > blocksize)) {