Skip to content

Commit c268e7a

Browse files
seanyoungmchehab
authored andcommitted
media: dvb-frontends: use ida for pll number
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+ Freescale#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]>
1 parent d4e0f82 commit c268e7a

1 file changed

Lines changed: 24 additions & 16 deletions

File tree

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

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include <linux/slab.h>
1111
#include <linux/module.h>
12+
#include <linux/idr.h>
1213
#include <linux/dvb/frontend.h>
1314
#include <asm/types.h>
1415

@@ -34,8 +35,7 @@ struct dvb_pll_priv {
3435
};
3536

3637
#define DVB_PLL_MAX 64
37-
38-
static unsigned int dvb_pll_devcount;
38+
static DEFINE_IDA(pll_ida);
3939

4040
static int debug;
4141
module_param(debug, int, 0644);
@@ -787,6 +787,7 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
787787
struct dvb_pll_priv *priv = NULL;
788788
int ret;
789789
const struct dvb_pll_desc *desc;
790+
int nr;
790791

791792
b1 = kmalloc(1, GFP_KERNEL);
792793
if (!b1)
@@ -795,9 +796,14 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
795796
b1[0] = 0;
796797
msg.buf = b1;
797798

798-
if ((id[dvb_pll_devcount] > DVB_PLL_UNDEFINED) &&
799-
(id[dvb_pll_devcount] < ARRAY_SIZE(pll_list)))
800-
pll_desc_id = id[dvb_pll_devcount];
799+
nr = ida_simple_get(&pll_ida, 0, DVB_PLL_MAX, GFP_KERNEL);
800+
if (nr < 0) {
801+
kfree(b1);
802+
return NULL;
803+
}
804+
805+
if (id[nr] > DVB_PLL_UNDEFINED && id[nr] < ARRAY_SIZE(pll_list))
806+
pll_desc_id = id[nr];
801807

802808
BUG_ON(pll_desc_id < 1 || pll_desc_id >= ARRAY_SIZE(pll_list));
803809

@@ -808,24 +814,20 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
808814
fe->ops.i2c_gate_ctrl(fe, 1);
809815

810816
ret = i2c_transfer (i2c, &msg, 1);
811-
if (ret != 1) {
812-
kfree(b1);
813-
return NULL;
814-
}
817+
if (ret != 1)
818+
goto out;
815819
if (fe->ops.i2c_gate_ctrl)
816820
fe->ops.i2c_gate_ctrl(fe, 0);
817821
}
818822

819823
priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL);
820-
if (!priv) {
821-
kfree(b1);
822-
return NULL;
823-
}
824+
if (!priv)
825+
goto out;
824826

825827
priv->pll_i2c_address = pll_addr;
826828
priv->i2c = i2c;
827829
priv->pll_desc = desc;
828-
priv->nr = dvb_pll_devcount++;
830+
priv->nr = nr;
829831

830832
memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops,
831833
sizeof(struct dvb_tuner_ops));
@@ -858,6 +860,11 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
858860
kfree(b1);
859861

860862
return fe;
863+
out:
864+
kfree(b1);
865+
ida_simple_remove(&pll_ida, nr);
866+
867+
return NULL;
861868
}
862869
EXPORT_SYMBOL(dvb_pll_attach);
863870

@@ -894,9 +901,10 @@ dvb_pll_probe(struct i2c_client *client, const struct i2c_device_id *id)
894901

895902
static int dvb_pll_remove(struct i2c_client *client)
896903
{
897-
struct dvb_frontend *fe;
904+
struct dvb_frontend *fe = i2c_get_clientdata(client);
905+
struct dvb_pll_priv *priv = fe->tuner_priv;
898906

899-
fe = i2c_get_clientdata(client);
907+
ida_simple_remove(&pll_ida, priv->nr);
900908
dvb_pll_release(fe);
901909
return 0;
902910
}

0 commit comments

Comments
 (0)