aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorSami Tolvanen <samitolvanen@google.com>2017-03-15 18:12:23 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-04-12 06:41:12 -0400
commit2ff087642643e9ac2aceb7a07c227357751c9a1b (patch)
tree951d0cf3498431fdbcfdc1b6954ce7c4e351a263 /drivers/md
parentd9fa4351037b60068e108465afb5ddf66b8d115e (diff)
dm verity fec: limit error correction recursion
commit f1a880a93baaadb14c10a348fd199f1cdb6bcccd upstream. If the hash tree itself is sufficiently corrupt in addition to data blocks, it's possible for error correction to end up in a deep recursive loop, which eventually causes a kernel panic. This change limits the recursion to a reasonable level during a single I/O operation. Fixes: a739ff3f543a ("dm verity: add support for forward error correction") Signed-off-by: Sami Tolvanen <samitolvanen@google.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/dm-verity-fec.c12
-rw-r--r--drivers/md/dm-verity-fec.h4
2 files changed, 15 insertions, 1 deletions
diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c
index 0f0eb8a3d922..c3cc04d89524 100644
--- a/drivers/md/dm-verity-fec.c
+++ b/drivers/md/dm-verity-fec.c
@@ -439,6 +439,13 @@ int verity_fec_decode(struct dm_verity *v, struct dm_verity_io *io,
439 if (!verity_fec_is_enabled(v)) 439 if (!verity_fec_is_enabled(v))
440 return -EOPNOTSUPP; 440 return -EOPNOTSUPP;
441 441
442 if (fio->level >= DM_VERITY_FEC_MAX_RECURSION) {
443 DMWARN_LIMIT("%s: FEC: recursion too deep", v->data_dev->name);
444 return -EIO;
445 }
446
447 fio->level++;
448
442 if (type == DM_VERITY_BLOCK_TYPE_METADATA) 449 if (type == DM_VERITY_BLOCK_TYPE_METADATA)
443 block += v->data_blocks; 450 block += v->data_blocks;
444 451
@@ -470,7 +477,7 @@ int verity_fec_decode(struct dm_verity *v, struct dm_verity_io *io,
470 if (r < 0) { 477 if (r < 0) {
471 r = fec_decode_rsb(v, io, fio, rsb, offset, true); 478 r = fec_decode_rsb(v, io, fio, rsb, offset, true);
472 if (r < 0) 479 if (r < 0)
473 return r; 480 goto done;
474 } 481 }
475 482
476 if (dest) 483 if (dest)
@@ -480,6 +487,8 @@ int verity_fec_decode(struct dm_verity *v, struct dm_verity_io *io,
480 r = verity_for_bv_block(v, io, iter, fec_bv_copy); 487 r = verity_for_bv_block(v, io, iter, fec_bv_copy);
481 } 488 }
482 489
490done:
491 fio->level--;
483 return r; 492 return r;
484} 493}
485 494
@@ -520,6 +529,7 @@ void verity_fec_init_io(struct dm_verity_io *io)
520 memset(fio->bufs, 0, sizeof(fio->bufs)); 529 memset(fio->bufs, 0, sizeof(fio->bufs));
521 fio->nbufs = 0; 530 fio->nbufs = 0;
522 fio->output = NULL; 531 fio->output = NULL;
532 fio->level = 0;
523} 533}
524 534
525/* 535/*
diff --git a/drivers/md/dm-verity-fec.h b/drivers/md/dm-verity-fec.h
index 7fa0298b995e..bb31ce87a933 100644
--- a/drivers/md/dm-verity-fec.h
+++ b/drivers/md/dm-verity-fec.h
@@ -27,6 +27,9 @@
27#define DM_VERITY_FEC_BUF_MAX \ 27#define DM_VERITY_FEC_BUF_MAX \
28 (1 << (PAGE_SHIFT - DM_VERITY_FEC_BUF_RS_BITS)) 28 (1 << (PAGE_SHIFT - DM_VERITY_FEC_BUF_RS_BITS))
29 29
30/* maximum recursion level for verity_fec_decode */
31#define DM_VERITY_FEC_MAX_RECURSION 4
32
30#define DM_VERITY_OPT_FEC_DEV "use_fec_from_device" 33#define DM_VERITY_OPT_FEC_DEV "use_fec_from_device"
31#define DM_VERITY_OPT_FEC_BLOCKS "fec_blocks" 34#define DM_VERITY_OPT_FEC_BLOCKS "fec_blocks"
32#define DM_VERITY_OPT_FEC_START "fec_start" 35#define DM_VERITY_OPT_FEC_START "fec_start"
@@ -58,6 +61,7 @@ struct dm_verity_fec_io {
58 unsigned nbufs; /* number of buffers allocated */ 61 unsigned nbufs; /* number of buffers allocated */
59 u8 *output; /* buffer for corrected output */ 62 u8 *output; /* buffer for corrected output */
60 size_t output_pos; 63 size_t output_pos;
64 unsigned level; /* recursion level */
61}; 65};
62 66
63#ifdef CONFIG_DM_VERITY_FEC 67#ifdef CONFIG_DM_VERITY_FEC