]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-4.19/ext4-fix-use-after-free-race-with-debug_want_extra_isize.patch
f77820084007cba293018073e58e53b43dae6a59
[thirdparty/kernel/stable-queue.git] / queue-4.19 / ext4-fix-use-after-free-race-with-debug_want_extra_isize.patch
1 From 7bc04c5c2cc467c5b40f2b03ba08da174a0d5fa7 Mon Sep 17 00:00:00 2001
2 From: Barret Rhoden <brho@google.com>
3 Date: Thu, 25 Apr 2019 11:55:50 -0400
4 Subject: ext4: fix use-after-free race with debug_want_extra_isize
5
6 From: Barret Rhoden <brho@google.com>
7
8 commit 7bc04c5c2cc467c5b40f2b03ba08da174a0d5fa7 upstream.
9
10 When remounting with debug_want_extra_isize, we were not performing the
11 same checks that we do during a normal mount. That allowed us to set a
12 value for s_want_extra_isize that reached outside the s_inode_size.
13
14 Fixes: e2b911c53584 ("ext4: clean up feature test macros with predicate functions")
15 Reported-by: syzbot+f584efa0ac7213c226b7@syzkaller.appspotmail.com
16 Reviewed-by: Jan Kara <jack@suse.cz>
17 Signed-off-by: Barret Rhoden <brho@google.com>
18 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
19 Cc: stable@vger.kernel.org
20 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
21
22 ---
23 fs/ext4/super.c | 58 ++++++++++++++++++++++++++++++++------------------------
24 1 file changed, 34 insertions(+), 24 deletions(-)
25
26 --- a/fs/ext4/super.c
27 +++ b/fs/ext4/super.c
28 @@ -3514,6 +3514,37 @@ int ext4_calculate_overhead(struct super
29 return 0;
30 }
31
32 +static void ext4_clamp_want_extra_isize(struct super_block *sb)
33 +{
34 + struct ext4_sb_info *sbi = EXT4_SB(sb);
35 + struct ext4_super_block *es = sbi->s_es;
36 +
37 + /* determine the minimum size of new large inodes, if present */
38 + if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE &&
39 + sbi->s_want_extra_isize == 0) {
40 + sbi->s_want_extra_isize = sizeof(struct ext4_inode) -
41 + EXT4_GOOD_OLD_INODE_SIZE;
42 + if (ext4_has_feature_extra_isize(sb)) {
43 + if (sbi->s_want_extra_isize <
44 + le16_to_cpu(es->s_want_extra_isize))
45 + sbi->s_want_extra_isize =
46 + le16_to_cpu(es->s_want_extra_isize);
47 + if (sbi->s_want_extra_isize <
48 + le16_to_cpu(es->s_min_extra_isize))
49 + sbi->s_want_extra_isize =
50 + le16_to_cpu(es->s_min_extra_isize);
51 + }
52 + }
53 + /* Check if enough inode space is available */
54 + if (EXT4_GOOD_OLD_INODE_SIZE + sbi->s_want_extra_isize >
55 + sbi->s_inode_size) {
56 + sbi->s_want_extra_isize = sizeof(struct ext4_inode) -
57 + EXT4_GOOD_OLD_INODE_SIZE;
58 + ext4_msg(sb, KERN_INFO,
59 + "required extra inode space not available");
60 + }
61 +}
62 +
63 static void ext4_set_resv_clusters(struct super_block *sb)
64 {
65 ext4_fsblk_t resv_clusters;
66 @@ -4388,30 +4419,7 @@ no_journal:
67 } else if (ret)
68 goto failed_mount4a;
69
70 - /* determine the minimum size of new large inodes, if present */
71 - if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE &&
72 - sbi->s_want_extra_isize == 0) {
73 - sbi->s_want_extra_isize = sizeof(struct ext4_inode) -
74 - EXT4_GOOD_OLD_INODE_SIZE;
75 - if (ext4_has_feature_extra_isize(sb)) {
76 - if (sbi->s_want_extra_isize <
77 - le16_to_cpu(es->s_want_extra_isize))
78 - sbi->s_want_extra_isize =
79 - le16_to_cpu(es->s_want_extra_isize);
80 - if (sbi->s_want_extra_isize <
81 - le16_to_cpu(es->s_min_extra_isize))
82 - sbi->s_want_extra_isize =
83 - le16_to_cpu(es->s_min_extra_isize);
84 - }
85 - }
86 - /* Check if enough inode space is available */
87 - if (EXT4_GOOD_OLD_INODE_SIZE + sbi->s_want_extra_isize >
88 - sbi->s_inode_size) {
89 - sbi->s_want_extra_isize = sizeof(struct ext4_inode) -
90 - EXT4_GOOD_OLD_INODE_SIZE;
91 - ext4_msg(sb, KERN_INFO, "required extra inode space not"
92 - "available");
93 - }
94 + ext4_clamp_want_extra_isize(sb);
95
96 ext4_set_resv_clusters(sb);
97
98 @@ -5197,6 +5205,8 @@ static int ext4_remount(struct super_blo
99 goto restore_opts;
100 }
101
102 + ext4_clamp_want_extra_isize(sb);
103 +
104 if ((old_opts.s_mount_opt & EXT4_MOUNT_JOURNAL_CHECKSUM) ^
105 test_opt(sb, JOURNAL_CHECKSUM)) {
106 ext4_msg(sb, KERN_ERR, "changing journal_checksum "