Skip to content

Commit 8545605

Browse files
ebiggerstytso
authored andcommitted
ext4: fix up test_dummy_encryption handling for new mount API
Since ext4 was converted to the new mount API, the test_dummy_encryption mount option isn't being handled entirely correctly, because the needed fscrypt_set_test_dummy_encryption() helper function combines parsing/checking/applying into one function. That doesn't work well with the new mount API, which split these into separate steps. This was sort of okay anyway, due to the parsing logic that was copied from fscrypt_set_test_dummy_encryption() into ext4_parse_param(), combined with an additional check in ext4_check_test_dummy_encryption(). However, these overlooked the case of changing the value of test_dummy_encryption on remount, which isn't allowed but ext4 wasn't detecting until ext4_apply_options() when it's too late to fail. Another bug is that if test_dummy_encryption was specified multiple times with an argument, memory was leaked. Fix this up properly by using the new helper functions that allow splitting up the parse/check/apply steps for test_dummy_encryption. Fixes: cebe85d ("ext4: switch to the new mount api") Signed-off-by: Eric Biggers <ebiggers@google.com> Link: https://lore.kernel.org/r/20220526040412.173025-1-ebiggers@kernel.org Signed-off-by: Theodore Ts'o <tytso@mit.edu>
1 parent 4efd9f0 commit 8545605

File tree

1 file changed

+71
-63
lines changed

1 file changed

+71
-63
lines changed

fs/ext4/super.c

Lines changed: 71 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ static struct inode *ext4_get_journal_inode(struct super_block *sb,
8787
static int ext4_validate_options(struct fs_context *fc);
8888
static int ext4_check_opt_consistency(struct fs_context *fc,
8989
struct super_block *sb);
90-
static int ext4_apply_options(struct fs_context *fc, struct super_block *sb);
90+
static void ext4_apply_options(struct fs_context *fc, struct super_block *sb);
9191
static int ext4_parse_param(struct fs_context *fc, struct fs_parameter *param);
9292
static int ext4_get_tree(struct fs_context *fc);
9393
static int ext4_reconfigure(struct fs_context *fc);
@@ -1870,31 +1870,12 @@ ext4_sb_read_encoding(const struct ext4_super_block *es)
18701870
}
18711871
#endif
18721872

1873-
static int ext4_set_test_dummy_encryption(struct super_block *sb, char *arg)
1874-
{
1875-
#ifdef CONFIG_FS_ENCRYPTION
1876-
struct ext4_sb_info *sbi = EXT4_SB(sb);
1877-
int err;
1878-
1879-
err = fscrypt_set_test_dummy_encryption(sb, arg,
1880-
&sbi->s_dummy_enc_policy);
1881-
if (err) {
1882-
ext4_msg(sb, KERN_WARNING,
1883-
"Error while setting test dummy encryption [%d]", err);
1884-
return err;
1885-
}
1886-
ext4_msg(sb, KERN_WARNING, "Test dummy encryption mode enabled");
1887-
#endif
1888-
return 0;
1889-
}
1890-
18911873
#define EXT4_SPEC_JQUOTA (1 << 0)
18921874
#define EXT4_SPEC_JQFMT (1 << 1)
18931875
#define EXT4_SPEC_DATAJ (1 << 2)
18941876
#define EXT4_SPEC_SB_BLOCK (1 << 3)
18951877
#define EXT4_SPEC_JOURNAL_DEV (1 << 4)
18961878
#define EXT4_SPEC_JOURNAL_IOPRIO (1 << 5)
1897-
#define EXT4_SPEC_DUMMY_ENCRYPTION (1 << 6)
18981879
#define EXT4_SPEC_s_want_extra_isize (1 << 7)
18991880
#define EXT4_SPEC_s_max_batch_time (1 << 8)
19001881
#define EXT4_SPEC_s_min_batch_time (1 << 9)
@@ -1911,7 +1892,7 @@ static int ext4_set_test_dummy_encryption(struct super_block *sb, char *arg)
19111892

19121893
struct ext4_fs_context {
19131894
char *s_qf_names[EXT4_MAXQUOTAS];
1914-
char *test_dummy_enc_arg;
1895+
struct fscrypt_dummy_policy dummy_enc_policy;
19151896
int s_jquota_fmt; /* Format of quota to use */
19161897
#ifdef CONFIG_EXT4_DEBUG
19171898
int s_fc_debug_max_replay;
@@ -1953,7 +1934,7 @@ static void ext4_fc_free(struct fs_context *fc)
19531934
for (i = 0; i < EXT4_MAXQUOTAS; i++)
19541935
kfree(ctx->s_qf_names[i]);
19551936

1956-
kfree(ctx->test_dummy_enc_arg);
1937+
fscrypt_free_dummy_policy(&ctx->dummy_enc_policy);
19571938
kfree(ctx);
19581939
}
19591940

@@ -2029,6 +2010,29 @@ static int unnote_qf_name(struct fs_context *fc, int qtype)
20292010
}
20302011
#endif
20312012

2013+
static int ext4_parse_test_dummy_encryption(const struct fs_parameter *param,
2014+
struct ext4_fs_context *ctx)
2015+
{
2016+
int err;
2017+
2018+
if (!IS_ENABLED(CONFIG_FS_ENCRYPTION)) {
2019+
ext4_msg(NULL, KERN_WARNING,
2020+
"test_dummy_encryption option not supported");
2021+
return -EINVAL;
2022+
}
2023+
err = fscrypt_parse_test_dummy_encryption(param,
2024+
&ctx->dummy_enc_policy);
2025+
if (err == -EINVAL) {
2026+
ext4_msg(NULL, KERN_WARNING,
2027+
"Value of option \"%s\" is unrecognized", param->key);
2028+
} else if (err == -EEXIST) {
2029+
ext4_msg(NULL, KERN_WARNING,
2030+
"Conflicting test_dummy_encryption options");
2031+
return -EINVAL;
2032+
}
2033+
return err;
2034+
}
2035+
20322036
#define EXT4_SET_CTX(name) \
20332037
static inline void ctx_set_##name(struct ext4_fs_context *ctx, \
20342038
unsigned long flag) \
@@ -2291,29 +2295,7 @@ static int ext4_parse_param(struct fs_context *fc, struct fs_parameter *param)
22912295
ctx->spec |= EXT4_SPEC_JOURNAL_IOPRIO;
22922296
return 0;
22932297
case Opt_test_dummy_encryption:
2294-
#ifdef CONFIG_FS_ENCRYPTION
2295-
if (param->type == fs_value_is_flag) {
2296-
ctx->spec |= EXT4_SPEC_DUMMY_ENCRYPTION;
2297-
ctx->test_dummy_enc_arg = NULL;
2298-
return 0;
2299-
}
2300-
if (*param->string &&
2301-
!(!strcmp(param->string, "v1") ||
2302-
!strcmp(param->string, "v2"))) {
2303-
ext4_msg(NULL, KERN_WARNING,
2304-
"Value of option \"%s\" is unrecognized",
2305-
param->key);
2306-
return -EINVAL;
2307-
}
2308-
ctx->spec |= EXT4_SPEC_DUMMY_ENCRYPTION;
2309-
ctx->test_dummy_enc_arg = kmemdup_nul(param->string, param->size,
2310-
GFP_KERNEL);
2311-
return 0;
2312-
#else
2313-
ext4_msg(NULL, KERN_WARNING,
2314-
"test_dummy_encryption option not supported");
2315-
return -EINVAL;
2316-
#endif
2298+
return ext4_parse_test_dummy_encryption(param, ctx);
23172299
case Opt_dax:
23182300
case Opt_dax_type:
23192301
#ifdef CONFIG_FS_DAX
@@ -2504,7 +2486,8 @@ static int parse_apply_sb_mount_options(struct super_block *sb,
25042486
if (s_ctx->spec & EXT4_SPEC_JOURNAL_IOPRIO)
25052487
m_ctx->journal_ioprio = s_ctx->journal_ioprio;
25062488

2507-
ret = ext4_apply_options(fc, sb);
2489+
ext4_apply_options(fc, sb);
2490+
ret = 0;
25082491

25092492
out_free:
25102493
if (fc) {
@@ -2673,11 +2656,11 @@ static int ext4_check_quota_consistency(struct fs_context *fc,
26732656
static int ext4_check_test_dummy_encryption(const struct fs_context *fc,
26742657
struct super_block *sb)
26752658
{
2676-
#ifdef CONFIG_FS_ENCRYPTION
26772659
const struct ext4_fs_context *ctx = fc->fs_private;
26782660
const struct ext4_sb_info *sbi = EXT4_SB(sb);
2661+
int err;
26792662

2680-
if (!(ctx->spec & EXT4_SPEC_DUMMY_ENCRYPTION))
2663+
if (!fscrypt_is_dummy_policy_set(&ctx->dummy_enc_policy))
26812664
return 0;
26822665

26832666
if (!ext4_has_feature_encrypt(sb)) {
@@ -2691,14 +2674,46 @@ static int ext4_check_test_dummy_encryption(const struct fs_context *fc,
26912674
* needed to allow it to be set or changed during remount. We do allow
26922675
* it to be specified during remount, but only if there is no change.
26932676
*/
2694-
if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE &&
2695-
!sbi->s_dummy_enc_policy.policy) {
2677+
if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE) {
2678+
if (fscrypt_dummy_policies_equal(&sbi->s_dummy_enc_policy,
2679+
&ctx->dummy_enc_policy))
2680+
return 0;
26962681
ext4_msg(NULL, KERN_WARNING,
2697-
"Can't set test_dummy_encryption on remount");
2682+
"Can't set or change test_dummy_encryption on remount");
26982683
return -EINVAL;
26992684
}
2700-
#endif /* CONFIG_FS_ENCRYPTION */
2701-
return 0;
2685+
/* Also make sure s_mount_opts didn't contain a conflicting value. */
2686+
if (fscrypt_is_dummy_policy_set(&sbi->s_dummy_enc_policy)) {
2687+
if (fscrypt_dummy_policies_equal(&sbi->s_dummy_enc_policy,
2688+
&ctx->dummy_enc_policy))
2689+
return 0;
2690+
ext4_msg(NULL, KERN_WARNING,
2691+
"Conflicting test_dummy_encryption options");
2692+
return -EINVAL;
2693+
}
2694+
/*
2695+
* fscrypt_add_test_dummy_key() technically changes the super_block, so
2696+
* technically it should be delayed until ext4_apply_options() like the
2697+
* other changes. But since we never get here for remounts (see above),
2698+
* and this is the last chance to report errors, we do it here.
2699+
*/
2700+
err = fscrypt_add_test_dummy_key(sb, &ctx->dummy_enc_policy);
2701+
if (err)
2702+
ext4_msg(NULL, KERN_WARNING,
2703+
"Error adding test dummy encryption key [%d]", err);
2704+
return err;
2705+
}
2706+
2707+
static void ext4_apply_test_dummy_encryption(struct ext4_fs_context *ctx,
2708+
struct super_block *sb)
2709+
{
2710+
if (!fscrypt_is_dummy_policy_set(&ctx->dummy_enc_policy) ||
2711+
/* if already set, it was already verified to be the same */
2712+
fscrypt_is_dummy_policy_set(&EXT4_SB(sb)->s_dummy_enc_policy))
2713+
return;
2714+
EXT4_SB(sb)->s_dummy_enc_policy = ctx->dummy_enc_policy;
2715+
memset(&ctx->dummy_enc_policy, 0, sizeof(ctx->dummy_enc_policy));
2716+
ext4_msg(sb, KERN_WARNING, "Test dummy encryption mode enabled");
27022717
}
27032718

27042719
static int ext4_check_opt_consistency(struct fs_context *fc,
@@ -2785,11 +2800,10 @@ static int ext4_check_opt_consistency(struct fs_context *fc,
27852800
return ext4_check_quota_consistency(fc, sb);
27862801
}
27872802

2788-
static int ext4_apply_options(struct fs_context *fc, struct super_block *sb)
2803+
static void ext4_apply_options(struct fs_context *fc, struct super_block *sb)
27892804
{
27902805
struct ext4_fs_context *ctx = fc->fs_private;
27912806
struct ext4_sb_info *sbi = fc->s_fs_info;
2792-
int ret = 0;
27932807

27942808
sbi->s_mount_opt &= ~ctx->mask_s_mount_opt;
27952809
sbi->s_mount_opt |= ctx->vals_s_mount_opt;
@@ -2825,11 +2839,7 @@ static int ext4_apply_options(struct fs_context *fc, struct super_block *sb)
28252839
#endif
28262840

28272841
ext4_apply_quota_options(fc, sb);
2828-
2829-
if (ctx->spec & EXT4_SPEC_DUMMY_ENCRYPTION)
2830-
ret = ext4_set_test_dummy_encryption(sb, ctx->test_dummy_enc_arg);
2831-
2832-
return ret;
2842+
ext4_apply_test_dummy_encryption(ctx, sb);
28332843
}
28342844

28352845

@@ -4552,9 +4562,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
45524562
if (err < 0)
45534563
goto failed_mount;
45544564

4555-
err = ext4_apply_options(fc, sb);
4556-
if (err < 0)
4557-
goto failed_mount;
4565+
ext4_apply_options(fc, sb);
45584566

45594567
#if IS_ENABLED(CONFIG_UNICODE)
45604568
if (ext4_has_feature_casefold(sb) && !sb->s_encoding) {

0 commit comments

Comments
 (0)