Commit dbe0e78d authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/linux

Pull fscrypt updates from Eric Biggers:
 "A few cleanups for fs/crypto/, and another patch to prepare for the
  upcoming CephFS encryption support"

* tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/linux:
  fscrypt: optimize fscrypt_initialize()
  fscrypt: use WARN_ON_ONCE instead of WARN_ON
  fscrypt: new helper function - fscrypt_prepare_lookup_partial()
  fs/buffer.c: use b_folio for fscrypt work
parents 733f7e9c 83e57e47
...@@ -331,8 +331,8 @@ static void decrypt_bh(struct work_struct *work) ...@@ -331,8 +331,8 @@ static void decrypt_bh(struct work_struct *work)
struct buffer_head *bh = ctx->bh; struct buffer_head *bh = ctx->bh;
int err; int err;
err = fscrypt_decrypt_pagecache_blocks(page_folio(bh->b_page), err = fscrypt_decrypt_pagecache_blocks(bh->b_folio, bh->b_size,
bh->b_size, bh_offset(bh)); bh_offset(bh));
if (err == 0 && need_fsverity(bh)) { if (err == 0 && need_fsverity(bh)) {
/* /*
* We use different work queues for decryption and for verity * We use different work queues for decryption and for verity
......
...@@ -69,7 +69,7 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode, ...@@ -69,7 +69,7 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
pblk << (blockbits - SECTOR_SHIFT); pblk << (blockbits - SECTOR_SHIFT);
} }
ret = bio_add_page(bio, ZERO_PAGE(0), bytes_this_page, 0); ret = bio_add_page(bio, ZERO_PAGE(0), bytes_this_page, 0);
if (WARN_ON(ret != bytes_this_page)) { if (WARN_ON_ONCE(ret != bytes_this_page)) {
err = -EIO; err = -EIO;
goto out; goto out;
} }
...@@ -147,7 +147,7 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, ...@@ -147,7 +147,7 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
break; break;
} }
nr_pages = i; nr_pages = i;
if (WARN_ON(nr_pages <= 0)) if (WARN_ON_ONCE(nr_pages <= 0))
return -EINVAL; return -EINVAL;
/* This always succeeds since __GFP_DIRECT_RECLAIM is set. */ /* This always succeeds since __GFP_DIRECT_RECLAIM is set. */
...@@ -170,7 +170,7 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, ...@@ -170,7 +170,7 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
offset += blocksize; offset += blocksize;
if (offset == PAGE_SIZE || len == 0) { if (offset == PAGE_SIZE || len == 0) {
ret = bio_add_page(bio, pages[i++], offset, 0); ret = bio_add_page(bio, pages[i++], offset, 0);
if (WARN_ON(ret != offset)) { if (WARN_ON_ONCE(ret != offset)) {
err = -EIO; err = -EIO;
goto out; goto out;
} }
......
...@@ -308,19 +308,24 @@ EXPORT_SYMBOL(fscrypt_decrypt_block_inplace); ...@@ -308,19 +308,24 @@ EXPORT_SYMBOL(fscrypt_decrypt_block_inplace);
/** /**
* fscrypt_initialize() - allocate major buffers for fs encryption. * fscrypt_initialize() - allocate major buffers for fs encryption.
* @cop_flags: fscrypt operations flags * @sb: the filesystem superblock
* *
* We only call this when we start accessing encrypted files, since it * We only call this when we start accessing encrypted files, since it
* results in memory getting allocated that wouldn't otherwise be used. * results in memory getting allocated that wouldn't otherwise be used.
* *
* Return: 0 on success; -errno on failure * Return: 0 on success; -errno on failure
*/ */
int fscrypt_initialize(unsigned int cop_flags) int fscrypt_initialize(struct super_block *sb)
{ {
int err = 0; int err = 0;
mempool_t *pool;
/* pairs with smp_store_release() below */
if (likely(smp_load_acquire(&fscrypt_bounce_page_pool)))
return 0;
/* No need to allocate a bounce page pool if this FS won't use it. */ /* No need to allocate a bounce page pool if this FS won't use it. */
if (cop_flags & FS_CFLG_OWN_PAGES) if (sb->s_cop->flags & FS_CFLG_OWN_PAGES)
return 0; return 0;
mutex_lock(&fscrypt_init_mutex); mutex_lock(&fscrypt_init_mutex);
...@@ -328,11 +333,11 @@ int fscrypt_initialize(unsigned int cop_flags) ...@@ -328,11 +333,11 @@ int fscrypt_initialize(unsigned int cop_flags)
goto out_unlock; goto out_unlock;
err = -ENOMEM; err = -ENOMEM;
fscrypt_bounce_page_pool = pool = mempool_create_page_pool(num_prealloc_crypto_pages, 0);
mempool_create_page_pool(num_prealloc_crypto_pages, 0); if (!pool)
if (!fscrypt_bounce_page_pool)
goto out_unlock; goto out_unlock;
/* pairs with smp_load_acquire() above */
smp_store_release(&fscrypt_bounce_page_pool, pool);
err = 0; err = 0;
out_unlock: out_unlock:
mutex_unlock(&fscrypt_init_mutex); mutex_unlock(&fscrypt_init_mutex);
......
...@@ -110,7 +110,7 @@ int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname, ...@@ -110,7 +110,7 @@ int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,
* Copy the filename to the output buffer for encrypting in-place and * Copy the filename to the output buffer for encrypting in-place and
* pad it with the needed number of NUL bytes. * pad it with the needed number of NUL bytes.
*/ */
if (WARN_ON(olen < iname->len)) if (WARN_ON_ONCE(olen < iname->len))
return -ENOBUFS; return -ENOBUFS;
memcpy(out, iname->name, iname->len); memcpy(out, iname->name, iname->len);
memset(out + iname->len, 0, olen - iname->len); memset(out + iname->len, 0, olen - iname->len);
...@@ -570,7 +570,7 @@ u64 fscrypt_fname_siphash(const struct inode *dir, const struct qstr *name) ...@@ -570,7 +570,7 @@ u64 fscrypt_fname_siphash(const struct inode *dir, const struct qstr *name)
{ {
const struct fscrypt_info *ci = dir->i_crypt_info; const struct fscrypt_info *ci = dir->i_crypt_info;
WARN_ON(!ci->ci_dirhash_key_initialized); WARN_ON_ONCE(!ci->ci_dirhash_key_initialized);
return siphash(name->name, name->len, &ci->ci_dirhash_key); return siphash(name->name, name->len, &ci->ci_dirhash_key);
} }
......
...@@ -101,7 +101,7 @@ static inline const u8 *fscrypt_context_nonce(const union fscrypt_context *ctx) ...@@ -101,7 +101,7 @@ static inline const u8 *fscrypt_context_nonce(const union fscrypt_context *ctx)
case FSCRYPT_CONTEXT_V2: case FSCRYPT_CONTEXT_V2:
return ctx->v2.nonce; return ctx->v2.nonce;
} }
WARN_ON(1); WARN_ON_ONCE(1);
return NULL; return NULL;
} }
...@@ -264,7 +264,7 @@ typedef enum { ...@@ -264,7 +264,7 @@ typedef enum {
/* crypto.c */ /* crypto.c */
extern struct kmem_cache *fscrypt_info_cachep; extern struct kmem_cache *fscrypt_info_cachep;
int fscrypt_initialize(unsigned int cop_flags); int fscrypt_initialize(struct super_block *sb);
int fscrypt_crypt_block(const struct inode *inode, fscrypt_direction_t rw, int fscrypt_crypt_block(const struct inode *inode, fscrypt_direction_t rw,
u64 lblk_num, struct page *src_page, u64 lblk_num, struct page *src_page,
struct page *dest_page, unsigned int len, struct page *dest_page, unsigned int len,
...@@ -386,7 +386,7 @@ fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key, ...@@ -386,7 +386,7 @@ fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
const u8 *raw_key, const u8 *raw_key,
const struct fscrypt_info *ci) const struct fscrypt_info *ci)
{ {
WARN_ON(1); WARN_ON_ONCE(1);
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
......
...@@ -79,7 +79,7 @@ int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key, ...@@ -79,7 +79,7 @@ int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key,
return PTR_ERR(hmac_tfm); return PTR_ERR(hmac_tfm);
} }
if (WARN_ON(crypto_shash_digestsize(hmac_tfm) != sizeof(prk))) { if (WARN_ON_ONCE(crypto_shash_digestsize(hmac_tfm) != sizeof(prk))) {
err = -EINVAL; err = -EINVAL;
goto err_free_tfm; goto err_free_tfm;
} }
...@@ -125,7 +125,7 @@ int fscrypt_hkdf_expand(const struct fscrypt_hkdf *hkdf, u8 context, ...@@ -125,7 +125,7 @@ int fscrypt_hkdf_expand(const struct fscrypt_hkdf *hkdf, u8 context,
u8 counter = 1; u8 counter = 1;
u8 tmp[HKDF_HASHLEN]; u8 tmp[HKDF_HASHLEN];
if (WARN_ON(okmlen > 255 * HKDF_HASHLEN)) if (WARN_ON_ONCE(okmlen > 255 * HKDF_HASHLEN))
return -EINVAL; return -EINVAL;
desc->tfm = hkdf->hmac_tfm; desc->tfm = hkdf->hmac_tfm;
......
...@@ -111,6 +111,36 @@ int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry, ...@@ -111,6 +111,36 @@ int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry,
} }
EXPORT_SYMBOL_GPL(__fscrypt_prepare_lookup); EXPORT_SYMBOL_GPL(__fscrypt_prepare_lookup);
/**
* fscrypt_prepare_lookup_partial() - prepare lookup without filename setup
* @dir: the encrypted directory being searched
* @dentry: the dentry being looked up in @dir
*
* This function should be used by the ->lookup and ->atomic_open methods of
* filesystems that handle filename encryption and no-key name encoding
* themselves and thus can't use fscrypt_prepare_lookup(). Like
* fscrypt_prepare_lookup(), this will try to set up the directory's encryption
* key and will set DCACHE_NOKEY_NAME on the dentry if the key is unavailable.
* However, this function doesn't set up a struct fscrypt_name for the filename.
*
* Return: 0 on success; -errno on error. Note that the encryption key being
* unavailable is not considered an error. It is also not an error if
* the encryption policy is unsupported by this kernel; that is treated
* like the key being unavailable, so that files can still be deleted.
*/
int fscrypt_prepare_lookup_partial(struct inode *dir, struct dentry *dentry)
{
int err = fscrypt_get_encryption_info(dir, true);
if (!err && !fscrypt_has_encryption_key(dir)) {
spin_lock(&dentry->d_lock);
dentry->d_flags |= DCACHE_NOKEY_NAME;
spin_unlock(&dentry->d_lock);
}
return err;
}
EXPORT_SYMBOL_GPL(fscrypt_prepare_lookup_partial);
int __fscrypt_prepare_readdir(struct inode *dir) int __fscrypt_prepare_readdir(struct inode *dir)
{ {
return fscrypt_get_encryption_info(dir, true); return fscrypt_get_encryption_info(dir, true);
...@@ -315,7 +345,7 @@ const char *fscrypt_get_symlink(struct inode *inode, const void *caddr, ...@@ -315,7 +345,7 @@ const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
int err; int err;
/* This is for encrypted symlinks only */ /* This is for encrypted symlinks only */
if (WARN_ON(!IS_ENCRYPTED(inode))) if (WARN_ON_ONCE(!IS_ENCRYPTED(inode)))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
/* If the decrypted target is already cached, just return it. */ /* If the decrypted target is already cached, just return it. */
......
...@@ -73,7 +73,7 @@ void fscrypt_put_master_key(struct fscrypt_master_key *mk) ...@@ -73,7 +73,7 @@ void fscrypt_put_master_key(struct fscrypt_master_key *mk)
* fscrypt_master_key struct itself after an RCU grace period ensures * fscrypt_master_key struct itself after an RCU grace period ensures
* that concurrent keyring lookups can no longer find it. * that concurrent keyring lookups can no longer find it.
*/ */
WARN_ON(refcount_read(&mk->mk_active_refs) != 0); WARN_ON_ONCE(refcount_read(&mk->mk_active_refs) != 0);
key_put(mk->mk_users); key_put(mk->mk_users);
mk->mk_users = NULL; mk->mk_users = NULL;
call_rcu(&mk->mk_rcu_head, fscrypt_free_master_key); call_rcu(&mk->mk_rcu_head, fscrypt_free_master_key);
...@@ -92,7 +92,7 @@ void fscrypt_put_master_key_activeref(struct super_block *sb, ...@@ -92,7 +92,7 @@ void fscrypt_put_master_key_activeref(struct super_block *sb,
* destroying any subkeys embedded in it. * destroying any subkeys embedded in it.
*/ */
if (WARN_ON(!sb->s_master_keys)) if (WARN_ON_ONCE(!sb->s_master_keys))
return; return;
spin_lock(&sb->s_master_keys->lock); spin_lock(&sb->s_master_keys->lock);
hlist_del_rcu(&mk->mk_node); hlist_del_rcu(&mk->mk_node);
...@@ -102,8 +102,8 @@ void fscrypt_put_master_key_activeref(struct super_block *sb, ...@@ -102,8 +102,8 @@ void fscrypt_put_master_key_activeref(struct super_block *sb,
* ->mk_active_refs == 0 implies that ->mk_secret is not present and * ->mk_active_refs == 0 implies that ->mk_secret is not present and
* that ->mk_decrypted_inodes is empty. * that ->mk_decrypted_inodes is empty.
*/ */
WARN_ON(is_master_key_secret_present(&mk->mk_secret)); WARN_ON_ONCE(is_master_key_secret_present(&mk->mk_secret));
WARN_ON(!list_empty(&mk->mk_decrypted_inodes)); WARN_ON_ONCE(!list_empty(&mk->mk_decrypted_inodes));
for (i = 0; i <= FSCRYPT_MODE_MAX; i++) { for (i = 0; i <= FSCRYPT_MODE_MAX; i++) {
fscrypt_destroy_prepared_key( fscrypt_destroy_prepared_key(
...@@ -237,9 +237,9 @@ void fscrypt_destroy_keyring(struct super_block *sb) ...@@ -237,9 +237,9 @@ void fscrypt_destroy_keyring(struct super_block *sb)
* with ->mk_secret. There should be no structural refs * with ->mk_secret. There should be no structural refs
* beyond the one associated with the active ref. * beyond the one associated with the active ref.
*/ */
WARN_ON(refcount_read(&mk->mk_active_refs) != 1); WARN_ON_ONCE(refcount_read(&mk->mk_active_refs) != 1);
WARN_ON(refcount_read(&mk->mk_struct_refs) != 1); WARN_ON_ONCE(refcount_read(&mk->mk_struct_refs) != 1);
WARN_ON(!is_master_key_secret_present(&mk->mk_secret)); WARN_ON_ONCE(!is_master_key_secret_present(&mk->mk_secret));
wipe_master_key_secret(&mk->mk_secret); wipe_master_key_secret(&mk->mk_secret);
fscrypt_put_master_key_activeref(sb, mk); fscrypt_put_master_key_activeref(sb, mk);
} }
......
...@@ -125,7 +125,7 @@ fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key, ...@@ -125,7 +125,7 @@ fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key,
pr_info("fscrypt: %s using implementation \"%s\"\n", pr_info("fscrypt: %s using implementation \"%s\"\n",
mode->friendly_name, crypto_skcipher_driver_name(tfm)); mode->friendly_name, crypto_skcipher_driver_name(tfm));
} }
if (WARN_ON(crypto_skcipher_ivsize(tfm) != mode->ivsize)) { if (WARN_ON_ONCE(crypto_skcipher_ivsize(tfm) != mode->ivsize)) {
err = -EINVAL; err = -EINVAL;
goto err_free_tfm; goto err_free_tfm;
} }
...@@ -199,7 +199,7 @@ static int setup_per_mode_enc_key(struct fscrypt_info *ci, ...@@ -199,7 +199,7 @@ static int setup_per_mode_enc_key(struct fscrypt_info *ci,
unsigned int hkdf_infolen = 0; unsigned int hkdf_infolen = 0;
int err; int err;
if (WARN_ON(mode_num > FSCRYPT_MODE_MAX)) if (WARN_ON_ONCE(mode_num > FSCRYPT_MODE_MAX))
return -EINVAL; return -EINVAL;
prep_key = &keys[mode_num]; prep_key = &keys[mode_num];
...@@ -282,8 +282,8 @@ int fscrypt_derive_dirhash_key(struct fscrypt_info *ci, ...@@ -282,8 +282,8 @@ int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
void fscrypt_hash_inode_number(struct fscrypt_info *ci, void fscrypt_hash_inode_number(struct fscrypt_info *ci,
const struct fscrypt_master_key *mk) const struct fscrypt_master_key *mk)
{ {
WARN_ON(ci->ci_inode->i_ino == 0); WARN_ON_ONCE(ci->ci_inode->i_ino == 0);
WARN_ON(!mk->mk_ino_hash_key_initialized); WARN_ON_ONCE(!mk->mk_ino_hash_key_initialized);
ci->ci_hashed_ino = (u32)siphash_1u64(ci->ci_inode->i_ino, ci->ci_hashed_ino = (u32)siphash_1u64(ci->ci_inode->i_ino,
&mk->mk_ino_hash_key); &mk->mk_ino_hash_key);
...@@ -503,7 +503,7 @@ static int setup_file_encryption_key(struct fscrypt_info *ci, ...@@ -503,7 +503,7 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
err = fscrypt_setup_v2_file_key(ci, mk, need_dirhash_key); err = fscrypt_setup_v2_file_key(ci, mk, need_dirhash_key);
break; break;
default: default:
WARN_ON(1); WARN_ON_ONCE(1);
err = -EINVAL; err = -EINVAL;
break; break;
} }
...@@ -560,7 +560,7 @@ fscrypt_setup_encryption_info(struct inode *inode, ...@@ -560,7 +560,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
struct fscrypt_master_key *mk = NULL; struct fscrypt_master_key *mk = NULL;
int res; int res;
res = fscrypt_initialize(inode->i_sb->s_cop->flags); res = fscrypt_initialize(inode->i_sb);
if (res) if (res)
return res; return res;
...@@ -577,7 +577,7 @@ fscrypt_setup_encryption_info(struct inode *inode, ...@@ -577,7 +577,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
res = PTR_ERR(mode); res = PTR_ERR(mode);
goto out; goto out;
} }
WARN_ON(mode->ivsize > FSCRYPT_MAX_IV_SIZE); WARN_ON_ONCE(mode->ivsize > FSCRYPT_MAX_IV_SIZE);
crypt_info->ci_mode = mode; crypt_info->ci_mode = mode;
res = setup_file_encryption_key(crypt_info, need_dirhash_key, &mk); res = setup_file_encryption_key(crypt_info, need_dirhash_key, &mk);
......
...@@ -48,7 +48,7 @@ int fscrypt_policy_to_key_spec(const union fscrypt_policy *policy, ...@@ -48,7 +48,7 @@ int fscrypt_policy_to_key_spec(const union fscrypt_policy *policy,
FSCRYPT_KEY_IDENTIFIER_SIZE); FSCRYPT_KEY_IDENTIFIER_SIZE);
return 0; return 0;
default: default:
WARN_ON(1); WARN_ON_ONCE(1);
return -EINVAL; return -EINVAL;
} }
} }
...@@ -463,7 +463,7 @@ static int set_encryption_policy(struct inode *inode, ...@@ -463,7 +463,7 @@ static int set_encryption_policy(struct inode *inode,
current->comm, current->pid); current->comm, current->pid);
break; break;
default: default:
WARN_ON(1); WARN_ON_ONCE(1);
return -EINVAL; return -EINVAL;
} }
......
...@@ -359,6 +359,7 @@ int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -359,6 +359,7 @@ int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *old_dentry,
unsigned int flags); unsigned int flags);
int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry, int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry,
struct fscrypt_name *fname); struct fscrypt_name *fname);
int fscrypt_prepare_lookup_partial(struct inode *dir, struct dentry *dentry);
int __fscrypt_prepare_readdir(struct inode *dir); int __fscrypt_prepare_readdir(struct inode *dir);
int __fscrypt_prepare_setattr(struct dentry *dentry, struct iattr *attr); int __fscrypt_prepare_setattr(struct dentry *dentry, struct iattr *attr);
int fscrypt_prepare_setflags(struct inode *inode, int fscrypt_prepare_setflags(struct inode *inode,
...@@ -673,6 +674,12 @@ static inline int __fscrypt_prepare_lookup(struct inode *dir, ...@@ -673,6 +674,12 @@ static inline int __fscrypt_prepare_lookup(struct inode *dir,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline int fscrypt_prepare_lookup_partial(struct inode *dir,
struct dentry *dentry)
{
return -EOPNOTSUPP;
}
static inline int __fscrypt_prepare_readdir(struct inode *dir) static inline int __fscrypt_prepare_readdir(struct inode *dir)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment