[dm-devel] dm thin: Fix crash in dm_sm_register_threshold_callback()

Luo Meng luomeng at huaweicloud.com
Thu Jul 14 11:28:25 UTC 2022


From: Luo Meng <luomeng12 at huawei.com>

Fault inject on pool metadata device report:
  BUG: KASAN: use-after-free in dm_pool_register_metadata_threshold+0x40/0x80
  Read of size 8 at addr ffff8881b9d50068 by task dmsetup/950

  CPU: 7 PID: 950 Comm: dmsetup Tainted: G        W         5.19.0-rc6 #1
  Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-1.fc33 04/01/2014
  Call Trace:
   <TASK>
   dump_stack_lvl+0x34/0x44
   print_address_description.constprop.0.cold+0xeb/0x3f4
   kasan_report.cold+0xe6/0x147
   dm_pool_register_metadata_threshold+0x40/0x80
   pool_ctr+0xa0a/0x1150
   dm_table_add_target+0x2c8/0x640
   table_load+0x1fd/0x430
   ctl_ioctl+0x2c4/0x5a0
   dm_ctl_ioctl+0xa/0x10
   __x64_sys_ioctl+0xb3/0xd0
   do_syscall_64+0x35/0x80
   entry_SYSCALL_64_after_hwframe+0x46/0xb0

This can be easy reproduce:
  echo offline > /sys/block/sda/device/state
  dd if=/dev/zero of=/dev/mapper/thin bs=4k count=10
  dmsetup load pool --table "0 20971520 thin-pool /dev/sda /dev/sdb 128 0 0"

If metadata commit failed, the transaction will be aborted and the metadata
space manager will be destroyed. If load table on this pool, when register the
metadata threshold callback, the UAF will happen on metadata space manager.

So return error when load table if the pool is on FAIL status.

Fixes: ac8c3f3df65e4 ("dm thin: generate event when metadata threshold passed")
Reported-by: Hulk Robot <hulkci at huawei.com>
Signed-off-by: Luo Meng <luomeng12 at huawei.com>
---
 drivers/md/dm-thin-metadata.c | 8 +++++++-
 drivers/md/dm-thin.c          | 4 +++-
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index 2db7030aba00..138f67abffd0 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -2048,9 +2048,15 @@ int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
 	int r;
 
 	pmd_write_lock_in_core(pmd);
+	if (pmd->fail_io) {
+		r = -EINVAL;
+		goto out;
+	}
+
 	r = dm_sm_register_threshold_callback(pmd->metadata_sm, threshold, fn, context);
-	pmd_write_unlock(pmd);
 
+out:
+	pmd_write_unlock(pmd);
 	return r;
 }
 
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index 84c083f76673..e76c96c760a9 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -3375,8 +3375,10 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
 						calc_metadata_threshold(pt),
 						metadata_low_callback,
 						pool);
-	if (r)
+	if (r) {
+		ti->error = "Error registering metadata threshold";
 		goto out_flags_changed;
+	}
 
 	dm_pool_register_pre_commit_callback(pool->pmd,
 					     metadata_pre_commit_callback, pool);
-- 
2.31.1



More information about the dm-devel mailing list