@@ -262,6 +262,24 @@ typedef enum {
FS_ENCRYPT,
} fscrypt_direction_t;
+/**
+ * fscrypt_uses_extent_encryption() -- whether an inode uses per-extent
+ * encryption
+ *
+ * @param inode the inode in question
+ *
+ * Return: true if the inode uses per-extent encryption infos, false otherwise
+ */
+static inline bool fscrypt_uses_extent_encryption(const struct inode *inode)
+{
+ // Non-regular files don't have extents
+ if (!S_ISREG(inode->i_mode))
+ return false;
+
+ // No filesystem currently uses per-extent infos
+ return false;
+}
+
/**
* fscrypt_get_inode_info() - get the fscrypt_info for a particular inode
*
@@ -622,6 +622,22 @@ int fscrypt_get_encryption_info(struct inode *inode, bool allow_unsupported)
if (fscrypt_has_encryption_key(inode))
return 0;
+ if (fscrypt_uses_extent_encryption(inode)) {
+ struct dentry *dentry = d_find_any_alias(inode);
+ struct dentry *parent_dentry = dget_parent(dentry);
+ struct inode *dir = parent_dentry->d_inode;
+ struct fscrypt_info *dir_info = fscrypt_get_inode_info(dir);
+ struct fscrypt_master_key *mk = NULL;
+
+ if (dir_info)
+ mk = dir_info->ci_master_key;
+
+ fscrypt_set_inode_info(inode, dir_info, mk);
+ dput(parent_dentry);
+ dput(dentry);
+ return 0;
+ }
+
res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx));
if (res < 0) {
if (res == -ERANGE && allow_unsupported)
@@ -704,6 +720,14 @@ int fscrypt_prepare_new_inode(struct inode *dir, struct inode *inode,
*encrypt_ret = true;
+ if (fscrypt_uses_extent_encryption(inode)) {
+ struct fscrypt_info *dir_info = fscrypt_get_inode_info(dir);
+
+ fscrypt_set_inode_info(inode, dir_info,
+ dir_info->ci_master_key);
+ return 0;
+ }
+
get_random_bytes(nonce, FSCRYPT_FILE_NONCE_SIZE);
return fscrypt_setup_encryption_info(inode, policy, nonce,
IS_CASEFOLDED(dir) &&
@@ -720,7 +744,8 @@ EXPORT_SYMBOL_GPL(fscrypt_prepare_new_inode);
*/
void fscrypt_put_encryption_info(struct inode *inode)
{
- put_crypt_info(fscrypt_get_inode_info(inode));
+ if (!fscrypt_uses_extent_encryption(inode))
+ put_crypt_info(fscrypt_get_inode_info(inode));
fscrypt_set_inode_info(inode, NULL, NULL);
}
EXPORT_SYMBOL(fscrypt_put_encryption_info);
For regular files in filesystems using extent-based encryption, the corresponding inode does not need a fscrypt_info structure of its own as for inode-based fscrypt, as they will not be encrypting anything using it. Any new extents written to the inode will use a per-extent info structure derived from the inode's parent directory's info structure. However, it is convenient to cache that parent directory's info structure in the inode; it makes it easy to check whether the parents' info exists, so that we don't have to get and put a reference to the parent inode every time we want to get the inode info. So do that. Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me> --- fs/crypto/fscrypt_private.h | 18 ++++++++++++++++++ fs/crypto/keysetup.c | 27 ++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-)