Commit ac4acb1f authored by Eric Biggers's avatar Eric Biggers

fscrypt: handle test_dummy_encryption in more logical way

The behavior of the test_dummy_encryption mount option is that when a
new file (or directory or symlink) is created in an unencrypted
directory, it's automatically encrypted using a dummy encryption policy.
That's it; in particular, the encryption (or lack thereof) of existing
files (or directories or symlinks) doesn't change.

Unfortunately the implementation of test_dummy_encryption is a bit weird
and confusing.  When test_dummy_encryption is enabled and a file is
being created in an unencrypted directory, we set up an encryption key
(->i_crypt_info) for the directory.  This isn't actually used to do any
encryption, however, since the directory is still unencrypted!  Instead,
->i_crypt_info is only used for inheriting the encryption policy.

One consequence of this is that the filesystem ends up providing a
"dummy context" (policy + nonce) instead of a "dummy policy".  In
commit ed318a6c ("fscrypt: support test_dummy_encryption=v2"), I
mistakenly thought this was required.  However, actually the nonce only
ends up being used to derive a key that is never used.

Another consequence of this implementation is that it allows for
'inode->i_crypt_info != NULL && !IS_ENCRYPTED(inode)', which is an edge
case that can be forgotten about.  For example, currently
FS_IOC_GET_ENCRYPTION_POLICY on an unencrypted directory may return the
dummy encryption policy when the filesystem is mounted with
test_dummy_encryption.  That seems like the wrong thing to do, since
again, the directory itself is not actually encrypted.

Therefore, switch to a more logical and maintainable implementation
where the dummy encryption policy inheritance is done without setting up
keys for unencrypted directories.  This involves:

- Adding a function fscrypt_policy_to_inherit() which returns the
  encryption policy to inherit from a directory.  This can be a real
  policy, a dummy policy, or no policy.

- Replacing struct fscrypt_dummy_context, ->get_dummy_context(), etc.
  with struct fscrypt_dummy_policy, ->get_dummy_policy(), etc.

- Making fscrypt_fname_encrypted_size() take an fscrypt_policy instead
  of an inode.
Acked-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
Acked-by: default avatarJeff Layton <jlayton@kernel.org>
Link: https://lore.kernel.org/r/20200917041136.178600-13-ebiggers@kernel.orgSigned-off-by: default avatarEric Biggers <ebiggers@google.com>
parent 31114726
...@@ -242,11 +242,11 @@ static int base64_decode(const char *src, int len, u8 *dst) ...@@ -242,11 +242,11 @@ static int base64_decode(const char *src, int len, u8 *dst)
return cp - dst; return cp - dst;
} }
bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len, bool fscrypt_fname_encrypted_size(const union fscrypt_policy *policy,
u32 max_len, u32 *encrypted_len_ret) u32 orig_len, u32 max_len,
u32 *encrypted_len_ret)
{ {
const struct fscrypt_info *ci = inode->i_crypt_info; int padding = 4 << (fscrypt_policy_flags(policy) &
int padding = 4 << (fscrypt_policy_flags(&ci->ci_policy) &
FSCRYPT_POLICY_FLAGS_PAD_MASK); FSCRYPT_POLICY_FLAGS_PAD_MASK);
u32 encrypted_len; u32 encrypted_len;
...@@ -418,7 +418,8 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname, ...@@ -418,7 +418,8 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname,
return ret; return ret;
if (fscrypt_has_encryption_key(dir)) { if (fscrypt_has_encryption_key(dir)) {
if (!fscrypt_fname_encrypted_size(dir, iname->len, if (!fscrypt_fname_encrypted_size(&dir->i_crypt_info->ci_policy,
iname->len,
dir->i_sb->s_cop->max_namelen, dir->i_sb->s_cop->max_namelen,
&fname->crypto_buf.len)) &fname->crypto_buf.len))
return -ENAMETOOLONG; return -ENAMETOOLONG;
......
...@@ -291,8 +291,9 @@ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num, ...@@ -291,8 +291,9 @@ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num,
/* fname.c */ /* fname.c */
int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname, int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,
u8 *out, unsigned int olen); u8 *out, unsigned int olen);
bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len, bool fscrypt_fname_encrypted_size(const union fscrypt_policy *policy,
u32 max_len, u32 *encrypted_len_ret); u32 orig_len, u32 max_len,
u32 *encrypted_len_ret);
extern const struct dentry_operations fscrypt_d_ops; extern const struct dentry_operations fscrypt_d_ops;
/* hkdf.c */ /* hkdf.c */
...@@ -592,5 +593,6 @@ bool fscrypt_supported_policy(const union fscrypt_policy *policy_u, ...@@ -592,5 +593,6 @@ bool fscrypt_supported_policy(const union fscrypt_policy *policy_u,
int fscrypt_policy_from_context(union fscrypt_policy *policy_u, int fscrypt_policy_from_context(union fscrypt_policy *policy_u,
const union fscrypt_context *ctx_u, const union fscrypt_context *ctx_u,
int ctx_size); int ctx_size);
const union fscrypt_policy *fscrypt_policy_to_inherit(struct inode *dir);
#endif /* _FSCRYPT_PRIVATE_H */ #endif /* _FSCRYPT_PRIVATE_H */
...@@ -193,30 +193,24 @@ int fscrypt_prepare_symlink(struct inode *dir, const char *target, ...@@ -193,30 +193,24 @@ int fscrypt_prepare_symlink(struct inode *dir, const char *target,
unsigned int len, unsigned int max_len, unsigned int len, unsigned int max_len,
struct fscrypt_str *disk_link) struct fscrypt_str *disk_link)
{ {
int err; const union fscrypt_policy *policy;
if (!IS_ENCRYPTED(dir) && !fscrypt_get_dummy_context(dir->i_sb)) { /*
* To calculate the size of the encrypted symlink target we need to know
* the amount of NUL padding, which is determined by the flags set in
* the encryption policy which will be inherited from the directory.
*/
policy = fscrypt_policy_to_inherit(dir);
if (policy == NULL) {
/* Not encrypted */
disk_link->name = (unsigned char *)target; disk_link->name = (unsigned char *)target;
disk_link->len = len + 1; disk_link->len = len + 1;
if (disk_link->len > max_len) if (disk_link->len > max_len)
return -ENAMETOOLONG; return -ENAMETOOLONG;
return 0; return 0;
} }
if (IS_ERR(policy))
/* return PTR_ERR(policy);
* To calculate the size of the encrypted symlink target we need to know
* the amount of NUL padding, which is determined by the flags set in
* the encryption policy which will be inherited from the directory.
* The easiest way to get access to this is to just load the directory's
* fscrypt_info, since we'll need it to create the dir_entry anyway.
*
* Note: in test_dummy_encryption mode, @dir may be unencrypted.
*/
err = fscrypt_get_encryption_info(dir);
if (err)
return err;
if (!fscrypt_has_encryption_key(dir))
return -ENOKEY;
/* /*
* Calculate the size of the encrypted symlink and verify it won't * Calculate the size of the encrypted symlink and verify it won't
...@@ -229,7 +223,7 @@ int fscrypt_prepare_symlink(struct inode *dir, const char *target, ...@@ -229,7 +223,7 @@ int fscrypt_prepare_symlink(struct inode *dir, const char *target,
* counting it (even though it is meaningless for ciphertext) is simpler * counting it (even though it is meaningless for ciphertext) is simpler
* for now since filesystems will assume it is there and subtract it. * for now since filesystems will assume it is there and subtract it.
*/ */
if (!fscrypt_fname_encrypted_size(dir, len, if (!fscrypt_fname_encrypted_size(policy, len,
max_len - sizeof(struct fscrypt_symlink_data), max_len - sizeof(struct fscrypt_symlink_data),
&disk_link->len)) &disk_link->len))
return -ENAMETOOLONG; return -ENAMETOOLONG;
......
...@@ -547,7 +547,7 @@ fscrypt_setup_encryption_info(struct inode *inode, ...@@ -547,7 +547,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
/** /**
* fscrypt_get_encryption_info() - set up an inode's encryption key * fscrypt_get_encryption_info() - set up an inode's encryption key
* @inode: the inode to set up the key for * @inode: the inode to set up the key for. Must be encrypted.
* *
* Set up ->i_crypt_info, if it hasn't already been done. * Set up ->i_crypt_info, if it hasn't already been done.
* *
...@@ -569,18 +569,8 @@ int fscrypt_get_encryption_info(struct inode *inode) ...@@ -569,18 +569,8 @@ int fscrypt_get_encryption_info(struct inode *inode)
res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx));
if (res < 0) { if (res < 0) {
const union fscrypt_context *dummy_ctx = fscrypt_warn(inode, "Error %d getting encryption context", res);
fscrypt_get_dummy_context(inode->i_sb); return res;
if (IS_ENCRYPTED(inode) || !dummy_ctx) {
fscrypt_warn(inode,
"Error %d getting encryption context",
res);
return res;
}
/* Fake up a context for an unencrypted directory */
res = fscrypt_context_size(dummy_ctx);
memcpy(&ctx, dummy_ctx, res);
} }
res = fscrypt_policy_from_context(&policy, &ctx, res); res = fscrypt_policy_from_context(&policy, &ctx, res);
...@@ -627,17 +617,14 @@ EXPORT_SYMBOL(fscrypt_get_encryption_info); ...@@ -627,17 +617,14 @@ EXPORT_SYMBOL(fscrypt_get_encryption_info);
int fscrypt_prepare_new_inode(struct inode *dir, struct inode *inode, int fscrypt_prepare_new_inode(struct inode *dir, struct inode *inode,
bool *encrypt_ret) bool *encrypt_ret)
{ {
int err; const union fscrypt_policy *policy;
u8 nonce[FSCRYPT_FILE_NONCE_SIZE]; u8 nonce[FSCRYPT_FILE_NONCE_SIZE];
if (!IS_ENCRYPTED(dir) && fscrypt_get_dummy_context(dir->i_sb) == NULL) policy = fscrypt_policy_to_inherit(dir);
if (policy == NULL)
return 0; return 0;
if (IS_ERR(policy))
err = fscrypt_get_encryption_info(dir); return PTR_ERR(policy);
if (err)
return err;
if (!fscrypt_has_encryption_key(dir))
return -ENOKEY;
if (WARN_ON_ONCE(inode->i_mode == 0)) if (WARN_ON_ONCE(inode->i_mode == 0))
return -EINVAL; return -EINVAL;
...@@ -654,9 +641,7 @@ int fscrypt_prepare_new_inode(struct inode *dir, struct inode *inode, ...@@ -654,9 +641,7 @@ int fscrypt_prepare_new_inode(struct inode *dir, struct inode *inode,
*encrypt_ret = true; *encrypt_ret = true;
get_random_bytes(nonce, FSCRYPT_FILE_NONCE_SIZE); get_random_bytes(nonce, FSCRYPT_FILE_NONCE_SIZE);
return fscrypt_setup_encryption_info(inode, return fscrypt_setup_encryption_info(inode, policy, nonce,
&dir->i_crypt_info->ci_policy,
nonce,
IS_CASEFOLDED(dir) && IS_CASEFOLDED(dir) &&
S_ISDIR(inode->i_mode)); S_ISDIR(inode->i_mode));
} }
......
...@@ -32,6 +32,14 @@ bool fscrypt_policies_equal(const union fscrypt_policy *policy1, ...@@ -32,6 +32,14 @@ bool fscrypt_policies_equal(const union fscrypt_policy *policy1,
return !memcmp(policy1, policy2, fscrypt_policy_size(policy1)); return !memcmp(policy1, policy2, fscrypt_policy_size(policy1));
} }
static const union fscrypt_policy *
fscrypt_get_dummy_policy(struct super_block *sb)
{
if (!sb->s_cop->get_dummy_policy)
return NULL;
return sb->s_cop->get_dummy_policy(sb);
}
static bool fscrypt_valid_enc_modes(u32 contents_mode, u32 filenames_mode) static bool fscrypt_valid_enc_modes(u32 contents_mode, u32 filenames_mode)
{ {
if (contents_mode == FSCRYPT_MODE_AES_256_XTS && if (contents_mode == FSCRYPT_MODE_AES_256_XTS &&
...@@ -628,6 +636,25 @@ int fscrypt_has_permitted_context(struct inode *parent, struct inode *child) ...@@ -628,6 +636,25 @@ int fscrypt_has_permitted_context(struct inode *parent, struct inode *child)
} }
EXPORT_SYMBOL(fscrypt_has_permitted_context); EXPORT_SYMBOL(fscrypt_has_permitted_context);
/*
* Return the encryption policy that new files in the directory will inherit, or
* NULL if none, or an ERR_PTR() on error. If the directory is encrypted, also
* ensure that its key is set up, so that the new filename can be encrypted.
*/
const union fscrypt_policy *fscrypt_policy_to_inherit(struct inode *dir)
{
int err;
if (IS_ENCRYPTED(dir)) {
err = fscrypt_require_key(dir);
if (err)
return ERR_PTR(err);
return &dir->i_crypt_info->ci_policy;
}
return fscrypt_get_dummy_policy(dir->i_sb);
}
/** /**
* fscrypt_set_context() - Set the fscrypt context of a new inode * fscrypt_set_context() - Set the fscrypt context of a new inode
* @inode: a new inode * @inode: a new inode
...@@ -672,31 +699,28 @@ EXPORT_SYMBOL_GPL(fscrypt_set_context); ...@@ -672,31 +699,28 @@ EXPORT_SYMBOL_GPL(fscrypt_set_context);
* @sb: the filesystem on which test_dummy_encryption is being specified * @sb: the filesystem on which test_dummy_encryption is being specified
* @arg: the argument to the test_dummy_encryption option. * @arg: the argument to the test_dummy_encryption option.
* If no argument was specified, then @arg->from == NULL. * If no argument was specified, then @arg->from == NULL.
* @dummy_ctx: the filesystem's current dummy context (input/output, see below) * @dummy_policy: the filesystem's current dummy policy (input/output, see
* below)
* *
* Handle the test_dummy_encryption mount option by creating a dummy encryption * Handle the test_dummy_encryption mount option by creating a dummy encryption
* context, saving it in @dummy_ctx, and adding the corresponding dummy * policy, saving it in @dummy_policy, and adding the corresponding dummy
* encryption key to the filesystem. If the @dummy_ctx is already set, then * encryption key to the filesystem. If the @dummy_policy is already set, then
* instead validate that it matches @arg. Don't support changing it via * instead validate that it matches @arg. Don't support changing it via
* remount, as that is difficult to do safely. * remount, as that is difficult to do safely.
* *
* The reason we use an fscrypt_context rather than an fscrypt_policy is because * Return: 0 on success (dummy policy set, or the same policy is already set);
* we mustn't generate a new nonce each time we access a dummy-encrypted * -EEXIST if a different dummy policy is already set;
* directory, as that would change the way filenames are encrypted.
*
* Return: 0 on success (dummy context set, or the same context is already set);
* -EEXIST if a different dummy context is already set;
* or another -errno value. * or another -errno value.
*/ */
int fscrypt_set_test_dummy_encryption(struct super_block *sb, int fscrypt_set_test_dummy_encryption(struct super_block *sb,
const substring_t *arg, const substring_t *arg,
struct fscrypt_dummy_context *dummy_ctx) struct fscrypt_dummy_policy *dummy_policy)
{ {
const char *argstr = "v2"; const char *argstr = "v2";
const char *argstr_to_free = NULL; const char *argstr_to_free = NULL;
struct fscrypt_key_specifier key_spec = { 0 }; struct fscrypt_key_specifier key_spec = { 0 };
int version; int version;
union fscrypt_context *ctx = NULL; union fscrypt_policy *policy = NULL;
int err; int err;
if (arg->from) { if (arg->from) {
...@@ -706,12 +730,12 @@ int fscrypt_set_test_dummy_encryption(struct super_block *sb, ...@@ -706,12 +730,12 @@ int fscrypt_set_test_dummy_encryption(struct super_block *sb,
} }
if (!strcmp(argstr, "v1")) { if (!strcmp(argstr, "v1")) {
version = FSCRYPT_CONTEXT_V1; version = FSCRYPT_POLICY_V1;
key_spec.type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR; key_spec.type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR;
memset(key_spec.u.descriptor, 0x42, memset(key_spec.u.descriptor, 0x42,
FSCRYPT_KEY_DESCRIPTOR_SIZE); FSCRYPT_KEY_DESCRIPTOR_SIZE);
} else if (!strcmp(argstr, "v2")) { } else if (!strcmp(argstr, "v2")) {
version = FSCRYPT_CONTEXT_V2; version = FSCRYPT_POLICY_V2;
key_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER; key_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER;
/* key_spec.u.identifier gets filled in when adding the key */ /* key_spec.u.identifier gets filled in when adding the key */
} else { } else {
...@@ -719,21 +743,8 @@ int fscrypt_set_test_dummy_encryption(struct super_block *sb, ...@@ -719,21 +743,8 @@ int fscrypt_set_test_dummy_encryption(struct super_block *sb,
goto out; goto out;
} }
if (dummy_ctx->ctx) { policy = kzalloc(sizeof(*policy), GFP_KERNEL);
/* if (!policy) {
* Note: if we ever make test_dummy_encryption support
* specifying other encryption settings, such as the encryption
* modes, we'll need to compare those settings here.
*/
if (dummy_ctx->ctx->version == version)
err = 0;
else
err = -EEXIST;
goto out;
}
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx) {
err = -ENOMEM; err = -ENOMEM;
goto out; goto out;
} }
...@@ -742,18 +753,18 @@ int fscrypt_set_test_dummy_encryption(struct super_block *sb, ...@@ -742,18 +753,18 @@ int fscrypt_set_test_dummy_encryption(struct super_block *sb,
if (err) if (err)
goto out; goto out;
ctx->version = version; policy->version = version;
switch (ctx->version) { switch (policy->version) {
case FSCRYPT_CONTEXT_V1: case FSCRYPT_POLICY_V1:
ctx->v1.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS; policy->v1.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS;
ctx->v1.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS; policy->v1.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS;
memcpy(ctx->v1.master_key_descriptor, key_spec.u.descriptor, memcpy(policy->v1.master_key_descriptor, key_spec.u.descriptor,
FSCRYPT_KEY_DESCRIPTOR_SIZE); FSCRYPT_KEY_DESCRIPTOR_SIZE);
break; break;
case FSCRYPT_CONTEXT_V2: case FSCRYPT_POLICY_V2:
ctx->v2.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS; policy->v2.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS;
ctx->v2.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS; policy->v2.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS;
memcpy(ctx->v2.master_key_identifier, key_spec.u.identifier, memcpy(policy->v2.master_key_identifier, key_spec.u.identifier,
FSCRYPT_KEY_IDENTIFIER_SIZE); FSCRYPT_KEY_IDENTIFIER_SIZE);
break; break;
default: default:
...@@ -761,11 +772,19 @@ int fscrypt_set_test_dummy_encryption(struct super_block *sb, ...@@ -761,11 +772,19 @@ int fscrypt_set_test_dummy_encryption(struct super_block *sb,
err = -EINVAL; err = -EINVAL;
goto out; goto out;
} }
dummy_ctx->ctx = ctx;
ctx = NULL; if (dummy_policy->policy) {
if (fscrypt_policies_equal(policy, dummy_policy->policy))
err = 0;
else
err = -EEXIST;
goto out;
}
dummy_policy->policy = policy;
policy = NULL;
err = 0; err = 0;
out: out:
kfree(ctx); kfree(policy);
kfree(argstr_to_free); kfree(argstr_to_free);
return err; return err;
} }
...@@ -783,10 +802,16 @@ EXPORT_SYMBOL_GPL(fscrypt_set_test_dummy_encryption); ...@@ -783,10 +802,16 @@ EXPORT_SYMBOL_GPL(fscrypt_set_test_dummy_encryption);
void fscrypt_show_test_dummy_encryption(struct seq_file *seq, char sep, void fscrypt_show_test_dummy_encryption(struct seq_file *seq, char sep,
struct super_block *sb) struct super_block *sb)
{ {
const union fscrypt_context *ctx = fscrypt_get_dummy_context(sb); const union fscrypt_policy *policy = fscrypt_get_dummy_policy(sb);
int vers;
if (!ctx) if (!policy)
return; return;
seq_printf(seq, "%ctest_dummy_encryption=v%d", sep, ctx->version);
vers = policy->version;
if (vers == FSCRYPT_POLICY_V1) /* Handle numbering quirk */
vers = 1;
seq_printf(seq, "%ctest_dummy_encryption=v%d", sep, vers);
} }
EXPORT_SYMBOL_GPL(fscrypt_show_test_dummy_encryption); EXPORT_SYMBOL_GPL(fscrypt_show_test_dummy_encryption);
...@@ -1401,7 +1401,7 @@ struct ext4_super_block { ...@@ -1401,7 +1401,7 @@ struct ext4_super_block {
#define EXT4_MF_FS_ABORTED 0x0002 /* Fatal error detected */ #define EXT4_MF_FS_ABORTED 0x0002 /* Fatal error detected */
#ifdef CONFIG_FS_ENCRYPTION #ifdef CONFIG_FS_ENCRYPTION
#define DUMMY_ENCRYPTION_ENABLED(sbi) ((sbi)->s_dummy_enc_ctx.ctx != NULL) #define DUMMY_ENCRYPTION_ENABLED(sbi) ((sbi)->s_dummy_enc_policy.policy != NULL)
#else #else
#define DUMMY_ENCRYPTION_ENABLED(sbi) (0) #define DUMMY_ENCRYPTION_ENABLED(sbi) (0)
#endif #endif
...@@ -1596,8 +1596,8 @@ struct ext4_sb_info { ...@@ -1596,8 +1596,8 @@ struct ext4_sb_info {
atomic_t s_warning_count; atomic_t s_warning_count;
atomic_t s_msg_count; atomic_t s_msg_count;
/* Encryption context for '-o test_dummy_encryption' */ /* Encryption policy for '-o test_dummy_encryption' */
struct fscrypt_dummy_context s_dummy_enc_ctx; struct fscrypt_dummy_policy s_dummy_enc_policy;
/* /*
* Barrier between writepages ops and changing any inode's JOURNAL_DATA * Barrier between writepages ops and changing any inode's JOURNAL_DATA
......
...@@ -1104,7 +1104,7 @@ static void ext4_put_super(struct super_block *sb) ...@@ -1104,7 +1104,7 @@ static void ext4_put_super(struct super_block *sb)
crypto_free_shash(sbi->s_chksum_driver); crypto_free_shash(sbi->s_chksum_driver);
kfree(sbi->s_blockgroup_lock); kfree(sbi->s_blockgroup_lock);
fs_put_dax(sbi->s_daxdev); fs_put_dax(sbi->s_daxdev);
fscrypt_free_dummy_context(&sbi->s_dummy_enc_ctx); fscrypt_free_dummy_policy(&sbi->s_dummy_enc_policy);
#ifdef CONFIG_UNICODE #ifdef CONFIG_UNICODE
utf8_unload(sbi->s_encoding); utf8_unload(sbi->s_encoding);
#endif #endif
...@@ -1392,10 +1392,9 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len, ...@@ -1392,10 +1392,9 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
return res; return res;
} }
static const union fscrypt_context * static const union fscrypt_policy *ext4_get_dummy_policy(struct super_block *sb)
ext4_get_dummy_context(struct super_block *sb)
{ {
return EXT4_SB(sb)->s_dummy_enc_ctx.ctx; return EXT4_SB(sb)->s_dummy_enc_policy.policy;
} }
static bool ext4_has_stable_inodes(struct super_block *sb) static bool ext4_has_stable_inodes(struct super_block *sb)
...@@ -1414,7 +1413,7 @@ static const struct fscrypt_operations ext4_cryptops = { ...@@ -1414,7 +1413,7 @@ static const struct fscrypt_operations ext4_cryptops = {
.key_prefix = "ext4:", .key_prefix = "ext4:",
.get_context = ext4_get_context, .get_context = ext4_get_context,
.set_context = ext4_set_context, .set_context = ext4_set_context,
.get_dummy_context = ext4_get_dummy_context, .get_dummy_policy = ext4_get_dummy_policy,
.empty_dir = ext4_empty_dir, .empty_dir = ext4_empty_dir,
.max_namelen = EXT4_NAME_LEN, .max_namelen = EXT4_NAME_LEN,
.has_stable_inodes = ext4_has_stable_inodes, .has_stable_inodes = ext4_has_stable_inodes,
...@@ -1888,12 +1887,13 @@ static int ext4_set_test_dummy_encryption(struct super_block *sb, ...@@ -1888,12 +1887,13 @@ static int ext4_set_test_dummy_encryption(struct super_block *sb,
* needed to allow it to be set or changed during remount. We do allow * needed to allow it to be set or changed during remount. We do allow
* it to be specified during remount, but only if there is no change. * it to be specified during remount, but only if there is no change.
*/ */
if (is_remount && !sbi->s_dummy_enc_ctx.ctx) { if (is_remount && !sbi->s_dummy_enc_policy.policy) {
ext4_msg(sb, KERN_WARNING, ext4_msg(sb, KERN_WARNING,
"Can't set test_dummy_encryption on remount"); "Can't set test_dummy_encryption on remount");
return -1; return -1;
} }
err = fscrypt_set_test_dummy_encryption(sb, arg, &sbi->s_dummy_enc_ctx); err = fscrypt_set_test_dummy_encryption(sb, arg,
&sbi->s_dummy_enc_policy);
if (err) { if (err) {
if (err == -EEXIST) if (err == -EEXIST)
ext4_msg(sb, KERN_WARNING, ext4_msg(sb, KERN_WARNING,
...@@ -4935,7 +4935,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ...@@ -4935,7 +4935,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
for (i = 0; i < EXT4_MAXQUOTAS; i++) for (i = 0; i < EXT4_MAXQUOTAS; i++)
kfree(get_qf_name(sb, sbi, i)); kfree(get_qf_name(sb, sbi, i));
#endif #endif
fscrypt_free_dummy_context(&sbi->s_dummy_enc_ctx); fscrypt_free_dummy_policy(&sbi->s_dummy_enc_policy);
ext4_blkdev_remove(sbi); ext4_blkdev_remove(sbi);
brelse(bh); brelse(bh);
out_fail: out_fail:
......
...@@ -138,7 +138,7 @@ struct f2fs_mount_info { ...@@ -138,7 +138,7 @@ struct f2fs_mount_info {
int fsync_mode; /* fsync policy */ int fsync_mode; /* fsync policy */
int fs_mode; /* fs mode: LFS or ADAPTIVE */ int fs_mode; /* fs mode: LFS or ADAPTIVE */
int bggc_mode; /* bggc mode: off, on or sync */ int bggc_mode; /* bggc mode: off, on or sync */
struct fscrypt_dummy_context dummy_enc_ctx; /* test dummy encryption */ struct fscrypt_dummy_policy dummy_enc_policy; /* test dummy encryption */
block_t unusable_cap_perc; /* percentage for cap */ block_t unusable_cap_perc; /* percentage for cap */
block_t unusable_cap; /* Amount of space allowed to be block_t unusable_cap; /* Amount of space allowed to be
* unusable when disabling checkpoint * unusable when disabling checkpoint
......
...@@ -433,12 +433,12 @@ static int f2fs_set_test_dummy_encryption(struct super_block *sb, ...@@ -433,12 +433,12 @@ static int f2fs_set_test_dummy_encryption(struct super_block *sb,
* needed to allow it to be set or changed during remount. We do allow * needed to allow it to be set or changed during remount. We do allow
* it to be specified during remount, but only if there is no change. * it to be specified during remount, but only if there is no change.
*/ */
if (is_remount && !F2FS_OPTION(sbi).dummy_enc_ctx.ctx) { if (is_remount && !F2FS_OPTION(sbi).dummy_enc_policy.policy) {
f2fs_warn(sbi, "Can't set test_dummy_encryption on remount"); f2fs_warn(sbi, "Can't set test_dummy_encryption on remount");
return -EINVAL; return -EINVAL;
} }
err = fscrypt_set_test_dummy_encryption( err = fscrypt_set_test_dummy_encryption(
sb, arg, &F2FS_OPTION(sbi).dummy_enc_ctx); sb, arg, &F2FS_OPTION(sbi).dummy_enc_policy);
if (err) { if (err) {
if (err == -EEXIST) if (err == -EEXIST)
f2fs_warn(sbi, f2fs_warn(sbi,
...@@ -1275,7 +1275,7 @@ static void f2fs_put_super(struct super_block *sb) ...@@ -1275,7 +1275,7 @@ static void f2fs_put_super(struct super_block *sb)
for (i = 0; i < MAXQUOTAS; i++) for (i = 0; i < MAXQUOTAS; i++)
kfree(F2FS_OPTION(sbi).s_qf_names[i]); kfree(F2FS_OPTION(sbi).s_qf_names[i]);
#endif #endif
fscrypt_free_dummy_context(&F2FS_OPTION(sbi).dummy_enc_ctx); fscrypt_free_dummy_policy(&F2FS_OPTION(sbi).dummy_enc_policy);
destroy_percpu_info(sbi); destroy_percpu_info(sbi);
for (i = 0; i < NR_PAGE_TYPE; i++) for (i = 0; i < NR_PAGE_TYPE; i++)
kvfree(sbi->write_io[i]); kvfree(sbi->write_io[i]);
...@@ -2482,10 +2482,9 @@ static int f2fs_set_context(struct inode *inode, const void *ctx, size_t len, ...@@ -2482,10 +2482,9 @@ static int f2fs_set_context(struct inode *inode, const void *ctx, size_t len,
ctx, len, fs_data, XATTR_CREATE); ctx, len, fs_data, XATTR_CREATE);
} }
static const union fscrypt_context * static const union fscrypt_policy *f2fs_get_dummy_policy(struct super_block *sb)
f2fs_get_dummy_context(struct super_block *sb)
{ {
return F2FS_OPTION(F2FS_SB(sb)).dummy_enc_ctx.ctx; return F2FS_OPTION(F2FS_SB(sb)).dummy_enc_policy.policy;
} }
static bool f2fs_has_stable_inodes(struct super_block *sb) static bool f2fs_has_stable_inodes(struct super_block *sb)
...@@ -2523,7 +2522,7 @@ static const struct fscrypt_operations f2fs_cryptops = { ...@@ -2523,7 +2522,7 @@ static const struct fscrypt_operations f2fs_cryptops = {
.key_prefix = "f2fs:", .key_prefix = "f2fs:",
.get_context = f2fs_get_context, .get_context = f2fs_get_context,
.set_context = f2fs_set_context, .set_context = f2fs_set_context,
.get_dummy_context = f2fs_get_dummy_context, .get_dummy_policy = f2fs_get_dummy_policy,
.empty_dir = f2fs_empty_dir, .empty_dir = f2fs_empty_dir,
.max_namelen = F2FS_NAME_LEN, .max_namelen = F2FS_NAME_LEN,
.has_stable_inodes = f2fs_has_stable_inodes, .has_stable_inodes = f2fs_has_stable_inodes,
...@@ -3864,7 +3863,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -3864,7 +3863,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
for (i = 0; i < MAXQUOTAS; i++) for (i = 0; i < MAXQUOTAS; i++)
kfree(F2FS_OPTION(sbi).s_qf_names[i]); kfree(F2FS_OPTION(sbi).s_qf_names[i]);
#endif #endif
fscrypt_free_dummy_context(&F2FS_OPTION(sbi).dummy_enc_ctx); fscrypt_free_dummy_policy(&F2FS_OPTION(sbi).dummy_enc_policy);
kvfree(options); kvfree(options);
free_sb_buf: free_sb_buf:
kfree(raw_super); kfree(raw_super);
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#define FS_CRYPTO_BLOCK_SIZE 16 #define FS_CRYPTO_BLOCK_SIZE 16
union fscrypt_context; union fscrypt_policy;
struct fscrypt_info; struct fscrypt_info;
struct seq_file; struct seq_file;
...@@ -62,8 +62,7 @@ struct fscrypt_operations { ...@@ -62,8 +62,7 @@ struct fscrypt_operations {
int (*get_context)(struct inode *inode, void *ctx, size_t len); int (*get_context)(struct inode *inode, void *ctx, size_t len);
int (*set_context)(struct inode *inode, const void *ctx, size_t len, int (*set_context)(struct inode *inode, const void *ctx, size_t len,
void *fs_data); void *fs_data);
const union fscrypt_context *(*get_dummy_context)( const union fscrypt_policy *(*get_dummy_policy)(struct super_block *sb);
struct super_block *sb);
bool (*empty_dir)(struct inode *inode); bool (*empty_dir)(struct inode *inode);
unsigned int max_namelen; unsigned int max_namelen;
bool (*has_stable_inodes)(struct super_block *sb); bool (*has_stable_inodes)(struct super_block *sb);
...@@ -101,14 +100,6 @@ static inline bool fscrypt_needs_contents_encryption(const struct inode *inode) ...@@ -101,14 +100,6 @@ static inline bool fscrypt_needs_contents_encryption(const struct inode *inode)
return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode); return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode);
} }
static inline const union fscrypt_context *
fscrypt_get_dummy_context(struct super_block *sb)
{
if (!sb->s_cop->get_dummy_context)
return NULL;
return sb->s_cop->get_dummy_context(sb);
}
/* /*
* When d_splice_alias() moves a directory's encrypted alias to its decrypted * When d_splice_alias() moves a directory's encrypted alias to its decrypted
* alias as a result of the encryption key being added, DCACHE_ENCRYPTED_NAME * alias as a result of the encryption key being added, DCACHE_ENCRYPTED_NAME
...@@ -158,20 +149,21 @@ int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg); ...@@ -158,20 +149,21 @@ int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg);
int fscrypt_has_permitted_context(struct inode *parent, struct inode *child); int fscrypt_has_permitted_context(struct inode *parent, struct inode *child);
int fscrypt_set_context(struct inode *inode, void *fs_data); int fscrypt_set_context(struct inode *inode, void *fs_data);
struct fscrypt_dummy_context { struct fscrypt_dummy_policy {
const union fscrypt_context *ctx; const union fscrypt_policy *policy;
}; };
int fscrypt_set_test_dummy_encryption(struct super_block *sb, int fscrypt_set_test_dummy_encryption(
const substring_t *arg, struct super_block *sb,
struct fscrypt_dummy_context *dummy_ctx); const substring_t *arg,
struct fscrypt_dummy_policy *dummy_policy);
void fscrypt_show_test_dummy_encryption(struct seq_file *seq, char sep, void fscrypt_show_test_dummy_encryption(struct seq_file *seq, char sep,
struct super_block *sb); struct super_block *sb);
static inline void static inline void
fscrypt_free_dummy_context(struct fscrypt_dummy_context *dummy_ctx) fscrypt_free_dummy_policy(struct fscrypt_dummy_policy *dummy_policy)
{ {
kfree(dummy_ctx->ctx); kfree(dummy_policy->policy);
dummy_ctx->ctx = NULL; dummy_policy->policy = NULL;
} }
/* keyring.c */ /* keyring.c */
...@@ -250,12 +242,6 @@ static inline bool fscrypt_needs_contents_encryption(const struct inode *inode) ...@@ -250,12 +242,6 @@ static inline bool fscrypt_needs_contents_encryption(const struct inode *inode)
return false; return false;
} }
static inline const union fscrypt_context *
fscrypt_get_dummy_context(struct super_block *sb)
{
return NULL;
}
static inline void fscrypt_handle_d_move(struct dentry *dentry) static inline void fscrypt_handle_d_move(struct dentry *dentry)
{ {
} }
...@@ -346,7 +332,7 @@ static inline int fscrypt_set_context(struct inode *inode, void *fs_data) ...@@ -346,7 +332,7 @@ static inline int fscrypt_set_context(struct inode *inode, void *fs_data)
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
struct fscrypt_dummy_context { struct fscrypt_dummy_policy {
}; };
static inline void fscrypt_show_test_dummy_encryption(struct seq_file *seq, static inline void fscrypt_show_test_dummy_encryption(struct seq_file *seq,
...@@ -356,7 +342,7 @@ static inline void fscrypt_show_test_dummy_encryption(struct seq_file *seq, ...@@ -356,7 +342,7 @@ static inline void fscrypt_show_test_dummy_encryption(struct seq_file *seq,
} }
static inline void static inline void
fscrypt_free_dummy_context(struct fscrypt_dummy_context *dummy_ctx) fscrypt_free_dummy_policy(struct fscrypt_dummy_policy *dummy_policy)
{ {
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment