summaryrefslogtreecommitdiffstats
path: root/fs/ext4/super.c
diff options
context:
space:
mode:
authorLukas Czerner <lczerner@redhat.com>2022-01-04 15:35:17 +0100
committerTheodore Ts'o <tytso@mit.edu>2022-01-10 13:25:55 -0500
commit13b215a9e657808414a2159b0dec90f1c31ebe05 (patch)
tree4fa10dfd4de3113dcbb75cc0732b8885b88500d0 /fs/ext4/super.c
parent173b6e383d2a204c9921ffc1eca3b87aa2106c33 (diff)
downloadlinux-13b215a9e657808414a2159b0dec90f1c31ebe05.tar.gz
linux-13b215a9e657808414a2159b0dec90f1c31ebe05.tar.bz2
linux-13b215a9e657808414a2159b0dec90f1c31ebe05.zip
ext4: don't use kfree() on rcu protected pointer sbi->s_qf_names
During ext4 mount api rework the commit e6e268cb6822 ("ext4: move quota configuration out of handle_mount_opt()") introduced a bug where we would kfree(sbi->s_qf_names[i]) before assigning the new quota name in ext4_apply_quota_options(). This is wrong because we're using kfree() on rcu prointer that could be simultaneously accessed from ext4_show_quota_options() during remount. Fix it by using rcu_replace_pointer() to replace the old qname with the new one and then kfree_rcu() the old quota name. Also use get_qf_name() instead of sbi->s_qf_names in strcmp() to silence the sparse warning. Fixes: e6e268cb6822 ("ext4: move quota configuration out of handle_mount_opt()") Reported-by: kernel test robot <lkp@intel.com> Signed-off-by: Lukas Czerner <lczerner@redhat.com> Link: https://lore.kernel.org/r/20220104143518.134465-1-lczerner@redhat.com Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r--fs/ext4/super.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 1b55f234e006..72e4dfc9acaf 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -2636,8 +2636,10 @@ static void ext4_apply_quota_options(struct fs_context *fc,
qname = ctx->s_qf_names[i]; /* May be NULL */
ctx->s_qf_names[i] = NULL;
- kfree(sbi->s_qf_names[i]);
- rcu_assign_pointer(sbi->s_qf_names[i], qname);
+ qname = rcu_replace_pointer(sbi->s_qf_names[i], qname,
+ lockdep_is_held(&sb->s_umount));
+ if (qname)
+ kfree_rcu(qname);
set_opt(sb, QUOTA);
}
}
@@ -2691,7 +2693,7 @@ static int ext4_check_quota_consistency(struct fs_context *fc,
goto err_jquota_change;
if (sbi->s_qf_names[i] && ctx->s_qf_names[i] &&
- strcmp(sbi->s_qf_names[i],
+ strcmp(get_qf_name(sb, sbi, i),
ctx->s_qf_names[i]) != 0)
goto err_jquota_specified;
}