forked from Minki/linux
fscrypt: work on block_devices instead of request_queues
request_queues are a block layer implementation detail that should not leak into file systems. Change the fscrypt inline crypto code to retrieve block devices instead of request_queues from the file system. As part of that, clean up the interaction with multi-device file systems by returning both the number of devices and the actual device array in a single method call. Signed-off-by: Christoph Hellwig <hch@lst.de> [ebiggers: bug fixes and minor tweaks] Signed-off-by: Eric Biggers <ebiggers@google.com> Link: https://lore.kernel.org/r/20220901193208.138056-4-ebiggers@kernel.org
This commit is contained in:
parent
22e9947a4b
commit
0e91fc1e0f
@ -21,20 +21,22 @@
|
|||||||
|
|
||||||
#include "fscrypt_private.h"
|
#include "fscrypt_private.h"
|
||||||
|
|
||||||
static int fscrypt_get_num_devices(struct super_block *sb)
|
static struct block_device **fscrypt_get_devices(struct super_block *sb,
|
||||||
|
unsigned int *num_devs)
|
||||||
{
|
{
|
||||||
if (sb->s_cop->get_num_devices)
|
struct block_device **devs;
|
||||||
return sb->s_cop->get_num_devices(sb);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fscrypt_get_devices(struct super_block *sb, int num_devs,
|
if (sb->s_cop->get_devices) {
|
||||||
struct request_queue **devs)
|
devs = sb->s_cop->get_devices(sb, num_devs);
|
||||||
{
|
if (devs)
|
||||||
if (num_devs == 1)
|
return devs;
|
||||||
devs[0] = bdev_get_queue(sb->s_bdev);
|
}
|
||||||
else
|
devs = kmalloc(sizeof(*devs), GFP_KERNEL);
|
||||||
sb->s_cop->get_devices(sb, devs);
|
if (!devs)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
devs[0] = sb->s_bdev;
|
||||||
|
*num_devs = 1;
|
||||||
|
return devs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int fscrypt_get_dun_bytes(const struct fscrypt_info *ci)
|
static unsigned int fscrypt_get_dun_bytes(const struct fscrypt_info *ci)
|
||||||
@ -68,15 +70,17 @@ static unsigned int fscrypt_get_dun_bytes(const struct fscrypt_info *ci)
|
|||||||
* helpful for debugging problems where the "wrong" implementation is used.
|
* helpful for debugging problems where the "wrong" implementation is used.
|
||||||
*/
|
*/
|
||||||
static void fscrypt_log_blk_crypto_impl(struct fscrypt_mode *mode,
|
static void fscrypt_log_blk_crypto_impl(struct fscrypt_mode *mode,
|
||||||
struct request_queue **devs,
|
struct block_device **devs,
|
||||||
int num_devs,
|
unsigned int num_devs,
|
||||||
const struct blk_crypto_config *cfg)
|
const struct blk_crypto_config *cfg)
|
||||||
{
|
{
|
||||||
int i;
|
unsigned int i;
|
||||||
|
|
||||||
for (i = 0; i < num_devs; i++) {
|
for (i = 0; i < num_devs; i++) {
|
||||||
|
struct request_queue *q = bdev_get_queue(devs[i]);
|
||||||
|
|
||||||
if (!IS_ENABLED(CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK) ||
|
if (!IS_ENABLED(CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK) ||
|
||||||
__blk_crypto_cfg_supported(devs[i]->crypto_profile, cfg)) {
|
__blk_crypto_cfg_supported(q->crypto_profile, cfg)) {
|
||||||
if (!xchg(&mode->logged_blk_crypto_native, 1))
|
if (!xchg(&mode->logged_blk_crypto_native, 1))
|
||||||
pr_info("fscrypt: %s using blk-crypto (native)\n",
|
pr_info("fscrypt: %s using blk-crypto (native)\n",
|
||||||
mode->friendly_name);
|
mode->friendly_name);
|
||||||
@ -93,9 +97,9 @@ int fscrypt_select_encryption_impl(struct fscrypt_info *ci)
|
|||||||
const struct inode *inode = ci->ci_inode;
|
const struct inode *inode = ci->ci_inode;
|
||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
struct blk_crypto_config crypto_cfg;
|
struct blk_crypto_config crypto_cfg;
|
||||||
int num_devs;
|
struct block_device **devs;
|
||||||
struct request_queue **devs;
|
unsigned int num_devs;
|
||||||
int i;
|
unsigned int i;
|
||||||
|
|
||||||
/* The file must need contents encryption, not filenames encryption */
|
/* The file must need contents encryption, not filenames encryption */
|
||||||
if (!S_ISREG(inode->i_mode))
|
if (!S_ISREG(inode->i_mode))
|
||||||
@ -123,20 +127,20 @@ int fscrypt_select_encryption_impl(struct fscrypt_info *ci)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On all the filesystem's devices, blk-crypto must support the crypto
|
* On all the filesystem's block devices, blk-crypto must support the
|
||||||
* configuration that the file would use.
|
* crypto configuration that the file would use.
|
||||||
*/
|
*/
|
||||||
crypto_cfg.crypto_mode = ci->ci_mode->blk_crypto_mode;
|
crypto_cfg.crypto_mode = ci->ci_mode->blk_crypto_mode;
|
||||||
crypto_cfg.data_unit_size = sb->s_blocksize;
|
crypto_cfg.data_unit_size = sb->s_blocksize;
|
||||||
crypto_cfg.dun_bytes = fscrypt_get_dun_bytes(ci);
|
crypto_cfg.dun_bytes = fscrypt_get_dun_bytes(ci);
|
||||||
num_devs = fscrypt_get_num_devices(sb);
|
|
||||||
devs = kmalloc_array(num_devs, sizeof(*devs), GFP_KERNEL);
|
devs = fscrypt_get_devices(sb, &num_devs);
|
||||||
if (!devs)
|
if (IS_ERR(devs))
|
||||||
return -ENOMEM;
|
return PTR_ERR(devs);
|
||||||
fscrypt_get_devices(sb, num_devs, devs);
|
|
||||||
|
|
||||||
for (i = 0; i < num_devs; i++) {
|
for (i = 0; i < num_devs; i++) {
|
||||||
if (!blk_crypto_config_supported(devs[i], &crypto_cfg))
|
if (!blk_crypto_config_supported(bdev_get_queue(devs[i]),
|
||||||
|
&crypto_cfg))
|
||||||
goto out_free_devs;
|
goto out_free_devs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +161,7 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
|
|||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
enum blk_crypto_mode_num crypto_mode = ci->ci_mode->blk_crypto_mode;
|
enum blk_crypto_mode_num crypto_mode = ci->ci_mode->blk_crypto_mode;
|
||||||
struct blk_crypto_key *blk_key;
|
struct blk_crypto_key *blk_key;
|
||||||
struct request_queue **devs;
|
struct block_device **devs;
|
||||||
unsigned int num_devs;
|
unsigned int num_devs;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int err;
|
int err;
|
||||||
@ -174,15 +178,14 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Start using blk-crypto on all the filesystem's block devices. */
|
/* Start using blk-crypto on all the filesystem's block devices. */
|
||||||
num_devs = fscrypt_get_num_devices(sb);
|
devs = fscrypt_get_devices(sb, &num_devs);
|
||||||
devs = kmalloc_array(num_devs, sizeof(*devs), GFP_KERNEL);
|
if (IS_ERR(devs)) {
|
||||||
if (!devs) {
|
err = PTR_ERR(devs);
|
||||||
err = -ENOMEM;
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
fscrypt_get_devices(sb, num_devs, devs);
|
|
||||||
for (i = 0; i < num_devs; i++) {
|
for (i = 0; i < num_devs; i++) {
|
||||||
err = blk_crypto_start_using_key(blk_key, devs[i]);
|
err = blk_crypto_start_using_key(blk_key,
|
||||||
|
bdev_get_queue(devs[i]));
|
||||||
if (err)
|
if (err)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -210,7 +213,7 @@ void fscrypt_destroy_inline_crypt_key(struct super_block *sb,
|
|||||||
struct fscrypt_prepared_key *prep_key)
|
struct fscrypt_prepared_key *prep_key)
|
||||||
{
|
{
|
||||||
struct blk_crypto_key *blk_key = prep_key->blk_key;
|
struct blk_crypto_key *blk_key = prep_key->blk_key;
|
||||||
struct request_queue **devs;
|
struct block_device **devs;
|
||||||
unsigned int num_devs;
|
unsigned int num_devs;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
@ -218,12 +221,10 @@ void fscrypt_destroy_inline_crypt_key(struct super_block *sb,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* Evict the key from all the filesystem's block devices. */
|
/* Evict the key from all the filesystem's block devices. */
|
||||||
num_devs = fscrypt_get_num_devices(sb);
|
devs = fscrypt_get_devices(sb, &num_devs);
|
||||||
devs = kmalloc_array(num_devs, sizeof(*devs), GFP_KERNEL);
|
if (!IS_ERR(devs)) {
|
||||||
if (devs) {
|
|
||||||
fscrypt_get_devices(sb, num_devs, devs);
|
|
||||||
for (i = 0; i < num_devs; i++)
|
for (i = 0; i < num_devs; i++)
|
||||||
blk_crypto_evict_key(devs[i], blk_key);
|
blk_crypto_evict_key(bdev_get_queue(devs[i]), blk_key);
|
||||||
kfree(devs);
|
kfree(devs);
|
||||||
}
|
}
|
||||||
kfree_sensitive(blk_key);
|
kfree_sensitive(blk_key);
|
||||||
|
@ -3039,23 +3039,24 @@ static void f2fs_get_ino_and_lblk_bits(struct super_block *sb,
|
|||||||
*lblk_bits_ret = 8 * sizeof(block_t);
|
*lblk_bits_ret = 8 * sizeof(block_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int f2fs_get_num_devices(struct super_block *sb)
|
static struct block_device **f2fs_get_devices(struct super_block *sb,
|
||||||
{
|
unsigned int *num_devs)
|
||||||
struct f2fs_sb_info *sbi = F2FS_SB(sb);
|
|
||||||
|
|
||||||
if (f2fs_is_multi_device(sbi))
|
|
||||||
return sbi->s_ndevs;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void f2fs_get_devices(struct super_block *sb,
|
|
||||||
struct request_queue **devs)
|
|
||||||
{
|
{
|
||||||
struct f2fs_sb_info *sbi = F2FS_SB(sb);
|
struct f2fs_sb_info *sbi = F2FS_SB(sb);
|
||||||
|
struct block_device **devs;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (!f2fs_is_multi_device(sbi))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
devs = kmalloc_array(sbi->s_ndevs, sizeof(*devs), GFP_KERNEL);
|
||||||
|
if (!devs)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
for (i = 0; i < sbi->s_ndevs; i++)
|
for (i = 0; i < sbi->s_ndevs; i++)
|
||||||
devs[i] = bdev_get_queue(FDEV(i).bdev);
|
devs[i] = FDEV(i).bdev;
|
||||||
|
*num_devs = sbi->s_ndevs;
|
||||||
|
return devs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct fscrypt_operations f2fs_cryptops = {
|
static const struct fscrypt_operations f2fs_cryptops = {
|
||||||
@ -3066,7 +3067,6 @@ static const struct fscrypt_operations f2fs_cryptops = {
|
|||||||
.empty_dir = f2fs_empty_dir,
|
.empty_dir = f2fs_empty_dir,
|
||||||
.has_stable_inodes = f2fs_has_stable_inodes,
|
.has_stable_inodes = f2fs_has_stable_inodes,
|
||||||
.get_ino_and_lblk_bits = f2fs_get_ino_and_lblk_bits,
|
.get_ino_and_lblk_bits = f2fs_get_ino_and_lblk_bits,
|
||||||
.get_num_devices = f2fs_get_num_devices,
|
|
||||||
.get_devices = f2fs_get_devices,
|
.get_devices = f2fs_get_devices,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
@ -161,24 +161,21 @@ struct fscrypt_operations {
|
|||||||
int *ino_bits_ret, int *lblk_bits_ret);
|
int *ino_bits_ret, int *lblk_bits_ret);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the number of block devices to which the filesystem may write
|
* Return an array of pointers to the block devices to which the
|
||||||
* encrypted file contents.
|
* filesystem may write encrypted file contents, NULL if the filesystem
|
||||||
|
* only has a single such block device, or an ERR_PTR() on error.
|
||||||
|
*
|
||||||
|
* 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().
|
||||||
*
|
*
|
||||||
* If the filesystem can use multiple block devices (other than block
|
* If the filesystem can use multiple block devices (other than block
|
||||||
* devices that aren't used for encrypted file contents, such as
|
* devices that aren't used for encrypted file contents, such as
|
||||||
* external journal devices), and wants to support inline encryption,
|
* external journal devices), and wants to support inline encryption,
|
||||||
* then it must implement this function. Otherwise it's not needed.
|
* then it must implement this function. Otherwise it's not needed.
|
||||||
*/
|
*/
|
||||||
int (*get_num_devices)(struct super_block *sb);
|
struct block_device **(*get_devices)(struct super_block *sb,
|
||||||
|
unsigned int *num_devs);
|
||||||
/*
|
|
||||||
* If ->get_num_devices() returns a value greater than 1, then this
|
|
||||||
* function is called to get the array of request_queues that the
|
|
||||||
* filesystem is using -- one per block device. (There may be duplicate
|
|
||||||
* entries in this array, as block devices can share a request_queue.)
|
|
||||||
*/
|
|
||||||
void (*get_devices)(struct super_block *sb,
|
|
||||||
struct request_queue **devs);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct fscrypt_info *fscrypt_get_info(const struct inode *inode)
|
static inline struct fscrypt_info *fscrypt_get_info(const struct inode *inode)
|
||||||
|
Loading…
Reference in New Issue
Block a user