@@ -85,9 +85,10 @@ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num,
memset(iv, 0, ci->ci_mode->ivsize);
if (flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) {
+ u64 ino = fscrypt_get_info_ino(ci);
WARN_ON_ONCE(lblk_num > U32_MAX);
- WARN_ON_ONCE(ci->ci_inode->i_ino > U32_MAX);
- lblk_num |= (u64)ci->ci_inode->i_ino << 32;
+ WARN_ON_ONCE(ino > U32_MAX);
+ lblk_num |= (u64)ino << 32;
} else if (flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) {
WARN_ON_ONCE(lblk_num > U32_MAX);
lblk_num = (u32)(ci->ci_hashed_ino + lblk_num);
@@ -344,6 +344,24 @@ fscrypt_get_lblk_info(const struct inode *inode, u64 lblk, u64 *offset,
return fscrypt_get_info(inode);
}
+/**
+ * fscrypt_get_info_ino() - get the ino or ino equivalent for an info
+ *
+ * @ci: the fscrypt_info in question
+ *
+ * For inode-based encryption, this will return the info's inode's ino.
+ * For extent-based encryption, this will return the extent's ino equivalent
+ * or 0 if it is not implemented.
+ */
+static inline u64 fscrypt_get_info_ino(const struct fscrypt_info *ci)
+{
+ if (ci->ci_inode)
+ return ci->ci_inode->i_ino;
+ if (!ci->ci_sb->s_cop->get_extent_ino_equivalent)
+ return 0;
+ return ci->ci_sb->s_cop->get_extent_ino_equivalent(ci->ci_info_ptr);
+}
+
/* crypto.c */
extern struct kmem_cache *fscrypt_info_cachep;
int fscrypt_initialize(unsigned int cop_flags);
@@ -933,11 +933,11 @@ static int check_for_busy_inodes(struct super_block *sb,
{
/* select an example file to show for debugging purposes */
- struct inode *inode =
+ struct fscrypt_info *ci =
list_first_entry(&mk->mk_active_infos,
struct fscrypt_info,
- ci_master_key_link)->ci_inode;
- ino = inode->i_ino;
+ ci_master_key_link);
+ ino = fscrypt_get_info_ino(ci);
}
spin_unlock(&mk->mk_active_infos_lock);
@@ -266,11 +266,11 @@ int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
void fscrypt_hash_inode_number(struct fscrypt_info *ci,
const struct fscrypt_master_key *mk)
{
- WARN_ON(ci->ci_inode->i_ino == 0);
+ u64 ino = fscrypt_get_info_ino(ci);
+ WARN_ON(ino == 0);
WARN_ON(!mk->mk_ino_hash_key_initialized);
- ci->ci_hashed_ino = (u32)siphash_1u64(ci->ci_inode->i_ino,
- &mk->mk_ino_hash_key);
+ ci->ci_hashed_ino = (u32)siphash_1u64(ino, &mk->mk_ino_hash_key);
}
static int fscrypt_setup_iv_ino_lblk_32_key(struct fscrypt_info *ci,
@@ -308,7 +308,7 @@ static int fscrypt_setup_iv_ino_lblk_32_key(struct fscrypt_info *ci,
* New inodes may not have an inode number assigned yet.
* Hashing their inode number is delayed until later.
*/
- if (ci->ci_inode->i_ino)
+ if (fscrypt_get_info_ino(ci))
fscrypt_hash_inode_number(ci, mk);
return 0;
}
@@ -129,6 +129,15 @@ struct fscrypt_operations {
*/
bool (*empty_dir)(struct inode *inode);
+ /*
+ * Inform the filesystem that a particular extent must forget its
+ * fscrypt_info (for instance, for a key removal).
+ *
+ * @info_ptr: a pointer to the location storing the fscrypt_info pointer
+ * within the opaque extent whose info is to be freed
+ */
+ void (*forget_extent_info)(struct fscrypt_info **info_ptr);
+
/*
* Check whether the filesystem's inode numbers and UUID are stable,
* meaning that they will never be changed even by offline operations
@@ -160,6 +169,15 @@ struct fscrypt_operations {
void (*get_ino_and_lblk_bits)(struct super_block *sb,
int *ino_bits_ret, int *lblk_bits_ret);
+ /*
+ * Get the inode number equivalent for filesystems using per-extent
+ * encryption keys.
+ *
+ * This function only needs to be implemented if support for one of the
+ * FSCRYPT_POLICY_FLAG_IV_INO_* flags is needed.
+ */
+ u64 (*get_extent_ino_equivalent)(struct fscrypt_info **info_ptr);
+
/*
* Return an array of pointers to the block devices to which the
* filesystem may write encrypted file contents, NULL if the filesystem
Since per-extent infos are not tied to inodes, an ino-based policy cannot access the inode's i_ino to get the necessary information. Instead, this adds an optional fscrypt_operation pointer to get the ino equivalent for an extent, adds a wrapper to get the ino for an info, and uses this wrapper everywhere where the ci's inode's i_ino is currently accessed. Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me> --- fs/crypto/crypto.c | 5 +++-- fs/crypto/fscrypt_private.h | 18 ++++++++++++++++++ fs/crypto/keyring.c | 6 +++--- fs/crypto/keysetup.c | 8 ++++---- include/linux/fscrypt.h | 18 ++++++++++++++++++ 5 files changed, 46 insertions(+), 9 deletions(-)