summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSatya Tangirala <satyat@google.com>2021-02-01 08:10:18 +0300
committerMike Snitzer <snitzer@redhat.com>2021-02-11 17:45:25 +0300
commit9355a9eb21a5c9b859ec838beb1874eef2e2a6d9 (patch)
tree115efa910dae43f1854cdc7a0157d9e7f85aaf1d
parentaa6ce87a768226802f9a231b3909fe81c503852c (diff)
downloadlinux-9355a9eb21a5c9b859ec838beb1874eef2e2a6d9.tar.xz
dm: support key eviction from keyslot managers of underlying devices
Now that device mapper supports inline encryption, add the ability to evict keys from all underlying devices. When an upper layer requests a key eviction, we simply iterate through all underlying devices and evict that key from each device. Co-developed-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Satya Tangirala <satyat@google.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
-rw-r--r--block/blk-crypto.c1
-rw-r--r--drivers/md/dm-table.c53
2 files changed, 54 insertions, 0 deletions
diff --git a/block/blk-crypto.c b/block/blk-crypto.c
index 09fcb18fa778..c5bdaafffa29 100644
--- a/block/blk-crypto.c
+++ b/block/blk-crypto.c
@@ -409,3 +409,4 @@ int blk_crypto_evict_key(struct request_queue *q,
*/
return blk_crypto_fallback_evict_key(key);
}
+EXPORT_SYMBOL_GPL(blk_crypto_evict_key);
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 8c4ed3ec9409..95391f78b8d5 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -1214,6 +1214,58 @@ struct dm_keyslot_manager {
struct mapped_device *md;
};
+struct dm_keyslot_evict_args {
+ const struct blk_crypto_key *key;
+ int err;
+};
+
+static int dm_keyslot_evict_callback(struct dm_target *ti, struct dm_dev *dev,
+ sector_t start, sector_t len, void *data)
+{
+ struct dm_keyslot_evict_args *args = data;
+ int err;
+
+ err = blk_crypto_evict_key(bdev_get_queue(dev->bdev), args->key);
+ if (!args->err)
+ args->err = err;
+ /* Always try to evict the key from all devices. */
+ return 0;
+}
+
+/*
+ * 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,
+ 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 dm_keyslot_evict_args args = { key };
+ struct dm_table *t;
+ int srcu_idx;
+ int i;
+ struct dm_target *ti;
+
+ t = dm_get_live_table(md, &srcu_idx);
+ if (!t)
+ return 0;
+ for (i = 0; i < dm_table_get_num_targets(t); i++) {
+ ti = dm_table_get_target(t, i);
+ if (!ti->type->iterate_devices)
+ continue;
+ ti->type->iterate_devices(ti, dm_keyslot_evict_callback, &args);
+ }
+ dm_put_live_table(md, srcu_idx);
+ return args.err;
+}
+
+static 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)
@@ -1270,6 +1322,7 @@ static int dm_table_construct_keyslot_manager(struct dm_table *t)
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));