Skip to content

Commit

Permalink
dm crypt: add missing error handling
Browse files Browse the repository at this point in the history
Always set io->error to -EIO when an error is detected in dm-crypt.

There were cases where an error code would be set only if we finish
processing the last sector. If there were other encryption operations in
flight, the error would be ignored and bio would be returned with
success as if no error happened.

This bug is present in kcryptd_crypt_write_convert, kcryptd_crypt_read_convert
and kcryptd_async_done.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Cc: stable@kernel.org
Reviewed-by: Milan Broz <mbroz@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
  • Loading branch information
Mikulas Patocka authored and Alasdair G Kergon committed Mar 28, 2012
1 parent aeb2dea commit 72c6e7a
Showing 1 changed file with 16 additions and 12 deletions.
28 changes: 16 additions & 12 deletions drivers/md/dm-crypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1044,16 +1044,14 @@ static void kcryptd_queue_io(struct dm_crypt_io *io)
queue_work(cc->io_queue, &io->work);
}

static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io,
int error, int async)
static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, int async)
{
struct bio *clone = io->ctx.bio_out;
struct crypt_config *cc = io->target->private;

if (unlikely(error < 0)) {
if (unlikely(io->error < 0)) {
crypt_free_buffer_pages(cc, clone);
bio_put(clone);
io->error = -EIO;
crypt_dec_pending(io);
return;
}
Expand Down Expand Up @@ -1104,12 +1102,16 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
sector += bio_sectors(clone);

crypt_inc_pending(io);

r = crypt_convert(cc, &io->ctx);
if (r < 0)
io->error = -EIO;

crypt_finished = atomic_dec_and_test(&io->ctx.pending);

/* Encryption was already finished, submit io now */
if (crypt_finished) {
kcryptd_crypt_write_io_submit(io, r, 0);
kcryptd_crypt_write_io_submit(io, 0);

/*
* If there was an error, do not try next fragments.
Expand Down Expand Up @@ -1160,11 +1162,8 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
crypt_dec_pending(io);
}

static void kcryptd_crypt_read_done(struct dm_crypt_io *io, int error)
static void kcryptd_crypt_read_done(struct dm_crypt_io *io)
{
if (unlikely(error < 0))
io->error = -EIO;

crypt_dec_pending(io);
}

Expand All @@ -1179,9 +1178,11 @@ static void kcryptd_crypt_read_convert(struct dm_crypt_io *io)
io->sector);

r = crypt_convert(cc, &io->ctx);
if (r < 0)
io->error = -EIO;

if (atomic_dec_and_test(&io->ctx.pending))
kcryptd_crypt_read_done(io, r);
kcryptd_crypt_read_done(io);

crypt_dec_pending(io);
}
Expand All @@ -1202,15 +1203,18 @@ static void kcryptd_async_done(struct crypto_async_request *async_req,
if (!error && cc->iv_gen_ops && cc->iv_gen_ops->post)
error = cc->iv_gen_ops->post(cc, iv_of_dmreq(cc, dmreq), dmreq);

if (error < 0)
io->error = -EIO;

mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool);

if (!atomic_dec_and_test(&ctx->pending))
return;

if (bio_data_dir(io->base_bio) == READ)
kcryptd_crypt_read_done(io, error);
kcryptd_crypt_read_done(io);
else
kcryptd_crypt_write_io_submit(io, error, 1);
kcryptd_crypt_write_io_submit(io, 1);
}

static void kcryptd_crypt(struct work_struct *work)
Expand Down

0 comments on commit 72c6e7a

Please sign in to comment.