]> www.infradead.org Git - users/hch/misc.git/commitdiff
fscrypt: replace raw loads of info pointer with helper function
authorEric Biggers <ebiggers@kernel.org>
Sun, 10 Aug 2025 07:56:54 +0000 (00:56 -0700)
committerChristian Brauner <brauner@kernel.org>
Thu, 21 Aug 2025 11:58:06 +0000 (13:58 +0200)
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>
fs/crypto/bio.c
fs/crypto/crypto.c
fs/crypto/fname.c
fs/crypto/hooks.c
fs/crypto/inline_crypt.c
fs/crypto/policy.c
include/linux/fscrypt.h

index 486fcb2ecf13eb883d5ee867d791aa604008d879..0d746de4cd10397ab51211acbf9172529438e712 100644 (file)
@@ -113,7 +113,7 @@ out:
 int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
                          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_size = 1U << du_bits;
        const unsigned int du_per_page_bits = PAGE_SHIFT - du_bits;
index b6ccab524fdef82190278dea17b87fafa8d6d3b4..07f9cbfe3ea4115b8fcc881ae5154b3c3e898c04 100644 (file)
@@ -173,7 +173,7 @@ struct page *fscrypt_encrypt_pagecache_blocks(struct folio *folio,
                size_t len, size_t offs, gfp_t gfp_flags)
 {
        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_size = 1U << du_bits;
        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))
                return -EOPNOTSUPP;
-       return fscrypt_crypt_data_unit(inode->i_crypt_info, FS_ENCRYPT,
-                                      lblk_num, page, page, len, offs);
+       return fscrypt_crypt_data_unit(fscrypt_get_inode_info_raw(inode),
+                                      FS_ENCRYPT, lblk_num, page, page, len,
+                                      offs);
 }
 EXPORT_SYMBOL(fscrypt_encrypt_block_inplace);
 
@@ -255,7 +256,7 @@ int fscrypt_decrypt_pagecache_blocks(struct folio *folio, size_t len,
                                     size_t offs)
 {
        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_size = 1U << 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))
                return -EOPNOTSUPP;
-       return fscrypt_crypt_data_unit(inode->i_crypt_info, FS_DECRYPT,
-                                      lblk_num, page, page, len, offs);
+       return fscrypt_crypt_data_unit(fscrypt_get_inode_info_raw(inode),
+                                      FS_DECRYPT, lblk_num, page, page, len,
+                                      offs);
 }
 EXPORT_SYMBOL(fscrypt_decrypt_block_inplace);
 
index f9f6713e144f7a0835c8305dfadd414e285c9184..fb77ad1ca74a2c78a688815811bbac714d1006c8 100644 (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,
                          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;
        SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm);
        union fscrypt_iv iv;
@@ -138,7 +138,7 @@ static int fname_decrypt(const struct inode *inode,
                         const struct fscrypt_str *iname,
                         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;
        SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm);
        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,
                                  u32 max_len, u32 *encrypted_len_ret)
 {
-       return __fscrypt_fname_encrypted_size(&inode->i_crypt_info->ci_policy,
-                                             orig_len, max_len,
+       const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
+
+       return __fscrypt_fname_encrypted_size(&ci->ci_policy, orig_len, max_len,
                                              encrypted_len_ret);
 }
 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)
 {
-       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);
 
index e0b32ac841f765e8389f8b808da56a838b011c8d..7a5d4c168c49e64d936abb8e75a689eb619609ef 100644 (file)
@@ -199,7 +199,7 @@ int fscrypt_prepare_setflags(struct inode *inode,
                err = fscrypt_require_key(inode);
                if (err)
                        return err;
-               ci = inode->i_crypt_info;
+               ci = fscrypt_get_inode_info_raw(inode);
                if (ci->ci_policy.version != FSCRYPT_POLICY_V2)
                        return -EINVAL;
                mk = ci->ci_master_key;
index caaff809765b29413798aa7e4766288b64c140a8..5dee7c498bc8c54a23f7565d25c317de2c66386f 100644 (file)
@@ -263,7 +263,7 @@ int fscrypt_derive_sw_secret(struct super_block *sb,
 
 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);
 
@@ -307,7 +307,7 @@ void fscrypt_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode,
 
        if (!fscrypt_inode_uses_inline_crypto(inode))
                return;
-       ci = inode->i_crypt_info;
+       ci = fscrypt_get_inode_info_raw(inode);
 
        fscrypt_generate_dun(ci, first_lblk, dun);
        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)
 {
        const struct bio_crypt_ctx *bc = bio->bi_crypt_context;
+       const struct fscrypt_inode_info *ci;
        u64 next_dun[BLK_CRYPTO_DUN_ARRAY_SIZE];
 
        if (!!bc != fscrypt_inode_uses_inline_crypto(inode))
                return false;
        if (!bc)
                return true;
+       ci = fscrypt_get_inode_info_raw(inode);
 
        /*
         * 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
         * 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;
 
-       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);
 }
 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)
                return nr_blocks;
 
-       ci = inode->i_crypt_info;
+       ci = fscrypt_get_inode_info_raw(inode);
        if (!(fscrypt_policy_flags(&ci->ci_policy) &
              FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32))
                return nr_blocks;
index 6ad30ae07c065cfa05afe9933f908fa577d46fdc..9d51f3500de376de3723ce54dea308496178c023 100644 (file)
@@ -727,7 +727,7 @@ const union fscrypt_policy *fscrypt_policy_to_inherit(struct inode *dir)
                err = fscrypt_require_key(dir);
                if (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);
@@ -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)
 {
-       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) !=
                        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)
 {
-       struct fscrypt_inode_info *ci = inode->i_crypt_info;
+       struct fscrypt_inode_info *ci;
        union fscrypt_context ctx;
        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
         * delayed key setup that requires the inode number.
         */
+       ci = fscrypt_get_inode_info_raw(inode);
        if (ci->ci_policy.version == FSCRYPT_POLICY_V2 &&
            (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32))
                fscrypt_hash_inode_number(ci, ci->ci_master_key);
index 10dd161690a28c2bfd44491157144264c922719b..23c5198612d1a6bcc65160e72e1371e024344d2c 100644 (file)
@@ -195,6 +195,22 @@ struct fscrypt_operations {
 int fscrypt_d_revalidate(struct inode *dir, const struct qstr *name,
                         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 *
 fscrypt_get_inode_info(const struct inode *inode)
 {