blk-crypto: rename blk_keyslot_manager to blk_crypto_profile

blk_keyslot_manager is misnamed because it doesn't necessarily manage
keyslots.  It actually does several different things:

  - Contains the crypto capabilities of the device.

  - Provides functions to control the inline encryption hardware.
    Originally these were just for programming/evicting keyslots;
    however, new functionality (hardware-wrapped keys) will require new
    functions here which are unrelated to keyslots.  Moreover,
    device-mapper devices already (ab)use "keyslot_evict" to pass key
    eviction requests to their underlying devices even though
    device-mapper devices don't have any keyslots themselves (so it
    really should be "evict_key", not "keyslot_evict").

  - Sometimes (but not always!) it manages keyslots.  Originally it
    always did, but device-mapper devices don't have keyslots
    themselves, so they use a "passthrough keyslot manager" which
    doesn't actually manage keyslots.  This hack works, but the
    terminology is unnatural.  Also, some hardware doesn't have keyslots
    and thus also uses a "passthrough keyslot manager" (support for such
    hardware is yet to be upstreamed, but it will happen eventually).

Let's stop having keyslot managers which don't actually manage keyslots.
Instead, rename blk_keyslot_manager to blk_crypto_profile.

This is a fairly big change, since for consistency it also has to update
keyslot manager-related function names, variable names, and comments --
not just the actual struct name.  However it's still a fairly
straightforward change, as it doesn't change any actual functionality.

Acked-by: Ulf Hansson <ulf.hansson@linaro.org> # For MMC
Reviewed-by: Mike Snitzer <snitzer@redhat.com>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Eric Biggers <ebiggers@google.com>
Link: https://lore.kernel.org/r/20211018180453.40441-4-ebiggers@kernel.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Eric Biggers
2021-10-18 11:04:52 -07:00
committed by Jens Axboe
parent 1e8d44bddf
commit cb77cb5abe
18 changed files with 556 additions and 523 deletions

View File

@@ -200,7 +200,7 @@ struct dm_table {
struct dm_md_mempools *mempools;
#ifdef CONFIG_BLK_INLINE_ENCRYPTION
struct blk_keyslot_manager *ksm;
struct blk_crypto_profile *crypto_profile;
#endif
};

View File

@@ -170,7 +170,7 @@ static void free_devices(struct list_head *devices, struct mapped_device *md)
}
}
static void dm_table_destroy_keyslot_manager(struct dm_table *t);
static void dm_table_destroy_crypto_profile(struct dm_table *t);
void dm_table_destroy(struct dm_table *t)
{
@@ -200,7 +200,7 @@ void dm_table_destroy(struct dm_table *t)
dm_free_md_mempools(t->mempools);
dm_table_destroy_keyslot_manager(t);
dm_table_destroy_crypto_profile(t);
kfree(t);
}
@@ -1187,8 +1187,8 @@ static int dm_table_register_integrity(struct dm_table *t)
#ifdef CONFIG_BLK_INLINE_ENCRYPTION
struct dm_keyslot_manager {
struct blk_keyslot_manager ksm;
struct dm_crypto_profile {
struct blk_crypto_profile profile;
struct mapped_device *md;
};
@@ -1214,13 +1214,11 @@ static int dm_keyslot_evict_callback(struct dm_target *ti, struct dm_dev *dev,
* When an inline encryption key is evicted from a device-mapper device, evict
* it from all the underlying devices.
*/
static int dm_keyslot_evict(struct blk_keyslot_manager *ksm,
static int dm_keyslot_evict(struct blk_crypto_profile *profile,
const struct blk_crypto_key *key, unsigned int slot)
{
struct dm_keyslot_manager *dksm = container_of(ksm,
struct dm_keyslot_manager,
ksm);
struct mapped_device *md = dksm->md;
struct mapped_device *md =
container_of(profile, struct dm_crypto_profile, profile)->md;
struct dm_keyslot_evict_args args = { key };
struct dm_table *t;
int srcu_idx;
@@ -1240,150 +1238,148 @@ static int dm_keyslot_evict(struct blk_keyslot_manager *ksm,
return args.err;
}
static const struct blk_ksm_ll_ops dm_ksm_ll_ops = {
.keyslot_evict = dm_keyslot_evict,
};
static int device_intersect_crypto_modes(struct dm_target *ti,
struct dm_dev *dev, sector_t start,
sector_t len, void *data)
static int
device_intersect_crypto_capabilities(struct dm_target *ti, struct dm_dev *dev,
sector_t start, sector_t len, void *data)
{
struct blk_keyslot_manager *parent = data;
struct blk_keyslot_manager *child = bdev_get_queue(dev->bdev)->ksm;
struct blk_crypto_profile *parent = data;
struct blk_crypto_profile *child =
bdev_get_queue(dev->bdev)->crypto_profile;
blk_ksm_intersect_modes(parent, child);
blk_crypto_intersect_capabilities(parent, child);
return 0;
}
void dm_destroy_keyslot_manager(struct blk_keyslot_manager *ksm)
void dm_destroy_crypto_profile(struct blk_crypto_profile *profile)
{
struct dm_keyslot_manager *dksm = container_of(ksm,
struct dm_keyslot_manager,
ksm);
struct dm_crypto_profile *dmcp = container_of(profile,
struct dm_crypto_profile,
profile);
if (!ksm)
if (!profile)
return;
blk_ksm_destroy(ksm);
kfree(dksm);
blk_crypto_profile_destroy(profile);
kfree(dmcp);
}
static void dm_table_destroy_keyslot_manager(struct dm_table *t)
static void dm_table_destroy_crypto_profile(struct dm_table *t)
{
dm_destroy_keyslot_manager(t->ksm);
t->ksm = NULL;
dm_destroy_crypto_profile(t->crypto_profile);
t->crypto_profile = NULL;
}
/*
* Constructs and initializes t->ksm with a keyslot manager that
* represents the common set of crypto capabilities of the devices
* described by the dm_table. However, if the constructed keyslot
* manager does not support a superset of the crypto capabilities
* supported by the current keyslot manager of the mapped_device,
* it returns an error instead, since we don't support restricting
* crypto capabilities on table changes. Finally, if the constructed
* keyslot manager doesn't actually support any crypto modes at all,
* it just returns NULL.
* Constructs and initializes t->crypto_profile with a crypto profile that
* represents the common set of crypto capabilities of the devices described by
* the dm_table. However, if the constructed crypto profile doesn't support all
* crypto capabilities that are supported by the current mapped_device, it
* returns an error instead, since we don't support removing crypto capabilities
* on table changes. Finally, if the constructed crypto profile is "empty" (has
* no crypto capabilities at all), it just sets t->crypto_profile to NULL.
*/
static int dm_table_construct_keyslot_manager(struct dm_table *t)
static int dm_table_construct_crypto_profile(struct dm_table *t)
{
struct dm_keyslot_manager *dksm;
struct blk_keyslot_manager *ksm;
struct dm_crypto_profile *dmcp;
struct blk_crypto_profile *profile;
struct dm_target *ti;
unsigned int i;
bool ksm_is_empty = true;
bool empty_profile = true;
dksm = kmalloc(sizeof(*dksm), GFP_KERNEL);
if (!dksm)
dmcp = kmalloc(sizeof(*dmcp), GFP_KERNEL);
if (!dmcp)
return -ENOMEM;
dksm->md = t->md;
dmcp->md = t->md;
ksm = &dksm->ksm;
blk_ksm_init_passthrough(ksm);
ksm->ksm_ll_ops = dm_ksm_ll_ops;
ksm->max_dun_bytes_supported = UINT_MAX;
memset(ksm->crypto_modes_supported, 0xFF,
sizeof(ksm->crypto_modes_supported));
profile = &dmcp->profile;
blk_crypto_profile_init(profile, 0);
profile->ll_ops.keyslot_evict = dm_keyslot_evict;
profile->max_dun_bytes_supported = UINT_MAX;
memset(profile->modes_supported, 0xFF,
sizeof(profile->modes_supported));
for (i = 0; i < dm_table_get_num_targets(t); i++) {
ti = dm_table_get_target(t, i);
if (!dm_target_passes_crypto(ti->type)) {
blk_ksm_intersect_modes(ksm, NULL);
blk_crypto_intersect_capabilities(profile, NULL);
break;
}
if (!ti->type->iterate_devices)
continue;
ti->type->iterate_devices(ti, device_intersect_crypto_modes,
ksm);
ti->type->iterate_devices(ti,
device_intersect_crypto_capabilities,
profile);
}
if (t->md->queue && !blk_ksm_is_superset(ksm, t->md->queue->ksm)) {
if (t->md->queue &&
!blk_crypto_has_capabilities(profile,
t->md->queue->crypto_profile)) {
DMWARN("Inline encryption capabilities of new DM table were more restrictive than the old table's. This is not supported!");
dm_destroy_keyslot_manager(ksm);
dm_destroy_crypto_profile(profile);
return -EINVAL;
}
/*
* If the new KSM doesn't actually support any crypto modes, we may as
* well represent it with a NULL ksm.
* If the new profile doesn't actually support any crypto capabilities,
* we may as well represent it with a NULL profile.
*/
ksm_is_empty = true;
for (i = 0; i < ARRAY_SIZE(ksm->crypto_modes_supported); i++) {
if (ksm->crypto_modes_supported[i]) {
ksm_is_empty = false;
for (i = 0; i < ARRAY_SIZE(profile->modes_supported); i++) {
if (profile->modes_supported[i]) {
empty_profile = false;
break;
}
}
if (ksm_is_empty) {
dm_destroy_keyslot_manager(ksm);
ksm = NULL;
if (empty_profile) {
dm_destroy_crypto_profile(profile);
profile = NULL;
}
/*
* t->ksm is only set temporarily while the table is being set
* up, and it gets set to NULL after the capabilities have
* been transferred to the request_queue.
* t->crypto_profile is only set temporarily while the table is being
* set up, and it gets set to NULL after the profile has been
* transferred to the request_queue.
*/
t->ksm = ksm;
t->crypto_profile = profile;
return 0;
}
static void dm_update_keyslot_manager(struct request_queue *q,
struct dm_table *t)
static void dm_update_crypto_profile(struct request_queue *q,
struct dm_table *t)
{
if (!t->ksm)
if (!t->crypto_profile)
return;
/* Make the ksm less restrictive */
if (!q->ksm) {
blk_ksm_register(t->ksm, q);
/* Make the crypto profile less restrictive. */
if (!q->crypto_profile) {
blk_crypto_register(t->crypto_profile, q);
} else {
blk_ksm_update_capabilities(q->ksm, t->ksm);
dm_destroy_keyslot_manager(t->ksm);
blk_crypto_update_capabilities(q->crypto_profile,
t->crypto_profile);
dm_destroy_crypto_profile(t->crypto_profile);
}
t->ksm = NULL;
t->crypto_profile = NULL;
}
#else /* CONFIG_BLK_INLINE_ENCRYPTION */
static int dm_table_construct_keyslot_manager(struct dm_table *t)
static int dm_table_construct_crypto_profile(struct dm_table *t)
{
return 0;
}
void dm_destroy_keyslot_manager(struct blk_keyslot_manager *ksm)
void dm_destroy_crypto_profile(struct blk_crypto_profile *profile)
{
}
static void dm_table_destroy_keyslot_manager(struct dm_table *t)
static void dm_table_destroy_crypto_profile(struct dm_table *t)
{
}
static void dm_update_keyslot_manager(struct request_queue *q,
struct dm_table *t)
static void dm_update_crypto_profile(struct request_queue *q,
struct dm_table *t)
{
}
@@ -1415,9 +1411,9 @@ int dm_table_complete(struct dm_table *t)
return r;
}
r = dm_table_construct_keyslot_manager(t);
r = dm_table_construct_crypto_profile(t);
if (r) {
DMERR("could not construct keyslot manager.");
DMERR("could not construct crypto profile.");
return r;
}
@@ -2071,7 +2067,7 @@ int dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
return r;
}
dm_update_keyslot_manager(q, t);
dm_update_crypto_profile(q, t);
disk_update_readahead(t->md->disk);
return 0;

View File

@@ -1663,14 +1663,14 @@ static const struct dax_operations dm_dax_ops;
static void dm_wq_work(struct work_struct *work);
#ifdef CONFIG_BLK_INLINE_ENCRYPTION
static void dm_queue_destroy_keyslot_manager(struct request_queue *q)
static void dm_queue_destroy_crypto_profile(struct request_queue *q)
{
dm_destroy_keyslot_manager(q->ksm);
dm_destroy_crypto_profile(q->crypto_profile);
}
#else /* CONFIG_BLK_INLINE_ENCRYPTION */
static inline void dm_queue_destroy_keyslot_manager(struct request_queue *q)
static inline void dm_queue_destroy_crypto_profile(struct request_queue *q)
{
}
#endif /* !CONFIG_BLK_INLINE_ENCRYPTION */
@@ -1696,7 +1696,7 @@ static void cleanup_mapped_device(struct mapped_device *md)
dm_sysfs_exit(md);
del_gendisk(md->disk);
}
dm_queue_destroy_keyslot_manager(md->queue);
dm_queue_destroy_crypto_profile(md->queue);
blk_cleanup_disk(md->disk);
}