Skip to content

Commit 9df9652

Browse files
seanyounggregkh
authored andcommitted
media: dvb-frontends: use ida for pll number
[ Upstream commit c268e7a ] KASAN: global-out-of-bounds Read in dvb_pll_attach Syzbot reported global-out-of-bounds Read in dvb_pll_attach, while accessing id[dvb_pll_devcount], because dvb_pll_devcount was 65, that is more than size of 'id' which is DVB_PLL_MAX(64). Rather than increasing dvb_pll_devcount every time, use ida so that numbers are allocated correctly. This does mean that no more than 64 devices can be attached at the same time, but this is more than sufficient. usb 1-1: dvb_usb_v2: will pass the complete MPEG2 transport stream to the software demuxer dvbdev: DVB: registering new adapter (774 Friio White ISDB-T USB2.0) usb 1-1: media controller created dvbdev: dvb_create_media_entity: media entity 'dvb-demux' registered. tc90522 0-0018: Toshiba TC90522 attached. usb 1-1: DVB: registering adapter 0 frontend 0 (Toshiba TC90522 ISDB-T module)... dvbdev: dvb_create_media_entity: media entity 'Toshiba TC90522 ISDB-T module' registered. ================================================================== BUG: KASAN: global-out-of-bounds in dvb_pll_attach+0x6c5/0x830 drivers/media/dvb-frontends/dvb-pll.c:798 Read of size 4 at addr ffffffff89c9e5e0 by task kworker/0:1/12 CPU: 0 PID: 12 Comm: kworker/0:1 Not tainted 5.2.0-rc6+ #13 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Workqueue: usb_hub_wq hub_event Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0xca/0x13e lib/dump_stack.c:113 print_address_description+0x67/0x231 mm/kasan/report.c:188 __kasan_report.cold+0x1a/0x32 mm/kasan/report.c:317 kasan_report+0xe/0x20 mm/kasan/common.c:614 dvb_pll_attach+0x6c5/0x830 drivers/media/dvb-frontends/dvb-pll.c:798 dvb_pll_probe+0xfe/0x174 drivers/media/dvb-frontends/dvb-pll.c:877 i2c_device_probe+0x790/0xaa0 drivers/i2c/i2c-core-base.c:389 really_probe+0x281/0x660 drivers/base/dd.c:509 driver_probe_device+0x104/0x210 drivers/base/dd.c:670 __device_attach_driver+0x1c2/0x220 drivers/base/dd.c:777 bus_for_each_drv+0x15c/0x1e0 drivers/base/bus.c:454 __device_attach+0x217/0x360 drivers/base/dd.c:843 bus_probe_device+0x1e4/0x290 drivers/base/bus.c:514 device_add+0xae6/0x16f0 drivers/base/core.c:2111 i2c_new_client_device+0x5b3/0xc40 drivers/i2c/i2c-core-base.c:778 i2c_new_device+0x19/0x50 drivers/i2c/i2c-core-base.c:821 dvb_module_probe+0xf9/0x220 drivers/media/dvb-core/dvbdev.c:985 friio_tuner_attach+0x125/0x1d0 drivers/media/usb/dvb-usb-v2/gl861.c:536 dvb_usbv2_adapter_frontend_init drivers/media/usb/dvb-usb-v2/dvb_usb_core.c:675 [inline] dvb_usbv2_adapter_init drivers/media/usb/dvb-usb-v2/dvb_usb_core.c:804 [inline] dvb_usbv2_init drivers/media/usb/dvb-usb-v2/dvb_usb_core.c:865 [inline] dvb_usbv2_probe.cold+0x24dc/0x255d drivers/media/usb/dvb-usb-v2/dvb_usb_core.c:980 usb_probe_interface+0x305/0x7a0 drivers/usb/core/driver.c:361 really_probe+0x281/0x660 drivers/base/dd.c:509 driver_probe_device+0x104/0x210 drivers/base/dd.c:670 __device_attach_driver+0x1c2/0x220 drivers/base/dd.c:777 bus_for_each_drv+0x15c/0x1e0 drivers/base/bus.c:454 __device_attach+0x217/0x360 drivers/base/dd.c:843 bus_probe_device+0x1e4/0x290 drivers/base/bus.c:514 device_add+0xae6/0x16f0 drivers/base/core.c:2111 usb_set_configuration+0xdf6/0x1670 drivers/usb/core/message.c:2023 generic_probe+0x9d/0xd5 drivers/usb/core/generic.c:210 usb_probe_device+0x99/0x100 drivers/usb/core/driver.c:266 really_probe+0x281/0x660 drivers/base/dd.c:509 driver_probe_device+0x104/0x210 drivers/base/dd.c:670 __device_attach_driver+0x1c2/0x220 drivers/base/dd.c:777 bus_for_each_drv+0x15c/0x1e0 drivers/base/bus.c:454 __device_attach+0x217/0x360 drivers/base/dd.c:843 bus_probe_device+0x1e4/0x290 drivers/base/bus.c:514 device_add+0xae6/0x16f0 drivers/base/core.c:2111 usb_new_device.cold+0x8c1/0x1016 drivers/usb/core/hub.c:2534 hub_port_connect drivers/usb/core/hub.c:5089 [inline] hub_port_connect_change drivers/usb/core/hub.c:5204 [inline] port_event drivers/usb/core/hub.c:5350 [inline] hub_event+0x1ada/0x3590 drivers/usb/core/hub.c:5432 process_one_work+0x905/0x1570 kernel/workqueue.c:2269 process_scheduled_works kernel/workqueue.c:2331 [inline] worker_thread+0x7ab/0xe20 kernel/workqueue.c:2417 kthread+0x30b/0x410 kernel/kthread.c:255 ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:352 The buggy address belongs to the variable: id+0x100/0x120 Memory state around the buggy address: ffffffff89c9e480: fa fa fa fa 00 00 fa fa fa fa fa fa 00 00 00 00 ffffffff89c9e500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > ffffffff89c9e580: 00 00 00 00 00 00 00 00 00 00 00 00 fa fa fa fa ^ ffffffff89c9e600: 04 fa fa fa fa fa fa fa 04 fa fa fa fa fa fa fa ffffffff89c9e680: 04 fa fa fa fa fa fa fa 04 fa fa fa fa fa fa fa ================================================================== Reported-by: [email protected] Signed-off-by: Sean Young <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 006a606 commit 9df9652

File tree

1 file changed

+24
-16
lines changed

1 file changed

+24
-16
lines changed

drivers/media/dvb-frontends/dvb-pll.c

+24-16
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include <linux/slab.h>
2020
#include <linux/module.h>
21+
#include <linux/idr.h>
2122
#include <linux/dvb/frontend.h>
2223
#include <asm/types.h>
2324

@@ -43,8 +44,7 @@ struct dvb_pll_priv {
4344
};
4445

4546
#define DVB_PLL_MAX 64
46-
47-
static unsigned int dvb_pll_devcount;
47+
static DEFINE_IDA(pll_ida);
4848

4949
static int debug;
5050
module_param(debug, int, 0644);
@@ -796,6 +796,7 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
796796
struct dvb_pll_priv *priv = NULL;
797797
int ret;
798798
const struct dvb_pll_desc *desc;
799+
int nr;
799800

800801
b1 = kmalloc(1, GFP_KERNEL);
801802
if (!b1)
@@ -804,9 +805,14 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
804805
b1[0] = 0;
805806
msg.buf = b1;
806807

807-
if ((id[dvb_pll_devcount] > DVB_PLL_UNDEFINED) &&
808-
(id[dvb_pll_devcount] < ARRAY_SIZE(pll_list)))
809-
pll_desc_id = id[dvb_pll_devcount];
808+
nr = ida_simple_get(&pll_ida, 0, DVB_PLL_MAX, GFP_KERNEL);
809+
if (nr < 0) {
810+
kfree(b1);
811+
return NULL;
812+
}
813+
814+
if (id[nr] > DVB_PLL_UNDEFINED && id[nr] < ARRAY_SIZE(pll_list))
815+
pll_desc_id = id[nr];
810816

811817
BUG_ON(pll_desc_id < 1 || pll_desc_id >= ARRAY_SIZE(pll_list));
812818

@@ -817,24 +823,20 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
817823
fe->ops.i2c_gate_ctrl(fe, 1);
818824

819825
ret = i2c_transfer (i2c, &msg, 1);
820-
if (ret != 1) {
821-
kfree(b1);
822-
return NULL;
823-
}
826+
if (ret != 1)
827+
goto out;
824828
if (fe->ops.i2c_gate_ctrl)
825829
fe->ops.i2c_gate_ctrl(fe, 0);
826830
}
827831

828832
priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL);
829-
if (!priv) {
830-
kfree(b1);
831-
return NULL;
832-
}
833+
if (!priv)
834+
goto out;
833835

834836
priv->pll_i2c_address = pll_addr;
835837
priv->i2c = i2c;
836838
priv->pll_desc = desc;
837-
priv->nr = dvb_pll_devcount++;
839+
priv->nr = nr;
838840

839841
memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops,
840842
sizeof(struct dvb_tuner_ops));
@@ -867,6 +869,11 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
867869
kfree(b1);
868870

869871
return fe;
872+
out:
873+
kfree(b1);
874+
ida_simple_remove(&pll_ida, nr);
875+
876+
return NULL;
870877
}
871878
EXPORT_SYMBOL(dvb_pll_attach);
872879

@@ -903,9 +910,10 @@ dvb_pll_probe(struct i2c_client *client, const struct i2c_device_id *id)
903910

904911
static int dvb_pll_remove(struct i2c_client *client)
905912
{
906-
struct dvb_frontend *fe;
913+
struct dvb_frontend *fe = i2c_get_clientdata(client);
914+
struct dvb_pll_priv *priv = fe->tuner_priv;
907915

908-
fe = i2c_get_clientdata(client);
916+
ida_simple_remove(&pll_ida, priv->nr);
909917
dvb_pll_release(fe);
910918
return 0;
911919
}

0 commit comments

Comments
 (0)