From: Luo Meng luomeng12@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5GRX6 CVE: NA
--------------------------------
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@huawei.com Signed-off-by: Luo Meng luomeng12@huawei.com Reviewed-by: Hou Tao houtao1@huawei.com Signed-off-by: Yongqiang Liu liuyongqiang13@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 a6a5cee6b943..c3dc171114dc 100644 --- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c @@ -1997,9 +1997,15 @@ int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd, int r;
down_write(&pmd->root_lock); + if (pmd->fail_io) { + r = -EINVAL; + goto out; + } + r = dm_sm_register_threshold_callback(pmd->metadata_sm, threshold, fn, context); - up_write(&pmd->root_lock);
+out: + up_write(&pmd->root_lock); return r; }
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 435a2ee4a392..2b6dd7a275eb 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -3383,8 +3383,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; + }
pt->callbacks.congested_fn = pool_is_congested; dm_table_add_target_callbacks(ti->table, &pt->callbacks);