Skip to content

Commit 2260840

Browse files
committed
Merge tag 'for-5.3/dm-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm
Pull device mapper updates from Mike Snitzer: - Add encrypted byte-offset initialization vector (eboiv) to DM crypt. - Add optional discard features to DM snapshot which allow freeing space from a DM device whose free space was exhausted. - Various small improvements to use struct_size() and kzalloc(). - Fix to check if DM thin metadata is in fail_io mode before attempting to update the superblock to set the needs_check flag. Otherwise the DM thin-pool can hang. - Fix DM bufio shrinker's potential for ABBA recursion deadlock with DM thin provisioning on loop usecase. * tag 'for-5.3/dm-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm: dm bufio: fix deadlock with loop device dm snapshot: add optional discard support features dm crypt: implement eboiv - encrypted byte-offset initialization vector dm crypt: remove obsolete comment about plumb IV dm crypt: wipe private IV struct after key invalid flag is set dm integrity: use kzalloc() instead of kmalloc() + memset() dm: update stale comment in end_clone_bio() dm log writes: fix incorrect comment about the logged sequence example dm log writes: use struct_size() to calculate size of pending_block dm crypt: use struct_size() when allocating encryption context dm integrity: always set version on superblock update dm thin metadata: check if in fail_io mode when setting needs_check
2 parents 92adeb6 + bd293d0 commit 2260840

File tree

8 files changed

+285
-44
lines changed

8 files changed

+285
-44
lines changed

Documentation/device-mapper/snapshot.rst

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ its visible content unchanged, at least until the <COW device> fills up.
3232

3333

3434
- snapshot <origin> <COW device> <persistent?> <chunksize>
35+
[<# feature args> [<arg>]*]
3536

3637
A snapshot of the <origin> block device is created. Changed chunks of
3738
<chunksize> sectors will be stored on the <COW device>. Writes will
@@ -54,8 +55,23 @@ When loading or unloading the snapshot target, the corresponding
5455
snapshot-origin or snapshot-merge target must be suspended. A failure to
5556
suspend the origin target could result in data corruption.
5657

58+
Optional features:
5759

58-
* snapshot-merge <origin> <COW device> <persistent> <chunksize>
60+
discard_zeroes_cow - a discard issued to the snapshot device that
61+
maps to entire chunks to will zero the corresponding exception(s) in
62+
the snapshot's exception store.
63+
64+
discard_passdown_origin - a discard to the snapshot device is passed
65+
down to the snapshot-origin's underlying device. This doesn't cause
66+
copy-out to the snapshot exception store because the snapshot-origin
67+
target is bypassed.
68+
69+
The discard_passdown_origin feature depends on the discard_zeroes_cow
70+
feature being enabled.
71+
72+
73+
- snapshot-merge <origin> <COW device> <persistent> <chunksize>
74+
[<# feature args> [<arg>]*]
5975

6076
takes the same table arguments as the snapshot target except it only
6177
works with persistent snapshots. This target assumes the role of the

drivers/md/dm-bufio.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1599,9 +1599,7 @@ dm_bufio_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
15991599
unsigned long freed;
16001600

16011601
c = container_of(shrink, struct dm_bufio_client, shrinker);
1602-
if (sc->gfp_mask & __GFP_FS)
1603-
dm_bufio_lock(c);
1604-
else if (!dm_bufio_trylock(c))
1602+
if (!dm_bufio_trylock(c))
16051603
return SHRINK_STOP;
16061604

16071605
freed = __scan(c, sc->nr_to_scan, sc->gfp_mask);

drivers/md/dm-crypt.c

Lines changed: 90 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ struct iv_tcw_private {
120120
u8 *whitening;
121121
};
122122

123+
struct iv_eboiv_private {
124+
struct crypto_cipher *tfm;
125+
};
126+
123127
/*
124128
* Crypt: maps a linear range of a block device
125129
* and encrypts / decrypts at the same time.
@@ -159,6 +163,7 @@ struct crypt_config {
159163
struct iv_benbi_private benbi;
160164
struct iv_lmk_private lmk;
161165
struct iv_tcw_private tcw;
166+
struct iv_eboiv_private eboiv;
162167
} iv_gen_private;
163168
u64 iv_offset;
164169
unsigned int iv_size;
@@ -291,8 +296,9 @@ static struct crypto_aead *any_tfm_aead(struct crypt_config *cc)
291296
* Note that this encryption scheme is vulnerable to watermarking attacks
292297
* and should be used for old compatible containers access only.
293298
*
294-
* plumb: unimplemented, see:
295-
* http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454
299+
* eboiv: Encrypted byte-offset IV (used in Bitlocker in CBC mode)
300+
* The IV is encrypted little-endian byte-offset (with the same key
301+
* and cipher as the volume).
296302
*/
297303

298304
static int crypt_iv_plain_gen(struct crypt_config *cc, u8 *iv,
@@ -841,6 +847,67 @@ static int crypt_iv_random_gen(struct crypt_config *cc, u8 *iv,
841847
return 0;
842848
}
843849

850+
static void crypt_iv_eboiv_dtr(struct crypt_config *cc)
851+
{
852+
struct iv_eboiv_private *eboiv = &cc->iv_gen_private.eboiv;
853+
854+
crypto_free_cipher(eboiv->tfm);
855+
eboiv->tfm = NULL;
856+
}
857+
858+
static int crypt_iv_eboiv_ctr(struct crypt_config *cc, struct dm_target *ti,
859+
const char *opts)
860+
{
861+
struct iv_eboiv_private *eboiv = &cc->iv_gen_private.eboiv;
862+
struct crypto_cipher *tfm;
863+
864+
tfm = crypto_alloc_cipher(cc->cipher, 0, 0);
865+
if (IS_ERR(tfm)) {
866+
ti->error = "Error allocating crypto tfm for EBOIV";
867+
return PTR_ERR(tfm);
868+
}
869+
870+
if (crypto_cipher_blocksize(tfm) != cc->iv_size) {
871+
ti->error = "Block size of EBOIV cipher does "
872+
"not match IV size of block cipher";
873+
crypto_free_cipher(tfm);
874+
return -EINVAL;
875+
}
876+
877+
eboiv->tfm = tfm;
878+
return 0;
879+
}
880+
881+
static int crypt_iv_eboiv_init(struct crypt_config *cc)
882+
{
883+
struct iv_eboiv_private *eboiv = &cc->iv_gen_private.eboiv;
884+
int err;
885+
886+
err = crypto_cipher_setkey(eboiv->tfm, cc->key, cc->key_size);
887+
if (err)
888+
return err;
889+
890+
return 0;
891+
}
892+
893+
static int crypt_iv_eboiv_wipe(struct crypt_config *cc)
894+
{
895+
/* Called after cc->key is set to random key in crypt_wipe() */
896+
return crypt_iv_eboiv_init(cc);
897+
}
898+
899+
static int crypt_iv_eboiv_gen(struct crypt_config *cc, u8 *iv,
900+
struct dm_crypt_request *dmreq)
901+
{
902+
struct iv_eboiv_private *eboiv = &cc->iv_gen_private.eboiv;
903+
904+
memset(iv, 0, cc->iv_size);
905+
*(__le64 *)iv = cpu_to_le64(dmreq->iv_sector * cc->sector_size);
906+
crypto_cipher_encrypt_one(eboiv->tfm, iv, iv);
907+
908+
return 0;
909+
}
910+
844911
static const struct crypt_iv_operations crypt_iv_plain_ops = {
845912
.generator = crypt_iv_plain_gen
846913
};
@@ -893,6 +960,14 @@ static struct crypt_iv_operations crypt_iv_random_ops = {
893960
.generator = crypt_iv_random_gen
894961
};
895962

963+
static struct crypt_iv_operations crypt_iv_eboiv_ops = {
964+
.ctr = crypt_iv_eboiv_ctr,
965+
.dtr = crypt_iv_eboiv_dtr,
966+
.init = crypt_iv_eboiv_init,
967+
.wipe = crypt_iv_eboiv_wipe,
968+
.generator = crypt_iv_eboiv_gen
969+
};
970+
896971
/*
897972
* Integrity extensions
898973
*/
@@ -2158,6 +2233,14 @@ static int crypt_wipe_key(struct crypt_config *cc)
21582233

21592234
clear_bit(DM_CRYPT_KEY_VALID, &cc->flags);
21602235
get_random_bytes(&cc->key, cc->key_size);
2236+
2237+
/* Wipe IV private keys */
2238+
if (cc->iv_gen_ops && cc->iv_gen_ops->wipe) {
2239+
r = cc->iv_gen_ops->wipe(cc);
2240+
if (r)
2241+
return r;
2242+
}
2243+
21612244
kzfree(cc->key_string);
21622245
cc->key_string = NULL;
21632246
r = crypt_setkey(cc);
@@ -2288,6 +2371,8 @@ static int crypt_ctr_ivmode(struct dm_target *ti, const char *ivmode)
22882371
cc->iv_gen_ops = &crypt_iv_benbi_ops;
22892372
else if (strcmp(ivmode, "null") == 0)
22902373
cc->iv_gen_ops = &crypt_iv_null_ops;
2374+
else if (strcmp(ivmode, "eboiv") == 0)
2375+
cc->iv_gen_ops = &crypt_iv_eboiv_ops;
22912376
else if (strcmp(ivmode, "lmk") == 0) {
22922377
cc->iv_gen_ops = &crypt_iv_lmk_ops;
22932378
/*
@@ -2699,7 +2784,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
26992784
return -EINVAL;
27002785
}
27012786

2702-
cc = kzalloc(sizeof(*cc) + key_size * sizeof(u8), GFP_KERNEL);
2787+
cc = kzalloc(struct_size(cc, key, key_size), GFP_KERNEL);
27032788
if (!cc) {
27042789
ti->error = "Cannot allocate encryption context";
27052790
return -ENOMEM;
@@ -3050,14 +3135,8 @@ static int crypt_message(struct dm_target *ti, unsigned argc, char **argv,
30503135
memset(cc->key, 0, cc->key_size * sizeof(u8));
30513136
return ret;
30523137
}
3053-
if (argc == 2 && !strcasecmp(argv[1], "wipe")) {
3054-
if (cc->iv_gen_ops && cc->iv_gen_ops->wipe) {
3055-
ret = cc->iv_gen_ops->wipe(cc);
3056-
if (ret)
3057-
return ret;
3058-
}
3138+
if (argc == 2 && !strcasecmp(argv[1], "wipe"))
30593139
return crypt_wipe_key(cc);
3060-
}
30613140
}
30623141

30633142
error:
@@ -3094,7 +3173,7 @@ static void crypt_io_hints(struct dm_target *ti, struct queue_limits *limits)
30943173

30953174
static struct target_type crypt_target = {
30963175
.name = "crypt",
3097-
.version = {1, 18, 1},
3176+
.version = {1, 19, 0},
30983177
.module = THIS_MODULE,
30993178
.ctr = crypt_ctr,
31003179
.dtr = crypt_dtr,

drivers/md/dm-integrity.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,9 @@ static int sync_rw_sb(struct dm_integrity_c *ic, int op, int op_flags)
476476
io_loc.sector = ic->start;
477477
io_loc.count = SB_SECTORS;
478478

479+
if (op == REQ_OP_WRITE)
480+
sb_set_version(ic);
481+
479482
return dm_io(&io_req, 1, &io_loc, NULL);
480483
}
481484

@@ -2317,7 +2320,6 @@ static void recalc_write_super(struct dm_integrity_c *ic)
23172320
if (dm_integrity_failed(ic))
23182321
return;
23192322

2320-
sb_set_version(ic);
23212323
r = sync_rw_sb(ic, REQ_OP_WRITE, 0);
23222324
if (unlikely(r))
23232325
dm_integrity_io_error(ic, "writing superblock", r);
@@ -3358,7 +3360,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
33583360
goto bad;
33593361
}
33603362

3361-
crypt_iv = kmalloc(ivsize, GFP_KERNEL);
3363+
crypt_iv = kzalloc(ivsize, GFP_KERNEL);
33623364
if (!crypt_iv) {
33633365
*error = "Could not allocate iv";
33643366
r = -ENOMEM;
@@ -3387,7 +3389,6 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
33873389
sg_set_buf(&sg[i], va, PAGE_SIZE);
33883390
}
33893391
sg_set_buf(&sg[i], &ic->commit_ids, sizeof ic->commit_ids);
3390-
memset(crypt_iv, 0x00, ivsize);
33913392

33923393
skcipher_request_set_crypt(req, sg, sg,
33933394
PAGE_SIZE * ic->journal_pages + sizeof ic->commit_ids, crypt_iv);

drivers/md/dm-log-writes.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
*
4141
* Would result in the log looking like this:
4242
*
43-
* c,a,flush,fuad,b,<other writes>,<next flush>
43+
* c,a,b,flush,fuad,<other writes>,<next flush>
4444
*
4545
* This is meant to help expose problems where file systems do not properly wait
4646
* on data being written before invoking a FLUSH. FUA bypasses cache so once it
@@ -699,7 +699,7 @@ static int log_writes_map(struct dm_target *ti, struct bio *bio)
699699
if (discard_bio)
700700
alloc_size = sizeof(struct pending_block);
701701
else
702-
alloc_size = sizeof(struct pending_block) + sizeof(struct bio_vec) * bio_segments(bio);
702+
alloc_size = struct_size(block, vecs, bio_segments(bio));
703703

704704
block = kzalloc(alloc_size, GFP_NOIO);
705705
if (!block) {

drivers/md/dm-rq.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ static void end_clone_bio(struct bio *clone)
115115

116116
/*
117117
* Update the original request.
118-
* Do not use blk_end_request() here, because it may complete
118+
* Do not use blk_mq_end_request() here, because it may complete
119119
* the original request before the clone, and break the ordering.
120120
*/
121121
if (is_last)

0 commit comments

Comments
 (0)