fscrypt: replace raw loads of info pointer with helper function

Add and use a helper function fscrypt_get_inode_info_raw().  It loads an
inode's fscrypt info pointer using a raw dereference, which is
appropriate when the caller knows the key setup already happened.

This eliminates most occurrences of inode::i_crypt_info in the source,
in preparation for replacing that with a filesystem-specific field.

Co-developed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
Link: https://lore.kernel.org/20250810075706.172910-2-ebiggers@kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>
pull/1354/merge
Eric Biggers 2025-08-10 00:56:54 -07:00 committed by Christian Brauner
parent 8f5ae30d69
commit 6c9468aad2
No known key found for this signature in database
GPG Key ID: 91C61BC06578DCA2
7 changed files with 43 additions and 21 deletions

View File

@ -113,7 +113,7 @@ out:
int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
sector_t pblk, unsigned int len) sector_t pblk, unsigned int len)
{ {
const struct fscrypt_inode_info *ci = inode->i_crypt_info; const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
const unsigned int du_bits = ci->ci_data_unit_bits; const unsigned int du_bits = ci->ci_data_unit_bits;
const unsigned int du_size = 1U << du_bits; const unsigned int du_size = 1U << du_bits;
const unsigned int du_per_page_bits = PAGE_SHIFT - du_bits; const unsigned int du_per_page_bits = PAGE_SHIFT - du_bits;

View File

@ -173,7 +173,7 @@ struct page *fscrypt_encrypt_pagecache_blocks(struct folio *folio,
size_t len, size_t offs, gfp_t gfp_flags) size_t len, size_t offs, gfp_t gfp_flags)
{ {
const struct inode *inode = folio->mapping->host; const struct inode *inode = folio->mapping->host;
const struct fscrypt_inode_info *ci = inode->i_crypt_info; const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
const unsigned int du_bits = ci->ci_data_unit_bits; const unsigned int du_bits = ci->ci_data_unit_bits;
const unsigned int du_size = 1U << du_bits; const unsigned int du_size = 1U << du_bits;
struct page *ciphertext_page; struct page *ciphertext_page;
@ -232,8 +232,9 @@ int fscrypt_encrypt_block_inplace(const struct inode *inode, struct page *page,
{ {
if (WARN_ON_ONCE(inode->i_sb->s_cop->supports_subblock_data_units)) if (WARN_ON_ONCE(inode->i_sb->s_cop->supports_subblock_data_units))
return -EOPNOTSUPP; return -EOPNOTSUPP;
return fscrypt_crypt_data_unit(inode->i_crypt_info, FS_ENCRYPT, return fscrypt_crypt_data_unit(fscrypt_get_inode_info_raw(inode),
lblk_num, page, page, len, offs); FS_ENCRYPT, lblk_num, page, page, len,
offs);
} }
EXPORT_SYMBOL(fscrypt_encrypt_block_inplace); EXPORT_SYMBOL(fscrypt_encrypt_block_inplace);
@ -255,7 +256,7 @@ int fscrypt_decrypt_pagecache_blocks(struct folio *folio, size_t len,
size_t offs) size_t offs)
{ {
const struct inode *inode = folio->mapping->host; const struct inode *inode = folio->mapping->host;
const struct fscrypt_inode_info *ci = inode->i_crypt_info; const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
const unsigned int du_bits = ci->ci_data_unit_bits; const unsigned int du_bits = ci->ci_data_unit_bits;
const unsigned int du_size = 1U << du_bits; const unsigned int du_size = 1U << du_bits;
u64 index = ((u64)folio->index << (PAGE_SHIFT - du_bits)) + u64 index = ((u64)folio->index << (PAGE_SHIFT - du_bits)) +
@ -305,8 +306,9 @@ int fscrypt_decrypt_block_inplace(const struct inode *inode, struct page *page,
{ {
if (WARN_ON_ONCE(inode->i_sb->s_cop->supports_subblock_data_units)) if (WARN_ON_ONCE(inode->i_sb->s_cop->supports_subblock_data_units))
return -EOPNOTSUPP; return -EOPNOTSUPP;
return fscrypt_crypt_data_unit(inode->i_crypt_info, FS_DECRYPT, return fscrypt_crypt_data_unit(fscrypt_get_inode_info_raw(inode),
lblk_num, page, page, len, offs); FS_DECRYPT, lblk_num, page, page, len,
offs);
} }
EXPORT_SYMBOL(fscrypt_decrypt_block_inplace); EXPORT_SYMBOL(fscrypt_decrypt_block_inplace);

View File

@ -94,7 +94,7 @@ static inline bool fscrypt_is_dot_dotdot(const struct qstr *str)
int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname, int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,
u8 *out, unsigned int olen) u8 *out, unsigned int olen)
{ {
const struct fscrypt_inode_info *ci = inode->i_crypt_info; const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
struct crypto_sync_skcipher *tfm = ci->ci_enc_key.tfm; struct crypto_sync_skcipher *tfm = ci->ci_enc_key.tfm;
SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm); SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm);
union fscrypt_iv iv; union fscrypt_iv iv;
@ -138,7 +138,7 @@ static int fname_decrypt(const struct inode *inode,
const struct fscrypt_str *iname, const struct fscrypt_str *iname,
struct fscrypt_str *oname) struct fscrypt_str *oname)
{ {
const struct fscrypt_inode_info *ci = inode->i_crypt_info; const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
struct crypto_sync_skcipher *tfm = ci->ci_enc_key.tfm; struct crypto_sync_skcipher *tfm = ci->ci_enc_key.tfm;
SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm); SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm);
union fscrypt_iv iv; union fscrypt_iv iv;
@ -274,8 +274,9 @@ bool __fscrypt_fname_encrypted_size(const union fscrypt_policy *policy,
bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len, bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len,
u32 max_len, u32 *encrypted_len_ret) u32 max_len, u32 *encrypted_len_ret)
{ {
return __fscrypt_fname_encrypted_size(&inode->i_crypt_info->ci_policy, const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
orig_len, max_len,
return __fscrypt_fname_encrypted_size(&ci->ci_policy, orig_len, max_len,
encrypted_len_ret); encrypted_len_ret);
} }
EXPORT_SYMBOL_GPL(fscrypt_fname_encrypted_size); EXPORT_SYMBOL_GPL(fscrypt_fname_encrypted_size);
@ -543,7 +544,7 @@ EXPORT_SYMBOL_GPL(fscrypt_match_name);
*/ */
u64 fscrypt_fname_siphash(const struct inode *dir, const struct qstr *name) u64 fscrypt_fname_siphash(const struct inode *dir, const struct qstr *name)
{ {
const struct fscrypt_inode_info *ci = dir->i_crypt_info; const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(dir);
WARN_ON_ONCE(!ci->ci_dirhash_key_initialized); WARN_ON_ONCE(!ci->ci_dirhash_key_initialized);

View File

@ -199,7 +199,7 @@ int fscrypt_prepare_setflags(struct inode *inode,
err = fscrypt_require_key(inode); err = fscrypt_require_key(inode);
if (err) if (err)
return err; return err;
ci = inode->i_crypt_info; ci = fscrypt_get_inode_info_raw(inode);
if (ci->ci_policy.version != FSCRYPT_POLICY_V2) if (ci->ci_policy.version != FSCRYPT_POLICY_V2)
return -EINVAL; return -EINVAL;
mk = ci->ci_master_key; mk = ci->ci_master_key;

View File

@ -263,7 +263,7 @@ int fscrypt_derive_sw_secret(struct super_block *sb,
bool __fscrypt_inode_uses_inline_crypto(const struct inode *inode) bool __fscrypt_inode_uses_inline_crypto(const struct inode *inode)
{ {
return inode->i_crypt_info->ci_inlinecrypt; return fscrypt_get_inode_info_raw(inode)->ci_inlinecrypt;
} }
EXPORT_SYMBOL_GPL(__fscrypt_inode_uses_inline_crypto); EXPORT_SYMBOL_GPL(__fscrypt_inode_uses_inline_crypto);
@ -307,7 +307,7 @@ void fscrypt_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode,
if (!fscrypt_inode_uses_inline_crypto(inode)) if (!fscrypt_inode_uses_inline_crypto(inode))
return; return;
ci = inode->i_crypt_info; ci = fscrypt_get_inode_info_raw(inode);
fscrypt_generate_dun(ci, first_lblk, dun); 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);
@ -385,22 +385,24 @@ bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode,
u64 next_lblk) u64 next_lblk)
{ {
const struct bio_crypt_ctx *bc = bio->bi_crypt_context; const struct bio_crypt_ctx *bc = bio->bi_crypt_context;
const struct fscrypt_inode_info *ci;
u64 next_dun[BLK_CRYPTO_DUN_ARRAY_SIZE]; u64 next_dun[BLK_CRYPTO_DUN_ARRAY_SIZE];
if (!!bc != fscrypt_inode_uses_inline_crypto(inode)) if (!!bc != fscrypt_inode_uses_inline_crypto(inode))
return false; return false;
if (!bc) if (!bc)
return true; return true;
ci = fscrypt_get_inode_info_raw(inode);
/* /*
* Comparing the key pointers is good enough, as all I/O for each key * Comparing the key pointers is good enough, as all I/O for each key
* uses the same pointer. I.e., there's currently no need to support * 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. * 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 != ci->ci_enc_key.blk_key)
return false; return false;
fscrypt_generate_dun(inode->i_crypt_info, next_lblk, next_dun); fscrypt_generate_dun(ci, next_lblk, next_dun);
return bio_crypt_dun_is_contiguous(bc, bio->bi_iter.bi_size, next_dun); return bio_crypt_dun_is_contiguous(bc, bio->bi_iter.bi_size, next_dun);
} }
EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio); EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio);
@ -502,7 +504,7 @@ u64 fscrypt_limit_io_blocks(const struct inode *inode, u64 lblk, u64 nr_blocks)
if (nr_blocks <= 1) if (nr_blocks <= 1)
return nr_blocks; return nr_blocks;
ci = inode->i_crypt_info; ci = fscrypt_get_inode_info_raw(inode);
if (!(fscrypt_policy_flags(&ci->ci_policy) & if (!(fscrypt_policy_flags(&ci->ci_policy) &
FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32))
return nr_blocks; return nr_blocks;

View File

@ -727,7 +727,7 @@ const union fscrypt_policy *fscrypt_policy_to_inherit(struct inode *dir)
err = fscrypt_require_key(dir); err = fscrypt_require_key(dir);
if (err) if (err)
return ERR_PTR(err); return ERR_PTR(err);
return &dir->i_crypt_info->ci_policy; return &fscrypt_get_inode_info_raw(dir)->ci_policy;
} }
return fscrypt_get_dummy_policy(dir->i_sb); return fscrypt_get_dummy_policy(dir->i_sb);
@ -746,7 +746,7 @@ const union fscrypt_policy *fscrypt_policy_to_inherit(struct inode *dir)
*/ */
int fscrypt_context_for_new_inode(void *ctx, struct inode *inode) int fscrypt_context_for_new_inode(void *ctx, struct inode *inode)
{ {
struct fscrypt_inode_info *ci = inode->i_crypt_info; struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
BUILD_BUG_ON(sizeof(union fscrypt_context) != BUILD_BUG_ON(sizeof(union fscrypt_context) !=
FSCRYPT_SET_CONTEXT_MAX_SIZE); FSCRYPT_SET_CONTEXT_MAX_SIZE);
@ -771,7 +771,7 @@ EXPORT_SYMBOL_GPL(fscrypt_context_for_new_inode);
*/ */
int fscrypt_set_context(struct inode *inode, void *fs_data) int fscrypt_set_context(struct inode *inode, void *fs_data)
{ {
struct fscrypt_inode_info *ci = inode->i_crypt_info; struct fscrypt_inode_info *ci;
union fscrypt_context ctx; union fscrypt_context ctx;
int ctxsize; int ctxsize;
@ -783,6 +783,7 @@ int fscrypt_set_context(struct inode *inode, void *fs_data)
* This may be the first time the inode number is available, so do any * This may be the first time the inode number is available, so do any
* delayed key setup that requires the inode number. * delayed key setup that requires the inode number.
*/ */
ci = fscrypt_get_inode_info_raw(inode);
if (ci->ci_policy.version == FSCRYPT_POLICY_V2 && if (ci->ci_policy.version == FSCRYPT_POLICY_V2 &&
(ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32))
fscrypt_hash_inode_number(ci, ci->ci_master_key); fscrypt_hash_inode_number(ci, ci->ci_master_key);

View File

@ -195,6 +195,22 @@ struct fscrypt_operations {
int fscrypt_d_revalidate(struct inode *dir, const struct qstr *name, int fscrypt_d_revalidate(struct inode *dir, const struct qstr *name,
struct dentry *dentry, unsigned int flags); struct dentry *dentry, unsigned int flags);
/*
* Load the inode's fscrypt info pointer, using a raw dereference. Since this
* uses a raw dereference with no memory barrier, it is appropriate to use only
* when the caller knows the inode's key setup already happened, resulting in
* non-NULL fscrypt info. E.g., the file contents en/decryption functions use
* this, since fscrypt_file_open() set up the key.
*/
static inline struct fscrypt_inode_info *
fscrypt_get_inode_info_raw(const struct inode *inode)
{
struct fscrypt_inode_info *ci = inode->i_crypt_info;
VFS_WARN_ON_ONCE(ci == NULL);
return ci;
}
static inline struct fscrypt_inode_info * static inline struct fscrypt_inode_info *
fscrypt_get_inode_info(const struct inode *inode) fscrypt_get_inode_info(const struct inode *inode)
{ {