Merge remote-tracking branch 'aosp/upstream-f2fs-stable-linux-6.1.y' into android14-6.1
* aosp/upstream-f2fs-stable-linux-6.1.y: fscrypt: destroy keyring after security_sb_delete() fscrypt: optimize fscrypt_initialize() fscrypt: use WARN_ON_ONCE instead of WARN_ON fscrypt: new helper function - fscrypt_prepare_lookup_partial() fscrypt: check for NULL keyring in fscrypt_put_master_key_activeref() fscrypt: improve fscrypt_destroy_keyring() documentation Bug: 273795759 Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> Change-Id: I32f5ac5bae203c62f8b1e00dd66c21046ab55014
This commit is contained in:
commit
a90747aabd
@ -69,7 +69,7 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
|
||||
pblk << (blockbits - SECTOR_SHIFT);
|
||||
}
|
||||
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;
|
||||
goto out;
|
||||
}
|
||||
@ -147,7 +147,7 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
|
||||
break;
|
||||
}
|
||||
nr_pages = i;
|
||||
if (WARN_ON(nr_pages <= 0))
|
||||
if (WARN_ON_ONCE(nr_pages <= 0))
|
||||
return -EINVAL;
|
||||
|
||||
/* This always succeeds since __GFP_DIRECT_RECLAIM is set. */
|
||||
@ -170,7 +170,7 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
|
||||
offset += blocksize;
|
||||
if (offset == PAGE_SIZE || len == 0) {
|
||||
ret = bio_add_page(bio, pages[i++], offset, 0);
|
||||
if (WARN_ON(ret != offset)) {
|
||||
if (WARN_ON_ONCE(ret != offset)) {
|
||||
err = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
@ -308,19 +308,24 @@ EXPORT_SYMBOL(fscrypt_decrypt_block_inplace);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* results in memory getting allocated that wouldn't otherwise be used.
|
||||
*
|
||||
* Return: 0 on success; -errno on failure
|
||||
*/
|
||||
int fscrypt_initialize(unsigned int cop_flags)
|
||||
int fscrypt_initialize(struct super_block *sb)
|
||||
{
|
||||
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. */
|
||||
if (cop_flags & FS_CFLG_OWN_PAGES)
|
||||
if (sb->s_cop->flags & FS_CFLG_OWN_PAGES)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&fscrypt_init_mutex);
|
||||
@ -328,11 +333,11 @@ int fscrypt_initialize(unsigned int cop_flags)
|
||||
goto out_unlock;
|
||||
|
||||
err = -ENOMEM;
|
||||
fscrypt_bounce_page_pool =
|
||||
mempool_create_page_pool(num_prealloc_crypto_pages, 0);
|
||||
if (!fscrypt_bounce_page_pool)
|
||||
pool = mempool_create_page_pool(num_prealloc_crypto_pages, 0);
|
||||
if (!pool)
|
||||
goto out_unlock;
|
||||
|
||||
/* pairs with smp_load_acquire() above */
|
||||
smp_store_release(&fscrypt_bounce_page_pool, pool);
|
||||
err = 0;
|
||||
out_unlock:
|
||||
mutex_unlock(&fscrypt_init_mutex);
|
||||
|
@ -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
|
||||
* pad it with the needed number of NUL bytes.
|
||||
*/
|
||||
if (WARN_ON(olen < iname->len))
|
||||
if (WARN_ON_ONCE(olen < iname->len))
|
||||
return -ENOBUFS;
|
||||
memcpy(out, iname->name, 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ static inline const u8 *fscrypt_context_nonce(const union fscrypt_context *ctx)
|
||||
case FSCRYPT_CONTEXT_V2:
|
||||
return ctx->v2.nonce;
|
||||
}
|
||||
WARN_ON(1);
|
||||
WARN_ON_ONCE(1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -285,7 +285,7 @@ typedef enum {
|
||||
|
||||
/* crypto.c */
|
||||
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,
|
||||
u64 lblk_num, struct page *src_page,
|
||||
struct page *dest_page, unsigned int len,
|
||||
@ -415,7 +415,7 @@ fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
|
||||
bool is_hw_wrapped,
|
||||
const struct fscrypt_info *ci)
|
||||
{
|
||||
WARN_ON(1);
|
||||
WARN_ON_ONCE(1);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key,
|
||||
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;
|
||||
goto err_free_tfm;
|
||||
}
|
||||
@ -127,7 +127,7 @@ int fscrypt_hkdf_expand(const struct fscrypt_hkdf *hkdf, u8 context,
|
||||
u8 counter = 1;
|
||||
u8 tmp[HKDF_HASHLEN];
|
||||
|
||||
if (WARN_ON(okmlen > 255 * HKDF_HASHLEN))
|
||||
if (WARN_ON_ONCE(okmlen > 255 * HKDF_HASHLEN))
|
||||
return -EINVAL;
|
||||
|
||||
desc->tfm = hkdf->hmac_tfm;
|
||||
|
@ -111,6 +111,36 @@ int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry,
|
||||
}
|
||||
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)
|
||||
{
|
||||
return fscrypt_get_encryption_info(dir, true);
|
||||
@ -315,7 +345,7 @@ const char *fscrypt_get_symlink(struct inode *inode, const void *caddr,
|
||||
int err;
|
||||
|
||||
/* This is for encrypted symlinks only */
|
||||
if (WARN_ON(!IS_ENCRYPTED(inode)))
|
||||
if (WARN_ON_ONCE(!IS_ENCRYPTED(inode)))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/* If the decrypted target is already cached, just return it. */
|
||||
|
@ -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
|
||||
* 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);
|
||||
mk->mk_users = NULL;
|
||||
call_rcu(&mk->mk_rcu_head, fscrypt_free_master_key);
|
||||
@ -92,6 +92,8 @@ void fscrypt_put_master_key_activeref(struct super_block *sb,
|
||||
* destroying any subkeys embedded in it.
|
||||
*/
|
||||
|
||||
if (WARN_ON_ONCE(!sb->s_master_keys))
|
||||
return;
|
||||
spin_lock(&sb->s_master_keys->lock);
|
||||
hlist_del_rcu(&mk->mk_node);
|
||||
spin_unlock(&sb->s_master_keys->lock);
|
||||
@ -100,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
|
||||
* that ->mk_decrypted_inodes is empty.
|
||||
*/
|
||||
WARN_ON(is_master_key_secret_present(&mk->mk_secret));
|
||||
WARN_ON(!list_empty(&mk->mk_decrypted_inodes));
|
||||
WARN_ON_ONCE(is_master_key_secret_present(&mk->mk_secret));
|
||||
WARN_ON_ONCE(!list_empty(&mk->mk_decrypted_inodes));
|
||||
|
||||
for (i = 0; i <= FSCRYPT_MODE_MAX; i++) {
|
||||
fscrypt_destroy_prepared_key(
|
||||
@ -207,10 +209,11 @@ static int allocate_filesystem_keyring(struct super_block *sb)
|
||||
* Release all encryption keys that have been added to the filesystem, along
|
||||
* with the keyring that contains them.
|
||||
*
|
||||
* This is called at unmount time. The filesystem's underlying block device(s)
|
||||
* are still available at this time; this is important because after user file
|
||||
* accesses have been allowed, this function may need to evict keys from the
|
||||
* keyslots of an inline crypto engine, which requires the block device(s).
|
||||
* This is called at unmount time, after all potentially-encrypted inodes have
|
||||
* been evicted. The filesystem's underlying block device(s) are still
|
||||
* available at this time; this is important because after user file accesses
|
||||
* have been allowed, this function may need to evict keys from the keyslots of
|
||||
* an inline crypto engine, which requires the block device(s).
|
||||
*/
|
||||
void fscrypt_destroy_keyring(struct super_block *sb)
|
||||
{
|
||||
@ -227,16 +230,16 @@ void fscrypt_destroy_keyring(struct super_block *sb)
|
||||
|
||||
hlist_for_each_entry_safe(mk, tmp, bucket, mk_node) {
|
||||
/*
|
||||
* Since all inodes were already evicted, every key
|
||||
* remaining in the keyring should have an empty inode
|
||||
* list, and should only still be in the keyring due to
|
||||
* the single active ref associated with ->mk_secret.
|
||||
* There should be no structural refs beyond the one
|
||||
* associated with the active ref.
|
||||
* Since all potentially-encrypted inodes were already
|
||||
* evicted, every key remaining in the keyring should
|
||||
* have an empty inode list, and should only still be in
|
||||
* the keyring due to the single active ref associated
|
||||
* with ->mk_secret. There should be no structural refs
|
||||
* beyond the one associated with the active ref.
|
||||
*/
|
||||
WARN_ON(refcount_read(&mk->mk_active_refs) != 1);
|
||||
WARN_ON(refcount_read(&mk->mk_struct_refs) != 1);
|
||||
WARN_ON(!is_master_key_secret_present(&mk->mk_secret));
|
||||
WARN_ON_ONCE(refcount_read(&mk->mk_active_refs) != 1);
|
||||
WARN_ON_ONCE(refcount_read(&mk->mk_struct_refs) != 1);
|
||||
WARN_ON_ONCE(!is_master_key_secret_present(&mk->mk_secret));
|
||||
wipe_master_key_secret(&mk->mk_secret);
|
||||
fscrypt_put_master_key_activeref(sb, mk);
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key,
|
||||
pr_info("fscrypt: %s using implementation \"%s\"\n",
|
||||
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;
|
||||
goto err_free_tfm;
|
||||
}
|
||||
@ -202,7 +202,7 @@ static int setup_per_mode_enc_key(struct fscrypt_info *ci,
|
||||
bool use_hw_wrapped_key = false;
|
||||
int err;
|
||||
|
||||
if (WARN_ON(mode_num > FSCRYPT_MODE_MAX))
|
||||
if (WARN_ON_ONCE(mode_num > FSCRYPT_MODE_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
if (mk->mk_secret.is_hw_wrapped && S_ISREG(inode->i_mode)) {
|
||||
@ -309,8 +309,8 @@ 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);
|
||||
WARN_ON(!mk->mk_ino_hash_key_initialized);
|
||||
WARN_ON_ONCE(ci->ci_inode->i_ino == 0);
|
||||
WARN_ON_ONCE(!mk->mk_ino_hash_key_initialized);
|
||||
|
||||
ci->ci_hashed_ino = (u32)siphash_1u64(ci->ci_inode->i_ino,
|
||||
&mk->mk_ino_hash_key);
|
||||
@ -550,7 +550,7 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
|
||||
err = fscrypt_setup_v2_file_key(ci, mk, need_dirhash_key);
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
WARN_ON_ONCE(1);
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
@ -607,7 +607,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
|
||||
struct fscrypt_master_key *mk = NULL;
|
||||
int res;
|
||||
|
||||
res = fscrypt_initialize(inode->i_sb->s_cop->flags);
|
||||
res = fscrypt_initialize(inode->i_sb);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
@ -624,7 +624,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
|
||||
res = PTR_ERR(mode);
|
||||
goto out;
|
||||
}
|
||||
WARN_ON(mode->ivsize > FSCRYPT_MAX_IV_SIZE);
|
||||
WARN_ON_ONCE(mode->ivsize > FSCRYPT_MAX_IV_SIZE);
|
||||
crypt_info->ci_mode = mode;
|
||||
|
||||
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,
|
||||
FSCRYPT_KEY_IDENTIFIER_SIZE);
|
||||
return 0;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
WARN_ON_ONCE(1);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
@ -463,7 +463,7 @@ static int set_encryption_policy(struct inode *inode,
|
||||
current->comm, current->pid);
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
WARN_ON_ONCE(1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -367,6 +367,7 @@ int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
unsigned int flags);
|
||||
int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry,
|
||||
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_setattr(struct dentry *dentry, struct iattr *attr);
|
||||
int fscrypt_prepare_setflags(struct inode *inode,
|
||||
@ -681,6 +682,12 @@ static inline int __fscrypt_prepare_lookup(struct inode *dir,
|
||||
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)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
|
Loading…
Reference in New Issue
Block a user