[1/2] dm verity: init fec io before cleaning it

Message ID 419e7aa58f67d90020512892f7652623e8c9f059.1700555778.git.bo.wu@vivo.com
State New
Headers
Series dm verity: fix FEC stuck during lower dm suspend |

Commit Message

Wu Bo Nov. 21, 2023, 8:55 a.m. UTC
  If BIO error, it may goto verity_finish_io() before
verity_fec_init_io(). Therefor, the fec_io->rs is not initialized and
may crash when doing memory freeing in verity_fec_finish_io().

Crash call stack:
 die+0x90/0x2b8
 __do_kernel_fault+0x260/0x298
 do_bad_area+0x2c/0xdc
 do_translation_fault+0x3c/0x54
 do_mem_abort+0x54/0x118
 el1_abort+0x38/0x5c
 el1h_64_sync_handler+0x50/0x90
 el1h_64_sync+0x64/0x6c
 free_rs+0x18/0xac
 fec_rs_free+0x10/0x24
 mempool_free+0x58/0x148
 verity_fec_finish_io+0x4c/0xb0
 verity_end_io+0xb8/0x150

Signed-off-by: Wu Bo <bo.wu@vivo.com>
---
 drivers/md/dm-verity-target.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
  

Comments

Eric Biggers Nov. 21, 2023, 10:57 p.m. UTC | #1
On Tue, Nov 21, 2023 at 01:55:28AM -0700, Wu Bo wrote:
> If BIO error, it may goto verity_finish_io() before
> verity_fec_init_io(). Therefor, the fec_io->rs is not initialized and
> may crash when doing memory freeing in verity_fec_finish_io().
> 
> Crash call stack:
>  die+0x90/0x2b8
>  __do_kernel_fault+0x260/0x298
>  do_bad_area+0x2c/0xdc
>  do_translation_fault+0x3c/0x54
>  do_mem_abort+0x54/0x118
>  el1_abort+0x38/0x5c
>  el1h_64_sync_handler+0x50/0x90
>  el1h_64_sync+0x64/0x6c
>  free_rs+0x18/0xac
>  fec_rs_free+0x10/0x24
>  mempool_free+0x58/0x148
>  verity_fec_finish_io+0x4c/0xb0
>  verity_end_io+0xb8/0x150
> 
> Signed-off-by: Wu Bo <bo.wu@vivo.com>

What commit introduced this bug?  It looks like it was commit 5721d4e5a9cd ("dm
verity: Add optional "try_verify_in_tasklet" feature"), which moved the call to
verity_fec_init_io() from verity_map() to verity_work().  Do you agree?  Should
the call to verity_fec_init_io() perhaps be moved back to verity_map(), instead
of putting it in verity_end_io()?  Or maybe another call to verity_fec_init_io()
should be added only just before the call to verity_finish_io() in
verity_end_io(), given that it's not needed in the tasklet case?

In any case, please also add a Fixes tag with the appropriate commit, as well as
a "Cc stable" tag.

- Eric
  

Patch

diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c
index e115fcfe723c..42b2483eb08c 100644
--- a/drivers/md/dm-verity-target.c
+++ b/drivers/md/dm-verity-target.c
@@ -642,7 +642,6 @@  static void verity_work(struct work_struct *w)
 
 	io->in_tasklet = false;
 
-	verity_fec_init_io(io);
 	verity_finish_io(io, errno_to_blk_status(verity_verify_io(io)));
 }
 
@@ -667,6 +666,7 @@  static void verity_end_io(struct bio *bio)
 {
 	struct dm_verity_io *io = bio->bi_private;
 
+	verity_fec_init_io(io);
 	if (bio->bi_status &&
 	    (!verity_fec_is_enabled(io->v) || verity_is_system_shutting_down())) {
 		verity_finish_io(io, bio->bi_status);