| From 3a2f2b9d25d706dff7281744e17e52459f0d665d Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Stefan=20Br=C3=BCns?= <stefan.bruens@rwth-aachen.de> |
| Date: Sat, 19 Jan 2019 20:30:04 -0500 |
| Subject: media: dvbsky: Avoid leaking dvb frontend |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| [ Upstream commit fdfa59cd63b184e1e96d51ff170fcac739bc6f6f ] |
| |
| Commit 14f4eaeddabc ("media: dvbsky: fix driver unregister logic") fixed |
| a use-after-free by removing the reference to the frontend after deleting |
| the backing i2c device. |
| |
| This has the unfortunate side effect the frontend device is never freed |
| in the dvb core leaving a dangling device, leading to errors when the |
| dvb core tries to register the frontend after e.g. a replug as reported |
| here: https://www.spinics.net/lists/linux-media/msg138181.html |
| |
| media: dvbsky: issues with DVBSky T680CI |
| |
| === |
| [ 561.119145] sp2 8-0040: CIMaX SP2 successfully attached |
| [ 561.119161] usb 2-3: DVB: registering adapter 0 frontend 0 (Silicon Labs |
| Si2168)... |
| [ 561.119174] sysfs: cannot create duplicate filename '/class/dvb/ |
| dvb0.frontend0' |
| === |
| |
| The use after free happened as dvb_usbv2_disconnect calls in this order: |
| - dvb_usb_device::props->exit(...) |
| - dvb_usbv2_adapter_frontend_exit(...) |
| + if (fe) dvb_unregister_frontend(fe) |
| + dvb_usb_device::props->frontend_detach(...) |
| |
| Moving the release of the i2c device from exit() to frontend_detach() |
| avoids the dangling pointer access and allows the core to unregister |
| the frontend. |
| |
| This was originally reported for a DVBSky T680CI, but it also affects |
| the MyGica T230C. As all supported devices structure the registration/ |
| unregistration identically, apply the change for all device types. |
| |
| Signed-off-by: Stefan BrΓΌns <stefan.bruens@rwth-aachen.de> |
| Signed-off-by: Sean Young <sean@mess.org> |
| Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/media/usb/dvb-usb-v2/dvbsky.c | 18 ++++++++++-------- |
| 1 file changed, 10 insertions(+), 8 deletions(-) |
| |
| diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c |
| index e28bd8836751e..ae0814dd202a6 100644 |
| --- a/drivers/media/usb/dvb-usb-v2/dvbsky.c |
| +++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c |
| @@ -615,16 +615,18 @@ static int dvbsky_init(struct dvb_usb_device *d) |
| return 0; |
| } |
| |
| -static void dvbsky_exit(struct dvb_usb_device *d) |
| +static int dvbsky_frontend_detach(struct dvb_usb_adapter *adap) |
| { |
| + struct dvb_usb_device *d = adap_to_d(adap); |
| struct dvbsky_state *state = d_to_priv(d); |
| - struct dvb_usb_adapter *adap = &d->adapter[0]; |
| + |
| + dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, adap->id); |
| |
| dvb_module_release(state->i2c_client_tuner); |
| dvb_module_release(state->i2c_client_demod); |
| dvb_module_release(state->i2c_client_ci); |
| |
| - adap->fe[0] = NULL; |
| + return 0; |
| } |
| |
| /* DVB USB Driver stuff */ |
| @@ -640,11 +642,11 @@ static struct dvb_usb_device_properties dvbsky_s960_props = { |
| |
| .i2c_algo = &dvbsky_i2c_algo, |
| .frontend_attach = dvbsky_s960_attach, |
| + .frontend_detach = dvbsky_frontend_detach, |
| .init = dvbsky_init, |
| .get_rc_config = dvbsky_get_rc_config, |
| .streaming_ctrl = dvbsky_streaming_ctrl, |
| .identify_state = dvbsky_identify_state, |
| - .exit = dvbsky_exit, |
| .read_mac_address = dvbsky_read_mac_addr, |
| |
| .num_adapters = 1, |
| @@ -667,11 +669,11 @@ static struct dvb_usb_device_properties dvbsky_s960c_props = { |
| |
| .i2c_algo = &dvbsky_i2c_algo, |
| .frontend_attach = dvbsky_s960c_attach, |
| + .frontend_detach = dvbsky_frontend_detach, |
| .init = dvbsky_init, |
| .get_rc_config = dvbsky_get_rc_config, |
| .streaming_ctrl = dvbsky_streaming_ctrl, |
| .identify_state = dvbsky_identify_state, |
| - .exit = dvbsky_exit, |
| .read_mac_address = dvbsky_read_mac_addr, |
| |
| .num_adapters = 1, |
| @@ -694,11 +696,11 @@ static struct dvb_usb_device_properties dvbsky_t680c_props = { |
| |
| .i2c_algo = &dvbsky_i2c_algo, |
| .frontend_attach = dvbsky_t680c_attach, |
| + .frontend_detach = dvbsky_frontend_detach, |
| .init = dvbsky_init, |
| .get_rc_config = dvbsky_get_rc_config, |
| .streaming_ctrl = dvbsky_streaming_ctrl, |
| .identify_state = dvbsky_identify_state, |
| - .exit = dvbsky_exit, |
| .read_mac_address = dvbsky_read_mac_addr, |
| |
| .num_adapters = 1, |
| @@ -721,11 +723,11 @@ static struct dvb_usb_device_properties dvbsky_t330_props = { |
| |
| .i2c_algo = &dvbsky_i2c_algo, |
| .frontend_attach = dvbsky_t330_attach, |
| + .frontend_detach = dvbsky_frontend_detach, |
| .init = dvbsky_init, |
| .get_rc_config = dvbsky_get_rc_config, |
| .streaming_ctrl = dvbsky_streaming_ctrl, |
| .identify_state = dvbsky_identify_state, |
| - .exit = dvbsky_exit, |
| .read_mac_address = dvbsky_read_mac_addr, |
| |
| .num_adapters = 1, |
| @@ -748,11 +750,11 @@ static struct dvb_usb_device_properties mygica_t230c_props = { |
| |
| .i2c_algo = &dvbsky_i2c_algo, |
| .frontend_attach = dvbsky_mygica_t230c_attach, |
| + .frontend_detach = dvbsky_frontend_detach, |
| .init = dvbsky_init, |
| .get_rc_config = dvbsky_get_rc_config, |
| .streaming_ctrl = dvbsky_streaming_ctrl, |
| .identify_state = dvbsky_identify_state, |
| - .exit = dvbsky_exit, |
| |
| .num_adapters = 1, |
| .adapter = { |
| -- |
| 2.20.1 |
| |