[PATCH 2/6] bus: fsl-mc: fix a use-after-free issue

From: laurentiu . tudor
Date: Tue Feb 08 2022 - 09:59:58 EST


From: Laurentiu Tudor <laurentiu.tudor@xxxxxxx>

Lets keep a reference to the MC IO object before deleting the
containing device structure, so that we can safely free it.
This fixes the below use-after-free kasan warning:

==================================================================
BUG: KASAN: use-after-free in fsl_mc_bus_remove+0xb8/0x198
Read of size 8 at addr ffff00203a304300 by task reboot/1362

CPU: 8 PID: 1362 Comm: reboot Not tainted 5.14.0-rc1-00218-g23d67ae4b6d7-dirty #111
Hardware name: NXP NXP LX2160ARDB Platform, BIOS EDK II Apr 16 2021
Call trace:
dump_backtrace+0x0/0x2a4
show_stack+0x1c/0x30
dump_stack_lvl+0x68/0x84
print_address_description.constprop.0+0x74/0x2b8
kasan_report+0x1e0/0x24c
__asan_load8+0xa4/0xd0
fsl_mc_bus_remove+0xb8/0x198
fsl_mc_bus_shutdown+0x14/0x24
platform_shutdown+0x44/0x54
device_shutdown+0x1f0/0x430
__do_sys_reboot+0x290/0x31c
__arm64_sys_reboot+0x58/0x70
invoke_syscall+0x60/0x190
el0_svc_common+0x84/0x130
do_el0_svc+0x88/0xa4
el0_svc+0x24/0x34
el0t_64_sync_handler+0xa8/0x130
el0t_64_sync+0x198/0x19c

Allocated by task 7:
kasan_save_stack+0x2c/0x60
__kasan_kmalloc+0x90/0xb4
fsl_mc_device_add+0x104/0x8f0
fsl_mc_bus_probe+0x400/0x650
platform_probe+0x90/0x110
really_probe.part.0+0xec/0x480
__driver_probe_device+0xd4/0x180
driver_probe_device+0xf8/0x1e0
__device_attach_driver+0x120/0x190
bus_for_each_drv+0xec/0x15c
__device_attach+0x168/0x250
device_initial_probe+0x18/0x24
bus_probe_device+0xec/0x100
deferred_probe_work_func+0xe8/0x130
process_one_work+0x3b8/0x650
worker_thread+0x3cc/0x72c
kthread+0x1f8/0x210
ret_from_fork+0x10/0x18

Freed by task 1362:
kasan_save_stack+0x2c/0x60
kasan_set_track+0x2c/0x40
kasan_set_free_info+0x2c/0x50
__kasan_slab_free+0xdc/0x140
kfree+0xd4/0x360
fsl_mc_device_release+0x30/0x40
device_release+0x54/0x110
kobject_put+0xac/0x180
put_device+0x18/0x30
fsl_mc_device_remove+0x48/0x5c
fsl_mc_bus_remove+0x84/0x198
fsl_mc_bus_shutdown+0x14/0x24
platform_shutdown+0x44/0x54
device_shutdown+0x1f0/0x430
__do_sys_reboot+0x290/0x31c
__arm64_sys_reboot+0x58/0x70
invoke_syscall+0x60/0x190
el0_svc_common+0x84/0x130
do_el0_svc+0x88/0xa4
el0_svc+0x24/0x34
el0t_64_sync_handler+0xa8/0x130
el0t_64_sync+0x198/0x19c

The buggy address belongs to the object at ffff00203a304000
which belongs to the cache kmalloc-2k of size 2048
The buggy address is located 768 bytes inside of
2048-byte region [ffff00203a304000, ffff00203a304800)
The buggy address belongs to the page:
page:00000000c0d8f504 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x20ba300
head:00000000c0d8f504 order:3 compound_mapcount:0 compound_pincount:0
flags: 0xbfffc0000010200(slab|head|node=0|zone=2|lastcpupid=0xffff)
raw: 0bfffc0000010200 0000000000000000 dead000000000122 ffff002000002a00
raw: 0000000000000000 0000000000080008 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected

Memory state around the buggy address:
ffff00203a304200: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff00203a304280: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff00203a304300: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff00203a304380: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff00203a304400: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================

Signed-off-by: Laurentiu Tudor <laurentiu.tudor@xxxxxxx>
---
drivers/bus/fsl-mc/fsl-mc-bus.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index 8fd4a356a86e..8cbac1b4b60e 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -1236,14 +1236,16 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
static int fsl_mc_bus_remove(struct platform_device *pdev)
{
struct fsl_mc *mc = platform_get_drvdata(pdev);
+ struct fsl_mc_io *mc_io;

if (!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev))
return -EINVAL;

+ mc_io = mc->root_mc_bus_dev->mc_io;
+
fsl_mc_device_remove(mc->root_mc_bus_dev);

- fsl_destroy_mc_io(mc->root_mc_bus_dev->mc_io);
- mc->root_mc_bus_dev->mc_io = NULL;
+ fsl_destroy_mc_io(mc_io);

bus_unregister_notifier(&fsl_mc_bus_type, &fsl_mc_nb);

--
2.17.1