aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/fscrypt.h
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2020-09-16 21:11:35 -0700
committerEric Biggers <ebiggers@google.com>2020-09-22 06:48:49 -0700
commitac4acb1f4b2b6b7e8d913537cccec8789903e164 (patch)
treee6999a5cae6cb884d844450d19b59da6049186e5 /include/linux/fscrypt.h
parentfscrypt: move fscrypt_prepare_symlink() out-of-line (diff)
downloadlinux-dev-ac4acb1f4b2b6b7e8d913537cccec8789903e164.tar.xz
linux-dev-ac4acb1f4b2b6b7e8d913537cccec8789903e164.zip
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 ed318a6cc0b6 ("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: Jaegeuk Kim <jaegeuk@kernel.org> Acked-by: Jeff Layton <jlayton@kernel.org> Link: https://lore.kernel.org/r/20200917041136.178600-13-ebiggers@kernel.org Signed-off-by: Eric Biggers <ebiggers@google.com>
Diffstat (limited to 'include/linux/fscrypt.h')
-rw-r--r--include/linux/fscrypt.h40
1 files changed, 13 insertions, 27 deletions
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 39e7397a3f10..b3b0c5675c6b 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -21,7 +21,7 @@
#define FS_CRYPTO_BLOCK_SIZE 16
-union fscrypt_context;
+union fscrypt_policy;
struct fscrypt_info;
struct seq_file;
@@ -62,8 +62,7 @@ struct fscrypt_operations {
int (*get_context)(struct inode *inode, void *ctx, size_t len);
int (*set_context)(struct inode *inode, const void *ctx, size_t len,
void *fs_data);
- const union fscrypt_context *(*get_dummy_context)(
- struct super_block *sb);
+ const union fscrypt_policy *(*get_dummy_policy)(struct super_block *sb);
bool (*empty_dir)(struct inode *inode);
unsigned int max_namelen;
bool (*has_stable_inodes)(struct super_block *sb);
@@ -101,14 +100,6 @@ static inline bool fscrypt_needs_contents_encryption(const struct inode *inode)
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
* 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);
int fscrypt_has_permitted_context(struct inode *parent, struct inode *child);
int fscrypt_set_context(struct inode *inode, void *fs_data);
-struct fscrypt_dummy_context {
- const union fscrypt_context *ctx;
+struct fscrypt_dummy_policy {
+ const union fscrypt_policy *policy;
};
-int fscrypt_set_test_dummy_encryption(struct super_block *sb,
- const substring_t *arg,
- struct fscrypt_dummy_context *dummy_ctx);
+int fscrypt_set_test_dummy_encryption(
+ struct super_block *sb,
+ const substring_t *arg,
+ struct fscrypt_dummy_policy *dummy_policy);
void fscrypt_show_test_dummy_encryption(struct seq_file *seq, char sep,
struct super_block *sb);
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);
- dummy_ctx->ctx = NULL;
+ kfree(dummy_policy->policy);
+ dummy_policy->policy = NULL;
}
/* keyring.c */
@@ -250,12 +242,6 @@ static inline bool fscrypt_needs_contents_encryption(const struct inode *inode)
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)
{
}
@@ -346,7 +332,7 @@ static inline int fscrypt_set_context(struct inode *inode, void *fs_data)
return -EOPNOTSUPP;
}
-struct fscrypt_dummy_context {
+struct fscrypt_dummy_policy {
};
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
-fscrypt_free_dummy_context(struct fscrypt_dummy_context *dummy_ctx)
+fscrypt_free_dummy_policy(struct fscrypt_dummy_policy *dummy_policy)
{
}