mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 01:32:21 +02:00
fscrypt fixes for v7.2-rc5
A couple fixes for AI-detected bugs. -----BEGIN PGP SIGNATURE----- iIkEABYIADIWIQSacvsUNc7UX4ntmEPzXCl4vpKOKwUCamPDWBQcZWJpZ2dlcnNA a2VybmVsLm9yZwAKCRDzXCl4vpKOK4C8APjY2sD4jMa1oX05SiLL7iUulkTXivOb n14nFabjqF25AP9MZImv0oS5eQWt/QPLHfNlB6olRd9Q0GqVOYYdKQ/6DA== =pStx -----END PGP SIGNATURE----- Merge tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/linux Pull fscrypt fixes from Eric Biggers: "A couple fixes for AI-detected bugs" * tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/linux: fscrypt: Avoid dynamic allocation in fscrypt_get_devices() fscrypt: Add missing superblock check in find_or_insert_direct_key()
This commit is contained in:
commit
981f4a2baa
|
|
@ -22,22 +22,14 @@
|
|||
|
||||
#include "fscrypt_private.h"
|
||||
|
||||
static struct block_device **fscrypt_get_devices(struct super_block *sb,
|
||||
unsigned int *num_devs)
|
||||
static unsigned int
|
||||
fscrypt_get_devices(struct super_block *sb,
|
||||
struct block_device *devs[FSCRYPT_MAX_DEVICES])
|
||||
{
|
||||
struct block_device **devs;
|
||||
|
||||
if (sb->s_cop->get_devices) {
|
||||
devs = sb->s_cop->get_devices(sb, num_devs);
|
||||
if (devs)
|
||||
return devs;
|
||||
}
|
||||
devs = kmalloc_obj(*devs);
|
||||
if (!devs)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
if (sb->s_cop->get_devices)
|
||||
return sb->s_cop->get_devices(sb, devs);
|
||||
devs[0] = sb->s_bdev;
|
||||
*num_devs = 1;
|
||||
return devs;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static unsigned int fscrypt_get_dun_bytes(const struct fscrypt_inode_info *ci)
|
||||
|
|
@ -96,7 +88,7 @@ int fscrypt_select_encryption_impl(struct fscrypt_inode_info *ci,
|
|||
const struct inode *inode = ci->ci_inode;
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct blk_crypto_config crypto_cfg;
|
||||
struct block_device **devs;
|
||||
struct block_device *devs[FSCRYPT_MAX_DEVICES];
|
||||
unsigned int num_devs;
|
||||
unsigned int i;
|
||||
|
||||
|
|
@ -135,20 +127,15 @@ int fscrypt_select_encryption_impl(struct fscrypt_inode_info *ci,
|
|||
crypto_cfg.key_type = is_hw_wrapped_key ?
|
||||
BLK_CRYPTO_KEY_TYPE_HW_WRAPPED : BLK_CRYPTO_KEY_TYPE_RAW;
|
||||
|
||||
devs = fscrypt_get_devices(sb, &num_devs);
|
||||
if (IS_ERR(devs))
|
||||
return PTR_ERR(devs);
|
||||
|
||||
num_devs = fscrypt_get_devices(sb, devs);
|
||||
for (i = 0; i < num_devs; i++) {
|
||||
if (!blk_crypto_config_supported(devs[i], &crypto_cfg))
|
||||
goto out_free_devs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
fscrypt_log_blk_crypto_impl(ci->ci_mode, devs, num_devs, &crypto_cfg);
|
||||
|
||||
ci->ci_inlinecrypt = true;
|
||||
out_free_devs:
|
||||
kfree(devs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -164,7 +151,7 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
|
|||
enum blk_crypto_key_type key_type = is_hw_wrapped ?
|
||||
BLK_CRYPTO_KEY_TYPE_HW_WRAPPED : BLK_CRYPTO_KEY_TYPE_RAW;
|
||||
struct blk_crypto_key *blk_key;
|
||||
struct block_device **devs;
|
||||
struct block_device *devs[FSCRYPT_MAX_DEVICES];
|
||||
unsigned int num_devs;
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
|
@ -182,17 +169,12 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
|
|||
}
|
||||
|
||||
/* Start using blk-crypto on all the filesystem's block devices. */
|
||||
devs = fscrypt_get_devices(sb, &num_devs);
|
||||
if (IS_ERR(devs)) {
|
||||
err = PTR_ERR(devs);
|
||||
goto fail;
|
||||
}
|
||||
num_devs = fscrypt_get_devices(sb, devs);
|
||||
for (i = 0; i < num_devs; i++) {
|
||||
err = blk_crypto_start_using_key(devs[i], blk_key);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
kfree(devs);
|
||||
if (err) {
|
||||
fscrypt_err(inode, "error %d starting to use blk-crypto", err);
|
||||
goto fail;
|
||||
|
|
@ -210,20 +192,21 @@ void fscrypt_destroy_inline_crypt_key(struct super_block *sb,
|
|||
struct fscrypt_prepared_key *prep_key)
|
||||
{
|
||||
struct blk_crypto_key *blk_key = prep_key->blk_key;
|
||||
struct block_device **devs;
|
||||
struct block_device *devs[FSCRYPT_MAX_DEVICES];
|
||||
unsigned int num_devs;
|
||||
unsigned int i;
|
||||
|
||||
if (!blk_key)
|
||||
return;
|
||||
|
||||
/* Evict the key from all the filesystem's block devices. */
|
||||
devs = fscrypt_get_devices(sb, &num_devs);
|
||||
if (!IS_ERR(devs)) {
|
||||
for (i = 0; i < num_devs; i++)
|
||||
blk_crypto_evict_key(devs[i], blk_key);
|
||||
kfree(devs);
|
||||
}
|
||||
/*
|
||||
* Evict the key from all the filesystem's block devices.
|
||||
* This *must* be done before the key is freed.
|
||||
*/
|
||||
num_devs = fscrypt_get_devices(sb, devs);
|
||||
for (i = 0; i < num_devs; i++)
|
||||
blk_crypto_evict_key(devs[i], blk_key);
|
||||
|
||||
kfree_sensitive(blk_key);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -147,13 +147,19 @@ find_or_insert_direct_key(struct fscrypt_direct_key *to_insert,
|
|||
if (memcmp(ci->ci_policy.v1.master_key_descriptor,
|
||||
dk->dk_descriptor, FSCRYPT_KEY_DESCRIPTOR_SIZE) != 0)
|
||||
continue;
|
||||
/* The sb is used at eviction time, so it must be the same. */
|
||||
if (ci->ci_inode->i_sb != dk->dk_sb)
|
||||
continue;
|
||||
if (ci->ci_mode != dk->dk_mode)
|
||||
continue;
|
||||
if (!fscrypt_is_key_prepared(&dk->dk_key, ci))
|
||||
continue;
|
||||
if (crypto_memneq(raw_key, dk->dk_raw, ci->ci_mode->keysize))
|
||||
continue;
|
||||
/* using existing tfm with same (descriptor, mode, raw_key) */
|
||||
/*
|
||||
* Use an existing prepared key with the same (descriptor, sb,
|
||||
* mode, inlinecrypt, raw_key) combination.
|
||||
*/
|
||||
refcount_inc(&dk->dk_refcount);
|
||||
spin_unlock(&fscrypt_direct_keys_lock);
|
||||
free_direct_key(to_insert);
|
||||
|
|
|
|||
|
|
@ -3749,24 +3749,27 @@ static bool f2fs_has_stable_inodes(struct super_block *sb)
|
|||
return true;
|
||||
}
|
||||
|
||||
static struct block_device **f2fs_get_devices(struct super_block *sb,
|
||||
unsigned int *num_devs)
|
||||
static unsigned int
|
||||
f2fs_get_devices(struct super_block *sb,
|
||||
struct block_device *devs[FSCRYPT_MAX_DEVICES])
|
||||
{
|
||||
struct f2fs_sb_info *sbi = F2FS_SB(sb);
|
||||
struct block_device **devs;
|
||||
int ndevs;
|
||||
int i;
|
||||
|
||||
if (!f2fs_is_multi_device(sbi))
|
||||
return NULL;
|
||||
static_assert(MAX_DEVICES <= FSCRYPT_MAX_DEVICES);
|
||||
|
||||
devs = kmalloc_objs(*devs, sbi->s_ndevs);
|
||||
if (!devs)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
if (!f2fs_is_multi_device(sbi)) {
|
||||
devs[0] = sb->s_bdev;
|
||||
return 1;
|
||||
}
|
||||
ndevs = sbi->s_ndevs;
|
||||
if (WARN_ON_ONCE(ndevs > FSCRYPT_MAX_DEVICES))
|
||||
ndevs = FSCRYPT_MAX_DEVICES;
|
||||
|
||||
for (i = 0; i < sbi->s_ndevs; i++)
|
||||
for (i = 0; i < ndevs; i++)
|
||||
devs[i] = FDEV(i).bdev;
|
||||
*num_devs = sbi->s_ndevs;
|
||||
return devs;
|
||||
return ndevs;
|
||||
}
|
||||
|
||||
static const struct fscrypt_operations f2fs_cryptops = {
|
||||
|
|
|
|||
|
|
@ -57,6 +57,9 @@ struct fscrypt_name {
|
|||
/* Maximum value for the third parameter of fscrypt_operations.set_context(). */
|
||||
#define FSCRYPT_SET_CONTEXT_MAX_SIZE 40
|
||||
|
||||
/* Maximum supported number of block devices per filesystem */
|
||||
#define FSCRYPT_MAX_DEVICES 8
|
||||
|
||||
#ifdef CONFIG_FS_ENCRYPTION
|
||||
|
||||
/* Crypto operations for filesystems */
|
||||
|
|
@ -181,21 +184,20 @@ struct fscrypt_operations {
|
|||
bool (*has_stable_inodes)(struct super_block *sb);
|
||||
|
||||
/*
|
||||
* Return an array of pointers to the block devices to which the
|
||||
* filesystem may write encrypted file contents, NULL if the filesystem
|
||||
* only has a single such block device, or an ERR_PTR() on error.
|
||||
* Retrieve the list of block devices to which the filesystem may write
|
||||
* encrypted file contents.
|
||||
*
|
||||
* On successful non-NULL return, *num_devs is set to the number of
|
||||
* devices in the returned array. The caller must free the returned
|
||||
* array using kfree().
|
||||
* This writes the block_device pointers to @devs and returns the count
|
||||
* (between 1 and FSCRYPT_MAX_DEVICES inclusively).
|
||||
*
|
||||
* If the filesystem can use multiple block devices (other than block
|
||||
* devices that aren't used for encrypted file contents, such as
|
||||
* external journal devices), and wants to support inline encryption,
|
||||
* then it must implement this function. Otherwise it's not needed.
|
||||
*/
|
||||
struct block_device **(*get_devices)(struct super_block *sb,
|
||||
unsigned int *num_devs);
|
||||
unsigned int (*get_devices)(
|
||||
struct super_block *sb,
|
||||
struct block_device *devs[FSCRYPT_MAX_DEVICES]);
|
||||
};
|
||||
|
||||
int fscrypt_d_revalidate(struct inode *dir, const struct qstr *name,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user