aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2018-06-17 00:41:14 -0400
committerTheodore Ts'o <tytso@mit.edu>2018-06-17 00:41:14 -0400
commitc37e9e013469521d9adb932d17a1795c139b36db (patch)
treea7a39bc1259d9c8398817a5c7c05fcc87e8f6bb6
parent8bc1379b82b8e809eef77a9fedbb75c6c297be19 (diff)
ext4: add more inode number paranoia checks
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
-rw-r--r--fs/ext4/ext4.h5
-rw-r--r--fs/ext4/inode.c3
-rw-r--r--fs/ext4/super.c5
3 files changed, 7 insertions, 6 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 859d6433dcc1..4bd69649a048 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1502,11 +1502,6 @@ static inline struct ext4_inode_info *EXT4_I(struct inode *inode)
1502static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino) 1502static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
1503{ 1503{
1504 return ino == EXT4_ROOT_INO || 1504 return ino == EXT4_ROOT_INO ||
1505 ino == EXT4_USR_QUOTA_INO ||
1506 ino == EXT4_GRP_QUOTA_INO ||
1507 ino == EXT4_BOOT_LOADER_INO ||
1508 ino == EXT4_JOURNAL_INO ||
1509 ino == EXT4_RESIZE_INO ||
1510 (ino >= EXT4_FIRST_INO(sb) && 1505 (ino >= EXT4_FIRST_INO(sb) &&
1511 ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count)); 1506 ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count));
1512} 1507}
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index c2f4ccb880c4..7d6c10017bdf 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -4506,7 +4506,8 @@ static int __ext4_get_inode_loc(struct inode *inode,
4506 int inodes_per_block, inode_offset; 4506 int inodes_per_block, inode_offset;
4507 4507
4508 iloc->bh = NULL; 4508 iloc->bh = NULL;
4509 if (!ext4_valid_inum(sb, inode->i_ino)) 4509 if (inode->i_ino < EXT4_ROOT_INO ||
4510 inode->i_ino > le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count))
4510 return -EFSCORRUPTED; 4511 return -EFSCORRUPTED;
4511 4512
4512 iloc->block_group = (inode->i_ino - 1) / EXT4_INODES_PER_GROUP(sb); 4513 iloc->block_group = (inode->i_ino - 1) / EXT4_INODES_PER_GROUP(sb);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 4d34430d75f6..1f955c128e0d 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -3858,6 +3858,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
3858 } else { 3858 } else {
3859 sbi->s_inode_size = le16_to_cpu(es->s_inode_size); 3859 sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
3860 sbi->s_first_ino = le32_to_cpu(es->s_first_ino); 3860 sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
3861 if (sbi->s_first_ino < EXT4_GOOD_OLD_FIRST_INO) {
3862 ext4_msg(sb, KERN_ERR, "invalid first ino: %u",
3863 sbi->s_first_ino);
3864 goto failed_mount;
3865 }
3861 if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) || 3866 if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) ||
3862 (!is_power_of_2(sbi->s_inode_size)) || 3867 (!is_power_of_2(sbi->s_inode_size)) ||
3863 (sbi->s_inode_size > blocksize)) { 3868 (sbi->s_inode_size > blocksize)) {