media: dmxdev: fix UAF when dvb_register_device() fails
I got a use-after-free report:
dvbdev: dvb_register_device: failed to create device dvb1.dvr0 (-12)
...
==================================================================
BUG: KASAN: use-after-free in dvb_dmxdev_release+0xce/0x2f0
...
Call Trace:
dump_stack_lvl+0x6c/0x8b
print_address_description.constprop.0+0x48/0x70
kasan_report.cold+0x82/0xdb
__asan_load4+0x6b/0x90
dvb_dmxdev_release+0xce/0x2f0
...
Allocated by task 7666:
kasan_save_stack+0x23/0x50
__kasan_kmalloc+0x83/0xa0
kmem_cache_alloc_trace+0x22e/0x470
dvb_register_device+0x12f/0x980
dvb_dmxdev_init+0x1f3/0x230
...
Freed by task 7666:
kasan_save_stack+0x23/0x50
kasan_set_track+0x20/0x30
kasan_set_free_info+0x24/0x40
__kasan_slab_free+0xf2/0x130
kfree+0xd1/0x5c0
dvb_register_device.cold+0x1ac/0x1fa
dvb_dmxdev_init+0x1f3/0x230
...
When dvb_register_device() in dvb_dmxdev_init() fails, dvb_dmxdev_init()
does not return a failure, and the memory pointed to by dvbdev or
dvr_dvbdev is invalid at this point. If they are used subsequently, it
will result in UFA or null-ptr-deref.
If dvb_register_device() in dvb_dmxdev_init() fails, fix the bug by making
dvb_dmxdev_init() return an error as well.
Link: https://lore.kernel.org/linux-media/20211015085741.1203283-1-wanghai38@huawei.com
Fixes: 1da177e4c3
("Linux-2.6.12-rc2")
Reported-by: Hulk Robot <hulkci@huawei.com>
Signed-off-by: Wang Hai <wanghai38@huawei.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
This commit is contained in:
Родитель
ea8587d9de
Коммит
ab599eb118
|
@ -1413,7 +1413,7 @@ static const struct dvb_device dvbdev_dvr = {
|
|||
};
|
||||
int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
|
||||
{
|
||||
int i;
|
||||
int i, ret;
|
||||
|
||||
if (dmxdev->demux->open(dmxdev->demux) < 0)
|
||||
return -EUSERS;
|
||||
|
@ -1432,14 +1432,26 @@ int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
|
|||
DMXDEV_STATE_FREE);
|
||||
}
|
||||
|
||||
dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev,
|
||||
ret = dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev,
|
||||
DVB_DEVICE_DEMUX, dmxdev->filternum);
|
||||
dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr,
|
||||
if (ret < 0)
|
||||
goto err_register_dvbdev;
|
||||
|
||||
ret = dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr,
|
||||
dmxdev, DVB_DEVICE_DVR, dmxdev->filternum);
|
||||
if (ret < 0)
|
||||
goto err_register_dvr_dvbdev;
|
||||
|
||||
dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192);
|
||||
|
||||
return 0;
|
||||
|
||||
err_register_dvr_dvbdev:
|
||||
dvb_unregister_device(dmxdev->dvbdev);
|
||||
err_register_dvbdev:
|
||||
vfree(dmxdev->filter);
|
||||
dmxdev->filter = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(dvb_dmxdev_init);
|
||||
|
|
Загрузка…
Ссылка в новой задаче