Coly Li ec13f5
From 3534e5a5ed2997ca1b00f44a0378a075bd05e8a3 Mon Sep 17 00:00:00 2001
Coly Li ec13f5
From: Luo Meng <luomeng12@huawei.com>
Coly Li ec13f5
Date: Thu, 14 Jul 2022 19:28:25 +0800
Coly Li ec13f5
Subject: [PATCH] dm thin: fix use-after-free crash in
Coly Li ec13f5
 dm_sm_register_threshold_callback
Coly Li ec13f5
Git-commit: 3534e5a5ed2997ca1b00f44a0378a075bd05e8a3
Coly Li ec13f5
Patch-mainline: v6.0-rc1
Coly Li ec13f5
References: git-fixes
Coly Li ec13f5
Coly Li ec13f5
Fault inject on pool metadata device reports:
Coly Li ec13f5
  BUG: KASAN: use-after-free in dm_pool_register_metadata_threshold+0x40/0x80
Coly Li ec13f5
  Read of size 8 at addr ffff8881b9d50068 by task dmsetup/950
Coly Li ec13f5
Coly Li ec13f5
  CPU: 7 PID: 950 Comm: dmsetup Tainted: G        W         5.19.0-rc6 #1
Coly Li ec13f5
  Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-1.fc33 04/01/2014
Coly Li ec13f5
  Call Trace:
Coly Li ec13f5
   <TASK>
Coly Li ec13f5
   dump_stack_lvl+0x34/0x44
Coly Li ec13f5
   print_address_description.constprop.0.cold+0xeb/0x3f4
Coly Li ec13f5
   kasan_report.cold+0xe6/0x147
Coly Li ec13f5
   dm_pool_register_metadata_threshold+0x40/0x80
Coly Li ec13f5
   pool_ctr+0xa0a/0x1150
Coly Li ec13f5
   dm_table_add_target+0x2c8/0x640
Coly Li ec13f5
   table_load+0x1fd/0x430
Coly Li ec13f5
   ctl_ioctl+0x2c4/0x5a0
Coly Li ec13f5
   dm_ctl_ioctl+0xa/0x10
Coly Li ec13f5
   __x64_sys_ioctl+0xb3/0xd0
Coly Li ec13f5
   do_syscall_64+0x35/0x80
Coly Li ec13f5
   entry_SYSCALL_64_after_hwframe+0x46/0xb0
Coly Li ec13f5
Coly Li ec13f5
This can be easily reproduced using:
Coly Li ec13f5
  echo offline > /sys/block/sda/device/state
Coly Li ec13f5
  dd if=/dev/zero of=/dev/mapper/thin bs=4k count=10
Coly Li ec13f5
  dmsetup load pool --table "0 20971520 thin-pool /dev/sda /dev/sdb 128 0 0"
Coly Li ec13f5
Coly Li ec13f5
If a metadata commit fails, the transaction will be aborted and the
Coly Li ec13f5
metadata space maps will be destroyed. If a DM table reload then
Coly Li ec13f5
happens for this failed thin-pool, a use-after-free will occur in
Coly Li ec13f5
dm_sm_register_threshold_callback (called from
Coly Li ec13f5
dm_pool_register_metadata_threshold).
Coly Li ec13f5
Coly Li ec13f5
Fix this by in dm_pool_register_metadata_threshold() by returning the
Coly Li ec13f5
-EINVAL error if the thin-pool is in fail mode. Also fail pool_ctr()
Coly Li ec13f5
with a new error message: "Error registering metadata threshold".
Coly Li ec13f5
Coly Li ec13f5
Fixes: ac8c3f3df65e4 ("dm thin: generate event when metadata threshold passed")
Coly Li ec13f5
Cc: stable@vger.kernel.org
Coly Li ec13f5
Reported-by: Hulk Robot <hulkci@huawei.com>
Coly Li ec13f5
Signed-off-by: Luo Meng <luomeng12@huawei.com>
Coly Li ec13f5
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Coly Li ec13f5
Signed-off-by: Coly Li <colyli@suse.de>
Coly Li ec13f5
Coly Li ec13f5
---
Coly Li ec13f5
 drivers/md/dm-thin-metadata.c | 7 +++++--
Coly Li ec13f5
 drivers/md/dm-thin.c          | 4 +++-
Coly Li ec13f5
 2 files changed, 8 insertions(+), 3 deletions(-)
Coly Li ec13f5
Coly Li ec13f5
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
Coly Li ec13f5
index 2db7030aba00..a27395c8621f 100644
Coly Li ec13f5
--- a/drivers/md/dm-thin-metadata.c
Coly Li ec13f5
+++ b/drivers/md/dm-thin-metadata.c
Coly Li ec13f5
@@ -2045,10 +2045,13 @@ int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
Coly Li ec13f5
 					dm_sm_threshold_fn fn,
Coly Li ec13f5
 					void *context)
Coly Li ec13f5
 {
Coly Li ec13f5
-	int r;
Coly Li ec13f5
+	int r = -EINVAL;
Coly Li ec13f5
 
Coly Li ec13f5
 	pmd_write_lock_in_core(pmd);
Coly Li ec13f5
-	r = dm_sm_register_threshold_callback(pmd->metadata_sm, threshold, fn, context);
Coly Li ec13f5
+	if (!pmd->fail_io) {
Coly Li ec13f5
+		r = dm_sm_register_threshold_callback(pmd->metadata_sm,
Coly Li ec13f5
+						      threshold, fn, context);
Coly Li ec13f5
+	}
Coly Li ec13f5
 	pmd_write_unlock(pmd);
Coly Li ec13f5
 
Coly Li ec13f5
 	return r;
Coly Li ec13f5
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
Coly Li ec13f5
index 84c083f76673..e76c96c760a9 100644
Coly Li ec13f5
--- a/drivers/md/dm-thin.c
Coly Li ec13f5
+++ b/drivers/md/dm-thin.c
Coly Li ec13f5
@@ -3375,8 +3375,10 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
Coly Li ec13f5
 						calc_metadata_threshold(pt),
Coly Li ec13f5
 						metadata_low_callback,
Coly Li ec13f5
 						pool);
Coly Li ec13f5
-	if (r)
Coly Li ec13f5
+	if (r) {
Coly Li ec13f5
+		ti->error = "Error registering metadata threshold";
Coly Li ec13f5
 		goto out_flags_changed;
Coly Li ec13f5
+	}
Coly Li ec13f5
 
Coly Li ec13f5
 	dm_pool_register_pre_commit_callback(pool->pmd,
Coly Li ec13f5
 					     metadata_pre_commit_callback, pool);
Coly Li ec13f5
-- 
Coly Li ec13f5
2.35.3
Coly Li ec13f5