Skip to content

Commit b6d9c22

Browse files
Hou Taogregkh
authored andcommitted
dm-crypt: track tag_offset in convert_context
commit 8b8f803 upstream. dm-crypt uses tag_offset to index the integrity metadata for each crypt sector. When the initial crypt_convert() returns BLK_STS_DEV_RESOURCE, dm-crypt will try to continue the crypt/decrypt procedure in a kworker. However, it resets tag_offset as zero instead of using the tag_offset related with current sector. It may return unexpected data when using random IV or return unexpected integrity related error. Fix the problem by tracking tag_offset in per-IO convert_context. Therefore, when the crypt/decrypt procedure continues in a kworker, it could use the next tag_offset saved in convert_context. Fixes: 8abec36 ("dm crypt: do not wait for backlogged crypto request completion in softirq") Cc: stable@vger.kernel.org Signed-off-by: Hou Tao <houtao1@huawei.com> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent c4cc18c commit b6d9c22

File tree

1 file changed

+7
-6
lines changed

1 file changed

+7
-6
lines changed

drivers/md/dm-crypt.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ struct convert_context {
5959
struct bio *bio_out;
6060
struct bvec_iter iter_out;
6161
atomic_t cc_pending;
62+
unsigned int tag_offset;
6263
u64 cc_sector;
6364
union {
6465
struct skcipher_request *req;
@@ -1256,6 +1257,7 @@ static void crypt_convert_init(struct crypt_config *cc,
12561257
if (bio_out)
12571258
ctx->iter_out = bio_out->bi_iter;
12581259
ctx->cc_sector = sector + cc->iv_offset;
1260+
ctx->tag_offset = 0;
12591261
init_completion(&ctx->restart);
12601262
}
12611263

@@ -1588,7 +1590,6 @@ static void crypt_free_req(struct crypt_config *cc, void *req, struct bio *base_
15881590
static blk_status_t crypt_convert(struct crypt_config *cc,
15891591
struct convert_context *ctx, bool atomic, bool reset_pending)
15901592
{
1591-
unsigned int tag_offset = 0;
15921593
unsigned int sector_step = cc->sector_size >> SECTOR_SHIFT;
15931594
int r;
15941595

@@ -1611,9 +1612,9 @@ static blk_status_t crypt_convert(struct crypt_config *cc,
16111612
atomic_inc(&ctx->cc_pending);
16121613

16131614
if (crypt_integrity_aead(cc))
1614-
r = crypt_convert_block_aead(cc, ctx, ctx->r.req_aead, tag_offset);
1615+
r = crypt_convert_block_aead(cc, ctx, ctx->r.req_aead, ctx->tag_offset);
16151616
else
1616-
r = crypt_convert_block_skcipher(cc, ctx, ctx->r.req, tag_offset);
1617+
r = crypt_convert_block_skcipher(cc, ctx, ctx->r.req, ctx->tag_offset);
16171618

16181619
switch (r) {
16191620
/*
@@ -1633,8 +1634,8 @@ static blk_status_t crypt_convert(struct crypt_config *cc,
16331634
* exit and continue processing in a workqueue
16341635
*/
16351636
ctx->r.req = NULL;
1637+
ctx->tag_offset++;
16361638
ctx->cc_sector += sector_step;
1637-
tag_offset++;
16381639
return BLK_STS_DEV_RESOURCE;
16391640
}
16401641
} else {
@@ -1648,16 +1649,16 @@ static blk_status_t crypt_convert(struct crypt_config *cc,
16481649
*/
16491650
case -EINPROGRESS:
16501651
ctx->r.req = NULL;
1652+
ctx->tag_offset++;
16511653
ctx->cc_sector += sector_step;
1652-
tag_offset++;
16531654
continue;
16541655
/*
16551656
* The request was already processed (synchronously).
16561657
*/
16571658
case 0:
16581659
atomic_dec(&ctx->cc_pending);
16591660
ctx->cc_sector += sector_step;
1660-
tag_offset++;
1661+
ctx->tag_offset++;
16611662
if (!atomic)
16621663
cond_resched();
16631664
continue;

0 commit comments

Comments
 (0)