@@ -108,7 +108,7 @@ int fscrypt_crypt_block(const struct inode *inode, fscrypt_direction_t rw,
DECLARE_CRYPTO_WAIT(wait);
struct scatterlist dst, src;
struct fscrypt_info *ci = inode->i_crypt_info;
- struct crypto_skcipher *tfm = ci->ci_enc_key.tfm;
+ struct crypto_skcipher *tfm = ci->ci_enc_key->tfm;
int res = 0;
if (WARN_ON_ONCE(len <= 0))
@@ -101,7 +101,7 @@ int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,
struct skcipher_request *req = NULL;
DECLARE_CRYPTO_WAIT(wait);
const struct fscrypt_info *ci = inode->i_crypt_info;
- struct crypto_skcipher *tfm = ci->ci_enc_key.tfm;
+ struct crypto_skcipher *tfm = ci->ci_enc_key->tfm;
union fscrypt_iv iv;
struct scatterlist sg;
int res;
@@ -158,7 +158,7 @@ static int fname_decrypt(const struct inode *inode,
DECLARE_CRYPTO_WAIT(wait);
struct scatterlist src_sg, dst_sg;
const struct fscrypt_info *ci = inode->i_crypt_info;
- struct crypto_skcipher *tfm = ci->ci_enc_key.tfm;
+ struct crypto_skcipher *tfm = ci->ci_enc_key->tfm;
union fscrypt_iv iv;
int res;
@@ -198,7 +198,7 @@ struct fscrypt_prepared_key {
struct fscrypt_info {
/* The key in a form prepared for actual encryption/decryption */
- struct fscrypt_prepared_key ci_enc_key;
+ struct fscrypt_prepared_key *ci_enc_key;
/* True if ci_enc_key should be freed when this fscrypt_info is freed */
bool ci_owns_key;
@@ -273,7 +273,7 @@ void fscrypt_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode,
ci = inode->i_crypt_info;
fscrypt_generate_dun(ci, first_lblk, dun);
- bio_crypt_set_ctx(bio, ci->ci_enc_key.blk_key, dun, gfp_mask);
+ bio_crypt_set_ctx(bio, ci->ci_enc_key->blk_key, dun, gfp_mask);
}
EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx);
@@ -360,7 +360,7 @@ bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode,
* uses the same pointer. I.e., there's currently no need to support
* merging requests where the keys are the same but the pointers differ.
*/
- if (bc->bc_key != inode->i_crypt_info->ci_enc_key.blk_key)
+ if (bc->bc_key != inode->i_crypt_info->ci_enc_key->blk_key)
return false;
fscrypt_generate_dun(inode->i_crypt_info, next_lblk, next_dun);
@@ -192,7 +192,11 @@ void fscrypt_destroy_prepared_key(struct super_block *sb,
int fscrypt_set_per_file_enc_key(struct fscrypt_info *ci, const u8 *raw_key)
{
ci->ci_owns_key = true;
- return fscrypt_prepare_key(&ci->ci_enc_key, raw_key, ci);
+ ci->ci_enc_key = kzalloc(sizeof(*ci->ci_enc_key), GFP_KERNEL);
+ if (!ci->ci_enc_key)
+ return -ENOMEM;
+
+ return fscrypt_prepare_key(ci->ci_enc_key, raw_key, ci);
}
static struct fscrypt_prepared_key *
@@ -311,14 +315,14 @@ static int setup_mode_prepared_key(struct fscrypt_info *ci,
return PTR_ERR(prep_key);
if (fscrypt_is_key_prepared(prep_key, ci)) {
- ci->ci_enc_key = *prep_key;
+ ci->ci_enc_key = prep_key;
return 0;
}
err = setup_new_mode_prepared_key(mk, prep_key, ci);
if (err)
return err;
- ci->ci_enc_key = *prep_key;
+ ci->ci_enc_key = prep_key;
return 0;
}
@@ -582,9 +586,11 @@ static void put_crypt_info(struct fscrypt_info *ci)
if (ci->ci_direct_key)
fscrypt_put_direct_key(ci->ci_direct_key);
- else if (ci->ci_owns_key)
+ else if (ci->ci_owns_key) {
fscrypt_destroy_prepared_key(ci->ci_inode->i_sb,
- &ci->ci_enc_key);
+ ci->ci_enc_key);
+ kfree_sensitive(ci->ci_enc_key);
+ }
mk = ci->ci_master_key;
if (mk) {
@@ -259,7 +259,7 @@ static int setup_v1_file_key_direct(struct fscrypt_info *ci,
if (IS_ERR(dk))
return PTR_ERR(dk);
ci->ci_direct_key = dk;
- ci->ci_enc_key = dk->dk_key;
+ ci->ci_enc_key = &dk->dk_key;
return 0;
}
Adding a layer of indirection between infos and prepared keys makes everything clearer at the cost of another pointer. Now everyone sharing a prepared key within a direct key or a master key have the same pointer to the single prepared key. Followups move information from the crypt_info into the prepared key, which ends up reducing memory usage slightly. Additionally, it makes asynchronous freeing of prepared keys possible later. So this change makes crypt_info->ci_enc_key a pointer and updates all users thereof. Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me> --- fs/crypto/crypto.c | 2 +- fs/crypto/fname.c | 4 ++-- fs/crypto/fscrypt_private.h | 2 +- fs/crypto/inline_crypt.c | 4 ++-- fs/crypto/keysetup.c | 16 +++++++++++----- fs/crypto/keysetup_v1.c | 2 +- 6 files changed, 18 insertions(+), 12 deletions(-)