Commit 675807de authored by Chen Zhongjin's avatar Chen Zhongjin Committed by Mauro Carvalho Chehab

media: vidtv: Fix use-after-free in vidtv_bridge_dvb_init()

KASAN reports a use-after-free:
BUG: KASAN: use-after-free in dvb_dmxdev_release+0x4d5/0x5d0 [dvb_core]
Call Trace:
 ...
 dvb_dmxdev_release+0x4d5/0x5d0 [dvb_core]
 vidtv_bridge_probe+0x7bf/0xa40 [dvb_vidtv_bridge]
 platform_probe+0xb6/0x170
 ...
Allocated by task 1238:
 ...
 dvb_register_device+0x1a7/0xa70 [dvb_core]
 dvb_dmxdev_init+0x2af/0x4a0 [dvb_core]
 vidtv_bridge_probe+0x766/0xa40 [dvb_vidtv_bridge]
 ...
Freed by task 1238:
 dvb_register_device+0x6d2/0xa70 [dvb_core]
 dvb_dmxdev_init+0x2af/0x4a0 [dvb_core]
 vidtv_bridge_probe+0x766/0xa40 [dvb_vidtv_bridge]
 ...

It is because the error handling in vidtv_bridge_dvb_init() is wrong.

First, vidtv_bridge_dmx(dev)_init() will clean themselves when fail, but
goto fail_dmx(_dev): calls release functions again, which causes
use-after-free.

Also, in fail_fe, fail_tuner_probe and fail_demod_probe, j = i will cause
out-of-bound when i finished its loop (i == NUM_FE). And the loop
releasing is wrong, although now NUM_FE is 1 so it won't cause problem.

Fix this by correctly releasing everything.

Fixes: f90cf607 ("media: vidtv: add a bridge driver")
Signed-off-by: default avatarChen Zhongjin <chenzhongjin@huawei.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@kernel.org>
parent 645e7133
......@@ -459,26 +459,20 @@ static int vidtv_bridge_dvb_init(struct vidtv_dvb *dvb)
for (j = j - 1; j >= 0; --j)
dvb->demux.dmx.remove_frontend(&dvb->demux.dmx,
&dvb->dmx_fe[j]);
fail_dmx_dev:
dvb_dmxdev_release(&dvb->dmx_dev);
fail_dmx:
fail_dmx_dev:
dvb_dmx_release(&dvb->demux);
fail_dmx:
fail_demod_probe:
for (i = i - 1; i >= 0; --i) {
dvb_unregister_frontend(dvb->fe[i]);
fail_fe:
for (j = i; j >= 0; --j)
dvb_unregister_frontend(dvb->fe[j]);
dvb_module_release(dvb->i2c_client_tuner[i]);
fail_tuner_probe:
for (j = i; j >= 0; --j)
if (dvb->i2c_client_tuner[j])
dvb_module_release(dvb->i2c_client_tuner[j]);
fail_demod_probe:
for (j = i; j >= 0; --j)
if (dvb->i2c_client_demod[j])
dvb_module_release(dvb->i2c_client_demod[j]);
dvb_module_release(dvb->i2c_client_demod[i]);
}
fail_adapter:
dvb_unregister_adapter(&dvb->adapter);
fail_i2c:
i2c_del_adapter(&dvb->i2c_adapter);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment