Skip to content

Commit 325b764

Browse files
committed
Merge tag 'for-5.12/dm-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm
Pull device mapper updates from Mike Snitzer: - Fix DM integrity's HMAC support to provide enhanced security of internal_hash and journal_mac capabilities. - Various DM writecache fixes to address performance, fix table output to match what was provided at table creation, fix writing beyond end of device when shrinking underlying data device, and a couple other small cleanups. - Add DM crypt support for using trusted keys. - Fix deadlock when swapping to DM crypt device by throttling number of in-flight REQ_SWAP bios. Implemented in DM core so that other bio-based targets can opt-in by setting ti->limit_swap_bios. - Fix various inverted logic bugs in the .iterate_devices callout functions that are used to assess if specific feature or capability is supported across all devices being combined/stacked by DM. - Fix DM era target bugs that exposed users to lost writes or memory leaks. - Add DM core support for passing through inline crypto support of underlying devices. Includes block/keyslot-manager changes that enable extending this support to DM. - Various small fixes and cleanups (spelling fixes, front padding calculation cleanup, cleanup conditional zoned support in targets, etc). * tag 'for-5.12/dm-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm: (31 commits) dm: fix deadlock when swapping to encrypted device dm: simplify target code conditional on CONFIG_BLK_DEV_ZONED dm: set DM_TARGET_PASSES_CRYPTO feature for some targets dm: support key eviction from keyslot managers of underlying devices dm: add support for passing through inline crypto support block/keyslot-manager: Introduce functions for device mapper support block/keyslot-manager: Introduce passthrough keyslot manager dm era: only resize metadata in preresume dm era: Use correct value size in equality function of writeset tree dm era: Fix bitset memory leaks dm era: Verify the data block size hasn't changed dm era: Reinitialize bitset cache before digesting a new writeset dm era: Update in-core bitset after committing the metadata dm era: Recover committed writeset after crash dm writecache: use bdev_nr_sectors() instead of open-coded equivalent dm writecache: fix writing beyond end of underlying device when shrinking dm table: remove needless request_queue NULL pointer checks dm table: fix zoned iterate_devices based device capability checks dm table: fix DAX iterate_devices based device capability checks dm table: fix iterate_devices based device capability checks ...
2 parents a99163e + a666e5c commit 325b764

File tree

21 files changed

+868
-218
lines changed

21 files changed

+868
-218
lines changed

Documentation/admin-guide/device-mapper/dm-crypt.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ Parameters::
6767
the value passed in <key_size>.
6868

6969
<key_type>
70-
Either 'logon', 'user' or 'encrypted' kernel key type.
70+
Either 'logon', 'user', 'encrypted' or 'trusted' kernel key type.
7171

7272
<key_description>
7373
The kernel keyring key description crypt target should look for

Documentation/admin-guide/device-mapper/dm-integrity.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,17 @@ fix_padding
186186
space-efficient. If this option is not present, large padding is
187187
used - that is for compatibility with older kernels.
188188

189+
fix_hmac
190+
Improve security of internal_hash and journal_mac:
191+
192+
- the section number is mixed to the mac, so that an attacker can't
193+
copy sectors from one journal section to another journal section
194+
- the superblock is protected by journal_mac
195+
- a 16-byte salt stored in the superblock is mixed to the mac, so
196+
that the attacker can't detect that two disks have the same hmac
197+
key and also to disallow the attacker to move sectors from one
198+
disk to another
199+
189200
legacy_recalculate
190201
Allow recalculating of volumes with HMAC keys. This is disabled by
191202
default for security reasons - an attacker could modify the volume,

block/blk-crypto.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,3 +409,4 @@ int blk_crypto_evict_key(struct request_queue *q,
409409
*/
410410
return blk_crypto_fallback_evict_key(key);
411411
}
412+
EXPORT_SYMBOL_GPL(blk_crypto_evict_key);

block/keyslot-manager.c

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ static inline void blk_ksm_hw_exit(struct blk_keyslot_manager *ksm)
6363
pm_runtime_put_sync(ksm->dev);
6464
}
6565

66+
static inline bool blk_ksm_is_passthrough(struct blk_keyslot_manager *ksm)
67+
{
68+
return ksm->num_slots == 0;
69+
}
70+
6671
/**
6772
* blk_ksm_init() - Initialize a keyslot manager
6873
* @ksm: The keyslot_manager to initialize.
@@ -234,6 +239,10 @@ blk_status_t blk_ksm_get_slot_for_key(struct blk_keyslot_manager *ksm,
234239
int err;
235240

236241
*slot_ptr = NULL;
242+
243+
if (blk_ksm_is_passthrough(ksm))
244+
return BLK_STS_OK;
245+
237246
down_read(&ksm->lock);
238247
slot = blk_ksm_find_and_grab_keyslot(ksm, key);
239248
up_read(&ksm->lock);
@@ -354,6 +363,16 @@ int blk_ksm_evict_key(struct blk_keyslot_manager *ksm,
354363
struct blk_ksm_keyslot *slot;
355364
int err = 0;
356365

366+
if (blk_ksm_is_passthrough(ksm)) {
367+
if (ksm->ksm_ll_ops.keyslot_evict) {
368+
blk_ksm_hw_enter(ksm);
369+
err = ksm->ksm_ll_ops.keyslot_evict(ksm, key, -1);
370+
blk_ksm_hw_exit(ksm);
371+
return err;
372+
}
373+
return 0;
374+
}
375+
357376
blk_ksm_hw_enter(ksm);
358377
slot = blk_ksm_find_keyslot(ksm, key);
359378
if (!slot)
@@ -389,6 +408,9 @@ void blk_ksm_reprogram_all_keys(struct blk_keyslot_manager *ksm)
389408
{
390409
unsigned int slot;
391410

411+
if (blk_ksm_is_passthrough(ksm))
412+
return;
413+
392414
/* This is for device initialization, so don't resume the device */
393415
down_write(&ksm->lock);
394416
for (slot = 0; slot < ksm->num_slots; slot++) {
@@ -430,3 +452,127 @@ void blk_ksm_unregister(struct request_queue *q)
430452
{
431453
q->ksm = NULL;
432454
}
455+
456+
/**
457+
* blk_ksm_intersect_modes() - restrict supported modes by child device
458+
* @parent: The keyslot manager for parent device
459+
* @child: The keyslot manager for child device, or NULL
460+
*
461+
* Clear any crypto mode support bits in @parent that aren't set in @child.
462+
* If @child is NULL, then all parent bits are cleared.
463+
*
464+
* Only use this when setting up the keyslot manager for a layered device,
465+
* before it's been exposed yet.
466+
*/
467+
void blk_ksm_intersect_modes(struct blk_keyslot_manager *parent,
468+
const struct blk_keyslot_manager *child)
469+
{
470+
if (child) {
471+
unsigned int i;
472+
473+
parent->max_dun_bytes_supported =
474+
min(parent->max_dun_bytes_supported,
475+
child->max_dun_bytes_supported);
476+
for (i = 0; i < ARRAY_SIZE(child->crypto_modes_supported);
477+
i++) {
478+
parent->crypto_modes_supported[i] &=
479+
child->crypto_modes_supported[i];
480+
}
481+
} else {
482+
parent->max_dun_bytes_supported = 0;
483+
memset(parent->crypto_modes_supported, 0,
484+
sizeof(parent->crypto_modes_supported));
485+
}
486+
}
487+
EXPORT_SYMBOL_GPL(blk_ksm_intersect_modes);
488+
489+
/**
490+
* blk_ksm_is_superset() - Check if a KSM supports a superset of crypto modes
491+
* and DUN bytes that another KSM supports. Here,
492+
* "superset" refers to the mathematical meaning of the
493+
* word - i.e. if two KSMs have the *same* capabilities,
494+
* they *are* considered supersets of each other.
495+
* @ksm_superset: The KSM that we want to verify is a superset
496+
* @ksm_subset: The KSM that we want to verify is a subset
497+
*
498+
* Return: True if @ksm_superset supports a superset of the crypto modes and DUN
499+
* bytes that @ksm_subset supports.
500+
*/
501+
bool blk_ksm_is_superset(struct blk_keyslot_manager *ksm_superset,
502+
struct blk_keyslot_manager *ksm_subset)
503+
{
504+
int i;
505+
506+
if (!ksm_subset)
507+
return true;
508+
509+
if (!ksm_superset)
510+
return false;
511+
512+
for (i = 0; i < ARRAY_SIZE(ksm_superset->crypto_modes_supported); i++) {
513+
if (ksm_subset->crypto_modes_supported[i] &
514+
(~ksm_superset->crypto_modes_supported[i])) {
515+
return false;
516+
}
517+
}
518+
519+
if (ksm_subset->max_dun_bytes_supported >
520+
ksm_superset->max_dun_bytes_supported) {
521+
return false;
522+
}
523+
524+
return true;
525+
}
526+
EXPORT_SYMBOL_GPL(blk_ksm_is_superset);
527+
528+
/**
529+
* blk_ksm_update_capabilities() - Update the restrictions of a KSM to those of
530+
* another KSM
531+
* @target_ksm: The KSM whose restrictions to update.
532+
* @reference_ksm: The KSM to whose restrictions this function will update
533+
* @target_ksm's restrictions to.
534+
*
535+
* Blk-crypto requires that crypto capabilities that were
536+
* advertised when a bio was created continue to be supported by the
537+
* device until that bio is ended. This is turn means that a device cannot
538+
* shrink its advertised crypto capabilities without any explicit
539+
* synchronization with upper layers. So if there's no such explicit
540+
* synchronization, @reference_ksm must support all the crypto capabilities that
541+
* @target_ksm does
542+
* (i.e. we need blk_ksm_is_superset(@reference_ksm, @target_ksm) == true).
543+
*
544+
* Note also that as long as the crypto capabilities are being expanded, the
545+
* order of updates becoming visible is not important because it's alright
546+
* for blk-crypto to see stale values - they only cause blk-crypto to
547+
* believe that a crypto capability isn't supported when it actually is (which
548+
* might result in blk-crypto-fallback being used if available, or the bio being
549+
* failed).
550+
*/
551+
void blk_ksm_update_capabilities(struct blk_keyslot_manager *target_ksm,
552+
struct blk_keyslot_manager *reference_ksm)
553+
{
554+
memcpy(target_ksm->crypto_modes_supported,
555+
reference_ksm->crypto_modes_supported,
556+
sizeof(target_ksm->crypto_modes_supported));
557+
558+
target_ksm->max_dun_bytes_supported =
559+
reference_ksm->max_dun_bytes_supported;
560+
}
561+
EXPORT_SYMBOL_GPL(blk_ksm_update_capabilities);
562+
563+
/**
564+
* blk_ksm_init_passthrough() - Init a passthrough keyslot manager
565+
* @ksm: The keyslot manager to init
566+
*
567+
* Initialize a passthrough keyslot manager.
568+
* Called by e.g. storage drivers to set up a keyslot manager in their
569+
* request_queue, when the storage driver wants to manage its keys by itself.
570+
* This is useful for inline encryption hardware that doesn't have the concept
571+
* of keyslots, and for layered devices.
572+
*/
573+
void blk_ksm_init_passthrough(struct blk_keyslot_manager *ksm)
574+
{
575+
memset(ksm, 0, sizeof(*ksm));
576+
init_rwsem(&ksm->lock);
577+
}
578+
EXPORT_SYMBOL_GPL(blk_ksm_init_passthrough);

drivers/md/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ config DM_CRYPT
270270
tristate "Crypt target support"
271271
depends on BLK_DEV_DM
272272
depends on (ENCRYPTED_KEYS || ENCRYPTED_KEYS=n)
273+
depends on (TRUSTED_KEYS || TRUSTED_KEYS=n)
273274
select CRYPTO
274275
select CRYPTO_CBC
275276
select CRYPTO_ESSIV

drivers/md/dm-core.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/ktime.h>
1414
#include <linux/genhd.h>
1515
#include <linux/blk-mq.h>
16+
#include <linux/keyslot-manager.h>
1617

1718
#include <trace/events/block.h>
1819

@@ -102,6 +103,10 @@ struct mapped_device {
102103
/* kobject and completion */
103104
struct dm_kobject_holder kobj_holder;
104105

106+
int swap_bios;
107+
struct semaphore swap_bios_semaphore;
108+
struct mutex swap_bios_lock;
109+
105110
struct dm_stats stats;
106111

107112
/* for blk-mq request-based DM support */
@@ -162,6 +167,10 @@ struct dm_table {
162167
void *event_context;
163168

164169
struct dm_md_mempools *mempools;
170+
171+
#ifdef CONFIG_BLK_INLINE_ENCRYPTION
172+
struct blk_keyslot_manager *ksm;
173+
#endif
165174
};
166175

167176
static inline struct completion *dm_get_completion_from_kobject(struct kobject *kobj)

drivers/md/dm-crypt.c

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include <linux/key-type.h>
3838
#include <keys/user-type.h>
3939
#include <keys/encrypted-type.h>
40+
#include <keys/trusted-type.h>
4041

4142
#include <linux/device-mapper.h>
4243

@@ -133,7 +134,7 @@ enum flags { DM_CRYPT_SUSPENDED, DM_CRYPT_KEY_VALID,
133134
DM_CRYPT_WRITE_INLINE };
134135

135136
enum cipher_flags {
136-
CRYPT_MODE_INTEGRITY_AEAD, /* Use authenticated mode for cihper */
137+
CRYPT_MODE_INTEGRITY_AEAD, /* Use authenticated mode for cipher */
137138
CRYPT_IV_LARGE_SECTORS, /* Calculate IV from sector_size, not 512B sectors */
138139
CRYPT_ENCRYPT_PREPROCESS, /* Must preprocess data for encryption (elephant) */
139140
};
@@ -2436,7 +2437,6 @@ static int set_key_user(struct crypt_config *cc, struct key *key)
24362437
return 0;
24372438
}
24382439

2439-
#if defined(CONFIG_ENCRYPTED_KEYS) || defined(CONFIG_ENCRYPTED_KEYS_MODULE)
24402440
static int set_key_encrypted(struct crypt_config *cc, struct key *key)
24412441
{
24422442
const struct encrypted_key_payload *ekp;
@@ -2452,7 +2452,22 @@ static int set_key_encrypted(struct crypt_config *cc, struct key *key)
24522452

24532453
return 0;
24542454
}
2455-
#endif /* CONFIG_ENCRYPTED_KEYS */
2455+
2456+
static int set_key_trusted(struct crypt_config *cc, struct key *key)
2457+
{
2458+
const struct trusted_key_payload *tkp;
2459+
2460+
tkp = key->payload.data[0];
2461+
if (!tkp)
2462+
return -EKEYREVOKED;
2463+
2464+
if (cc->key_size != tkp->key_len)
2465+
return -EINVAL;
2466+
2467+
memcpy(cc->key, tkp->key, cc->key_size);
2468+
2469+
return 0;
2470+
}
24562471

24572472
static int crypt_set_keyring_key(struct crypt_config *cc, const char *key_string)
24582473
{
@@ -2482,11 +2497,14 @@ static int crypt_set_keyring_key(struct crypt_config *cc, const char *key_string
24822497
} else if (!strncmp(key_string, "user:", key_desc - key_string + 1)) {
24832498
type = &key_type_user;
24842499
set_key = set_key_user;
2485-
#if defined(CONFIG_ENCRYPTED_KEYS) || defined(CONFIG_ENCRYPTED_KEYS_MODULE)
2486-
} else if (!strncmp(key_string, "encrypted:", key_desc - key_string + 1)) {
2500+
} else if (IS_ENABLED(CONFIG_ENCRYPTED_KEYS) &&
2501+
!strncmp(key_string, "encrypted:", key_desc - key_string + 1)) {
24872502
type = &key_type_encrypted;
24882503
set_key = set_key_encrypted;
2489-
#endif
2504+
} else if (IS_ENABLED(CONFIG_TRUSTED_KEYS) &&
2505+
!strncmp(key_string, "trusted:", key_desc - key_string + 1)) {
2506+
type = &key_type_trusted;
2507+
set_key = set_key_trusted;
24902508
} else {
24912509
return -EINVAL;
24922510
}
@@ -3116,7 +3134,6 @@ static int crypt_ctr_optional(struct dm_target *ti, unsigned int argc, char **ar
31163134
}
31173135

31183136
#ifdef CONFIG_BLK_DEV_ZONED
3119-
31203137
static int crypt_report_zones(struct dm_target *ti,
31213138
struct dm_report_zones_args *args, unsigned int nr_zones)
31223139
{
@@ -3127,7 +3144,8 @@ static int crypt_report_zones(struct dm_target *ti,
31273144
return blkdev_report_zones(cc->dev->bdev, sector, nr_zones,
31283145
dm_report_zones_cb, args);
31293146
}
3130-
3147+
#else
3148+
#define crypt_report_zones NULL
31313149
#endif
31323150

31333151
/*
@@ -3324,6 +3342,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
33243342
wake_up_process(cc->write_thread);
33253343

33263344
ti->num_flush_bios = 1;
3345+
ti->limit_swap_bios = true;
33273346

33283347
return 0;
33293348

@@ -3558,14 +3577,12 @@ static void crypt_io_hints(struct dm_target *ti, struct queue_limits *limits)
35583577

35593578
static struct target_type crypt_target = {
35603579
.name = "crypt",
3561-
.version = {1, 22, 0},
3580+
.version = {1, 23, 0},
35623581
.module = THIS_MODULE,
35633582
.ctr = crypt_ctr,
35643583
.dtr = crypt_dtr,
3565-
#ifdef CONFIG_BLK_DEV_ZONED
35663584
.features = DM_TARGET_ZONED_HM,
35673585
.report_zones = crypt_report_zones,
3568-
#endif
35693586
.map = crypt_map,
35703587
.status = crypt_status,
35713588
.postsuspend = crypt_postsuspend,

drivers/md/dm-dust.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ static int dust_add_block(struct dust_device *dd, unsigned long long block,
130130

131131
dd->badblock_count++;
132132
if (!dd->quiet_mode) {
133-
DMINFO("%s: badblock added at block %llu with write fail count %hhu",
133+
DMINFO("%s: badblock added at block %llu with write fail count %u",
134134
__func__, block, wr_fail_cnt);
135135
}
136136
spin_unlock_irqrestore(&dd->dust_lock, flags);

0 commit comments

Comments
 (0)