FAILED: patch "[PATCH] ext4: fix use-after-free race with debug_want_extra_isize" failed to apply to 4.4-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 4.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 7bc04c5c2cc467c5b40f2b03ba08da174a0d5fa7 Mon Sep 17 00:00:00 2001
From: Barret Rhoden <[email protected]>
Date: Thu, 25 Apr 2019 11:55:50 -0400
Subject: [PATCH] ext4: fix use-after-free race with debug_want_extra_isize
When remounting with debug_want_extra_isize, we were not performing the same checks that we do during a normal mount. That allowed us to set a value for s_want_extra_isize that reached outside the s_inode_size.
Fixes e2b911c53584 ("ext4: clean up feature test macros with predicate functions")
Reported-by [email protected]
Reviewed-by Jan Kara <[email protected]>
Signed-off-by Barret Rhoden <[email protected]>
Signed-off-by Theodore Ts'o <[email protected]>
fs/ext4/super.c +34 -24
@@ -3513,6 +3513,37 @@ int ext4_calculate_overhead(struct super_block *sb)return 0 ; } +static void ext4_clamp_want_extra_isize (struct super_block *sb) +{ +struct ext4_sb_info *sbi =EXT4_SB (sb); +struct ext4_super_block *es = sbi->s_es; + +/* determine the minimum size of new large inodes, if present */ +if (sbi->s_inode_size >EXT4_GOOD_OLD_INODE_SIZE && + sbi->s_want_extra_isize ==0 ) { + sbi->s_want_extra_isize =sizeof (struct ext4_inode ) - +EXT4_GOOD_OLD_INODE_SIZE ; +if (ext4_has_feature_extra_isize (sb)) { +if (sbi->s_want_extra_isize < +le16_to_cpu (es->s_want_extra_isize)) + sbi->s_want_extra_isize = +le16_to_cpu (es->s_want_extra_isize); +if (sbi->s_want_extra_isize < +le16_to_cpu (es->s_min_extra_isize)) + sbi->s_want_extra_isize = +le16_to_cpu (es->s_min_extra_isize); + } + } +/* Check if enough inode space is available */ +if (EXT4_GOOD_OLD_INODE_SIZE + sbi->s_want_extra_isize > + sbi->s_inode_size) { + sbi->s_want_extra_isize =sizeof (struct ext4_inode ) - +EXT4_GOOD_OLD_INODE_SIZE ; +ext4_msg (sb,KERN_INFO , +"required extra inode space not available" ); + } +} +static void ext4_set_resv_clusters (struct super_block *sb) {ext4_fsblk_t resv_clusters;
@@ -4387,30 +4418,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) }else if (ret) goto failed_mount4a; -/* determine the minimum size of new large inodes, if present */ -if (sbi->s_inode_size >EXT4_GOOD_OLD_INODE_SIZE && - sbi->s_want_extra_isize ==0 ) { - sbi->s_want_extra_isize =sizeof (struct ext4_inode ) - -EXT4_GOOD_OLD_INODE_SIZE ; -if (ext4_has_feature_extra_isize (sb)) { -if (sbi->s_want_extra_isize < -le16_to_cpu (es->s_want_extra_isize)) - sbi->s_want_extra_isize = -le16_to_cpu (es->s_want_extra_isize); -if (sbi->s_want_extra_isize < -le16_to_cpu (es->s_min_extra_isize)) - sbi->s_want_extra_isize = -le16_to_cpu (es->s_min_extra_isize); - } - } -/* Check if enough inode space is available */ -if (EXT4_GOOD_OLD_INODE_SIZE + sbi->s_want_extra_isize > - sbi->s_inode_size) { - sbi->s_want_extra_isize =sizeof (struct ext4_inode ) - -EXT4_GOOD_OLD_INODE_SIZE ; -ext4_msg (sb,KERN_INFO ,"required extra inode space not" -"available" ); - } +ext4_clamp_want_extra_isize (sb);ext4_set_resv_clusters (sb);
@@ -5194,6 +5202,8 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) goto restore_opts; } +ext4_clamp_want_extra_isize (sb); +if ((old_opts.s_mount_opt &EXT4_MOUNT_JOURNAL_CHECKSUM ) ^test_opt (sb,JOURNAL_CHECKSUM )) { ext4_msg(sb, KERN_ERR, "changing journal_checksum "