Jan Kara 2ef082
From c37e9e013469521d9adb932d17a1795c139b36db Mon Sep 17 00:00:00 2001
Jan Kara 2ef082
From: Theodore Ts'o <tytso@mit.edu>
Jan Kara 2ef082
Date: Sun, 17 Jun 2018 00:41:14 -0400
Jan Kara 2ef082
Subject: [PATCH] ext4: add more inode number paranoia checks
Jan Kara 2ef082
Git-commit: c37e9e013469521d9adb932d17a1795c139b36db
Jan Kara 2ef082
Patch-mainline: v4.18-rc4
Jan Kara 2ef082
References: bsc#1099849 cve-2018-10882
Jan Kara 2ef082
Jan Kara 2ef082
If there is a directory entry pointing to a system inode (such as a
Jan Kara 2ef082
journal inode), complain and declare the file system to be corrupted.
Jan Kara 2ef082
Jan Kara 2ef082
Also, if the superblock's first inode number field is too small,
Jan Kara 2ef082
refuse to mount the file system.
Jan Kara 2ef082
Jan Kara 2ef082
This addresses CVE-2018-10882.
Jan Kara 2ef082
Jan Kara 2ef082
https://bugzilla.kernel.org/show_bug.cgi?id=200069
Jan Kara 2ef082
Jan Kara 2ef082
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Jan Kara 2ef082
Cc: stable@kernel.org
Jan Kara 2ef082
Acked-by: Jan Kara <jack@suse.cz>
Jan Kara 2ef082
Jan Kara 2ef082
---
Jan Kara 2ef082
 fs/ext4/ext4.h  | 5 -----
Jan Kara 2ef082
 fs/ext4/inode.c | 3 ++-
Jan Kara 2ef082
 fs/ext4/super.c | 5 +++++
Jan Kara 2ef082
 3 files changed, 7 insertions(+), 6 deletions(-)
Jan Kara 2ef082
Jan Kara 2ef082
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
Jan Kara 2ef082
index 859d6433dcc1..4bd69649a048 100644
Jan Kara 2ef082
--- a/fs/ext4/ext4.h
Jan Kara 2ef082
+++ b/fs/ext4/ext4.h
Jan Kara 2ef082
@@ -1502,11 +1502,6 @@ static inline struct ext4_inode_info *EXT4_I(struct inode *inode)
Jan Kara 2ef082
 static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
Jan Kara 2ef082
 {
Jan Kara 2ef082
 	return ino == EXT4_ROOT_INO ||
Jan Kara 2ef082
-		ino == EXT4_USR_QUOTA_INO ||
Jan Kara 2ef082
-		ino == EXT4_GRP_QUOTA_INO ||
Jan Kara 2ef082
-		ino == EXT4_BOOT_LOADER_INO ||
Jan Kara 2ef082
-		ino == EXT4_JOURNAL_INO ||
Jan Kara 2ef082
-		ino == EXT4_RESIZE_INO ||
Jan Kara 2ef082
 		(ino >= EXT4_FIRST_INO(sb) &&
Jan Kara 2ef082
 		 ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count));
Jan Kara 2ef082
 }
Jan Kara 2ef082
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
Jan Kara 2ef082
index c2f4ccb880c4..7d6c10017bdf 100644
Jan Kara 2ef082
--- a/fs/ext4/inode.c
Jan Kara 2ef082
+++ b/fs/ext4/inode.c
Jan Kara 2ef082
@@ -4506,7 +4506,8 @@ static int __ext4_get_inode_loc(struct inode *inode,
Jan Kara 2ef082
 	int			inodes_per_block, inode_offset;
Jan Kara 2ef082
 
Jan Kara 2ef082
 	iloc->bh = NULL;
Jan Kara 2ef082
-	if (!ext4_valid_inum(sb, inode->i_ino))
Jan Kara 2ef082
+	if (inode->i_ino < EXT4_ROOT_INO ||
Jan Kara 2ef082
+	    inode->i_ino > le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count))
Jan Kara 2ef082
 		return -EFSCORRUPTED;
Jan Kara 2ef082
 
Jan Kara 2ef082
 	iloc->block_group = (inode->i_ino - 1) / EXT4_INODES_PER_GROUP(sb);
Jan Kara 2ef082
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
Jan Kara 2ef082
index 4d34430d75f6..1f955c128e0d 100644
Jan Kara 2ef082
--- a/fs/ext4/super.c
Jan Kara 2ef082
+++ b/fs/ext4/super.c
Jan Kara 2ef082
@@ -3858,6 +3858,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
Jan Kara 2ef082
 	} else {
Jan Kara 2ef082
 		sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
Jan Kara 2ef082
 		sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
Jan Kara 2ef082
+		if (sbi->s_first_ino < EXT4_GOOD_OLD_FIRST_INO) {
Jan Kara 2ef082
+			ext4_msg(sb, KERN_ERR, "invalid first ino: %u",
Jan Kara 2ef082
+				 sbi->s_first_ino);
Jan Kara 2ef082
+			goto failed_mount;
Jan Kara 2ef082
+		}
Jan Kara 2ef082
 		if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) ||
Jan Kara 2ef082
 		    (!is_power_of_2(sbi->s_inode_size)) ||
Jan Kara 2ef082
 		    (sbi->s_inode_size > blocksize)) {
Jan Kara 2ef082
-- 
Jan Kara 2ef082
2.16.4
Jan Kara 2ef082