summaryrefslogtreecommitdiff
path: root/include/linux/fscrypt.h
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2020-05-12 16:32:50 -0700
committerEric Biggers <ebiggers@google.com>2020-05-18 20:21:48 -0700
commited318a6cc0b620440e65f48eb527dc3df7269ce4 (patch)
tree6a437738295b51caeb302d22e258866084190a05 /include/linux/fscrypt.h
parentcdeb21da1783afe26a827eb62d61084f93720be9 (diff)
fscrypt: support test_dummy_encryption=v2
v1 encryption policies are deprecated in favor of v2, and some new features (e.g. encryption+casefolding) are only being added for v2. Therefore, the "test_dummy_encryption" mount option (which is used for encryption I/O testing with xfstests) needs to support v2 policies. To do this, extend its syntax to be "test_dummy_encryption=v1" or "test_dummy_encryption=v2". The existing "test_dummy_encryption" (no argument) also continues to be accepted, to specify the default setting -- currently v1, but the next patch changes it to v2. To cleanly support both v1 and v2 while also making it easy to support specifying other encryption settings in the future (say, accepting "$contents_mode:$filenames_mode:v2"), make ext4 and f2fs maintain a pointer to the dummy fscrypt_context rather than using mount flags. To avoid concurrency issues, don't allow test_dummy_encryption to be set or changed during a remount. (The former restriction is new, but xfstests doesn't run into it, so no one should notice.) Tested with 'gce-xfstests -c {ext4,f2fs}/encrypt -g auto'. On ext4, there are two regressions, both of which are test bugs: ext4/023 and ext4/028 fail because they set an xattr and expect it to be stored inline, but the increase in size of the fscrypt_context from 24 to 40 bytes causes this xattr to be spilled into an external block. Link: https://lore.kernel.org/r/20200512233251.118314-4-ebiggers@kernel.org Acked-by: Jaegeuk Kim <jaegeuk@kernel.org> Reviewed-by: Theodore Ts'o <tytso@mit.edu> Signed-off-by: Eric Biggers <ebiggers@google.com>
Diffstat (limited to 'include/linux/fscrypt.h')
-rw-r--r--include/linux/fscrypt.h51
1 files changed, 44 insertions, 7 deletions
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 0e0c7ad19383..2862ca5fea33 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -15,12 +15,15 @@
#include <linux/fs.h>
#include <linux/mm.h>
+#include <linux/parser.h>
#include <linux/slab.h>
#include <uapi/linux/fscrypt.h>
#define FS_CRYPTO_BLOCK_SIZE 16
+union fscrypt_context;
struct fscrypt_info;
+struct seq_file;
struct fscrypt_str {
unsigned char *name;
@@ -59,7 +62,8 @@ 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);
- bool (*dummy_context)(struct inode *inode);
+ const union fscrypt_context *(*get_dummy_context)(
+ struct super_block *sb);
bool (*empty_dir)(struct inode *inode);
unsigned int max_namelen;
bool (*has_stable_inodes)(struct super_block *sb);
@@ -89,10 +93,12 @@ static inline bool fscrypt_needs_contents_encryption(const struct inode *inode)
return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode);
}
-static inline bool fscrypt_dummy_context_enabled(struct inode *inode)
+static inline const union fscrypt_context *
+fscrypt_get_dummy_context(struct super_block *sb)
{
- return inode->i_sb->s_cop->dummy_context &&
- inode->i_sb->s_cop->dummy_context(inode);
+ if (!sb->s_cop->get_dummy_context)
+ return NULL;
+ return sb->s_cop->get_dummy_context(sb);
}
/*
@@ -145,6 +151,22 @@ int fscrypt_has_permitted_context(struct inode *parent, struct inode *child);
int fscrypt_inherit_context(struct inode *parent, struct inode *child,
void *fs_data, bool preload);
+struct fscrypt_dummy_context {
+ const union fscrypt_context *ctx;
+};
+
+int fscrypt_set_test_dummy_encryption(struct super_block *sb,
+ const substring_t *arg,
+ struct fscrypt_dummy_context *dummy_ctx);
+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)
+{
+ kfree(dummy_ctx->ctx);
+ dummy_ctx->ctx = NULL;
+}
+
/* keyring.c */
void fscrypt_sb_free(struct super_block *sb);
int fscrypt_ioctl_add_key(struct file *filp, void __user *arg);
@@ -219,9 +241,10 @@ static inline bool fscrypt_needs_contents_encryption(const struct inode *inode)
return false;
}
-static inline bool fscrypt_dummy_context_enabled(struct inode *inode)
+static inline const union fscrypt_context *
+fscrypt_get_dummy_context(struct super_block *sb)
{
- return false;
+ return NULL;
}
static inline void fscrypt_handle_d_move(struct dentry *dentry)
@@ -316,6 +339,20 @@ static inline int fscrypt_inherit_context(struct inode *parent,
return -EOPNOTSUPP;
}
+struct fscrypt_dummy_context {
+};
+
+static inline 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)
+{
+}
+
/* keyring.c */
static inline void fscrypt_sb_free(struct super_block *sb)
{
@@ -677,7 +714,7 @@ static inline int fscrypt_prepare_symlink(struct inode *dir,
unsigned int max_len,
struct fscrypt_str *disk_link)
{
- if (IS_ENCRYPTED(dir) || fscrypt_dummy_context_enabled(dir))
+ if (IS_ENCRYPTED(dir) || fscrypt_get_dummy_context(dir->i_sb) != NULL)
return __fscrypt_prepare_symlink(dir, len, max_len, disk_link);
disk_link->name = (unsigned char *)target;