add patch export-sysfs-casefold-feature-attribute
[ext4-patch-queue.git] / fix-use-after-free-race-with-debug_want_extra_isize
blob1b0c7d6bb616cbe73058e1b36ff0316eb73ff167
1 ext4: fix use-after-free race with debug_want_extra_isize
3 From: Barret Rhoden <brho@google.com>
5 When remounting with debug_want_extra_isize, we were not performing the
6 same checks that we do during a normal mount.  That allowed us to set a
7 value for s_want_extra_isize that reached outside the s_inode_size.
9 Fixes: e2b911c53584 ("ext4: clean up feature test macros with predicate functions")
10 Reported-by: syzbot+f584efa0ac7213c226b7@syzkaller.appspotmail.com
11 Reviewed-by: Jan Kara <jack@suse.cz>
12 Signed-off-by: Barret Rhoden <brho@google.com>
13 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
14 Cc: stable@vger.kernel.org
15 ---
17 - Updated tags
19 Thanks for the review!
21  fs/ext4/super.c | 58 +++++++++++++++++++++++++++++--------------------
22  1 file changed, 34 insertions(+), 24 deletions(-)
24 diff --git a/fs/ext4/super.c b/fs/ext4/super.c
25 index 6ed4eb81e674..184944d4d8d1 100644
26 --- a/fs/ext4/super.c
27 +++ b/fs/ext4/super.c
28 @@ -3513,6 +3513,37 @@ int ext4_calculate_overhead(struct super_block *sb)
29         return 0;
30  }
32 +static void ext4_clamp_want_extra_isize(struct super_block *sb)
34 +       struct ext4_sb_info *sbi = EXT4_SB(sb);
35 +       struct ext4_super_block *es = sbi->s_es;
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 +       }
63  static void ext4_set_resv_clusters(struct super_block *sb)
64  {
65         ext4_fsblk_t resv_clusters;
66 @@ -4387,30 +4418,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
67         } else if (ret)
68                 goto failed_mount4a;
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);
96         ext4_set_resv_clusters(sb);
98 @@ -5194,6 +5202,8 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
99                 goto restore_opts;
100         }
102 +       ext4_clamp_want_extra_isize(sb);
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 "
107 -- 
108 2.21.0.392.gf8f6787159e-goog