media: dw2102: Fix use after free
[ Upstream commit589a9f0eb7
] dvb_usb_device_init stores parts of properties at d->props and d->desc and uses it on dvb_usb_device_exit. Free of properties on module probe leads to use after free. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=204597 The patch makes properties static instead of allocated on heap to prevent memleak and use after free. Also fixes s421_properties.devices initialization to have 2 element instead of 6 copied from p7500_properties. [mchehab: fix function call alignments] Link: https://lore.kernel.org/linux-media/20190822104147.4420-1-vasilyev@ispras.ru Signed-off-by: Anton Vasilyev <vasilyev@ispras.ru> Fixes:299c7007e9
("media: dw2102: Fix memleak on sequence of probes") Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Родитель
f99f6ea71b
Коммит
4822591943
|
@ -2150,46 +2150,153 @@ static struct dvb_usb_device_properties s6x0_properties = {
|
|||
}
|
||||
};
|
||||
|
||||
static const struct dvb_usb_device_description d1100 = {
|
||||
"Prof 1100 USB ",
|
||||
{&dw2102_table[PROF_1100], NULL},
|
||||
{NULL},
|
||||
static struct dvb_usb_device_properties p1100_properties = {
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
.size_of_priv = sizeof(struct dw2102_state),
|
||||
.firmware = P1100_FIRMWARE,
|
||||
.no_reconnect = 1,
|
||||
|
||||
.i2c_algo = &s6x0_i2c_algo,
|
||||
.rc.core = {
|
||||
.rc_interval = 150,
|
||||
.rc_codes = RC_MAP_TBS_NEC,
|
||||
.module_name = "dw2102",
|
||||
.allowed_protos = RC_PROTO_BIT_NEC,
|
||||
.rc_query = prof_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x81,
|
||||
.num_adapters = 1,
|
||||
.download_firmware = dw2102_load_firmware,
|
||||
.read_mac_address = s6x0_read_mac_address,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.frontend_attach = stv0288_frontend_attach,
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 8,
|
||||
.endpoint = 0x82,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
} },
|
||||
}
|
||||
},
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{"Prof 1100 USB ",
|
||||
{&dw2102_table[PROF_1100], NULL},
|
||||
{NULL},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
static const struct dvb_usb_device_description d660 = {
|
||||
"TeVii S660 USB",
|
||||
{&dw2102_table[TEVII_S660], NULL},
|
||||
{NULL},
|
||||
static struct dvb_usb_device_properties s660_properties = {
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
.size_of_priv = sizeof(struct dw2102_state),
|
||||
.firmware = S660_FIRMWARE,
|
||||
.no_reconnect = 1,
|
||||
|
||||
.i2c_algo = &s6x0_i2c_algo,
|
||||
.rc.core = {
|
||||
.rc_interval = 150,
|
||||
.rc_codes = RC_MAP_TEVII_NEC,
|
||||
.module_name = "dw2102",
|
||||
.allowed_protos = RC_PROTO_BIT_NEC,
|
||||
.rc_query = dw2102_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x81,
|
||||
.num_adapters = 1,
|
||||
.download_firmware = dw2102_load_firmware,
|
||||
.read_mac_address = s6x0_read_mac_address,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.frontend_attach = ds3000_frontend_attach,
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 8,
|
||||
.endpoint = 0x82,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
} },
|
||||
}
|
||||
},
|
||||
.num_device_descs = 3,
|
||||
.devices = {
|
||||
{"TeVii S660 USB",
|
||||
{&dw2102_table[TEVII_S660], NULL},
|
||||
{NULL},
|
||||
},
|
||||
{"TeVii S480.1 USB",
|
||||
{&dw2102_table[TEVII_S480_1], NULL},
|
||||
{NULL},
|
||||
},
|
||||
{"TeVii S480.2 USB",
|
||||
{&dw2102_table[TEVII_S480_2], NULL},
|
||||
{NULL},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
static const struct dvb_usb_device_description d480_1 = {
|
||||
"TeVii S480.1 USB",
|
||||
{&dw2102_table[TEVII_S480_1], NULL},
|
||||
{NULL},
|
||||
};
|
||||
static struct dvb_usb_device_properties p7500_properties = {
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
.size_of_priv = sizeof(struct dw2102_state),
|
||||
.firmware = P7500_FIRMWARE,
|
||||
.no_reconnect = 1,
|
||||
|
||||
static const struct dvb_usb_device_description d480_2 = {
|
||||
"TeVii S480.2 USB",
|
||||
{&dw2102_table[TEVII_S480_2], NULL},
|
||||
{NULL},
|
||||
};
|
||||
.i2c_algo = &s6x0_i2c_algo,
|
||||
.rc.core = {
|
||||
.rc_interval = 150,
|
||||
.rc_codes = RC_MAP_TBS_NEC,
|
||||
.module_name = "dw2102",
|
||||
.allowed_protos = RC_PROTO_BIT_NEC,
|
||||
.rc_query = prof_rc_query,
|
||||
},
|
||||
|
||||
static const struct dvb_usb_device_description d7500 = {
|
||||
"Prof 7500 USB DVB-S2",
|
||||
{&dw2102_table[PROF_7500], NULL},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static const struct dvb_usb_device_description d421 = {
|
||||
"TeVii S421 PCI",
|
||||
{&dw2102_table[TEVII_S421], NULL},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static const struct dvb_usb_device_description d632 = {
|
||||
"TeVii S632 USB",
|
||||
{&dw2102_table[TEVII_S632], NULL},
|
||||
{NULL},
|
||||
.generic_bulk_ctrl_endpoint = 0x81,
|
||||
.num_adapters = 1,
|
||||
.download_firmware = dw2102_load_firmware,
|
||||
.read_mac_address = s6x0_read_mac_address,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.frontend_attach = prof_7500_frontend_attach,
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 8,
|
||||
.endpoint = 0x82,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
} },
|
||||
}
|
||||
},
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{"Prof 7500 USB DVB-S2",
|
||||
{&dw2102_table[PROF_7500], NULL},
|
||||
{NULL},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
static struct dvb_usb_device_properties su3000_properties = {
|
||||
|
@ -2273,6 +2380,59 @@ static struct dvb_usb_device_properties su3000_properties = {
|
|||
}
|
||||
};
|
||||
|
||||
static struct dvb_usb_device_properties s421_properties = {
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
.size_of_priv = sizeof(struct dw2102_state),
|
||||
.power_ctrl = su3000_power_ctrl,
|
||||
.num_adapters = 1,
|
||||
.identify_state = su3000_identify_state,
|
||||
.i2c_algo = &su3000_i2c_algo,
|
||||
|
||||
.rc.core = {
|
||||
.rc_interval = 150,
|
||||
.rc_codes = RC_MAP_SU3000,
|
||||
.module_name = "dw2102",
|
||||
.allowed_protos = RC_PROTO_BIT_RC5,
|
||||
.rc_query = su3000_rc_query,
|
||||
},
|
||||
|
||||
.read_mac_address = su3000_read_mac_address,
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.streaming_ctrl = su3000_streaming_ctrl,
|
||||
.frontend_attach = m88rs2000_frontend_attach,
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 8,
|
||||
.endpoint = 0x82,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
}
|
||||
} },
|
||||
}
|
||||
},
|
||||
.num_device_descs = 2,
|
||||
.devices = {
|
||||
{ "TeVii S421 PCI",
|
||||
{ &dw2102_table[TEVII_S421], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
{ "TeVii S632 USB",
|
||||
{ &dw2102_table[TEVII_S632], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
static struct dvb_usb_device_properties t220_properties = {
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
|
@ -2390,101 +2550,33 @@ static struct dvb_usb_device_properties tt_s2_4600_properties = {
|
|||
static int dw2102_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
int retval = -ENOMEM;
|
||||
struct dvb_usb_device_properties *p1100;
|
||||
struct dvb_usb_device_properties *s660;
|
||||
struct dvb_usb_device_properties *p7500;
|
||||
struct dvb_usb_device_properties *s421;
|
||||
|
||||
p1100 = kmemdup(&s6x0_properties,
|
||||
sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
|
||||
if (!p1100)
|
||||
goto err0;
|
||||
|
||||
/* copy default structure */
|
||||
/* fill only different fields */
|
||||
p1100->firmware = P1100_FIRMWARE;
|
||||
p1100->devices[0] = d1100;
|
||||
p1100->rc.core.rc_query = prof_rc_query;
|
||||
p1100->rc.core.rc_codes = RC_MAP_TBS_NEC;
|
||||
p1100->adapter->fe[0].frontend_attach = stv0288_frontend_attach;
|
||||
|
||||
s660 = kmemdup(&s6x0_properties,
|
||||
sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
|
||||
if (!s660)
|
||||
goto err1;
|
||||
|
||||
s660->firmware = S660_FIRMWARE;
|
||||
s660->num_device_descs = 3;
|
||||
s660->devices[0] = d660;
|
||||
s660->devices[1] = d480_1;
|
||||
s660->devices[2] = d480_2;
|
||||
s660->adapter->fe[0].frontend_attach = ds3000_frontend_attach;
|
||||
|
||||
p7500 = kmemdup(&s6x0_properties,
|
||||
sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
|
||||
if (!p7500)
|
||||
goto err2;
|
||||
|
||||
p7500->firmware = P7500_FIRMWARE;
|
||||
p7500->devices[0] = d7500;
|
||||
p7500->rc.core.rc_query = prof_rc_query;
|
||||
p7500->rc.core.rc_codes = RC_MAP_TBS_NEC;
|
||||
p7500->adapter->fe[0].frontend_attach = prof_7500_frontend_attach;
|
||||
|
||||
|
||||
s421 = kmemdup(&su3000_properties,
|
||||
sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
|
||||
if (!s421)
|
||||
goto err3;
|
||||
|
||||
s421->num_device_descs = 2;
|
||||
s421->devices[0] = d421;
|
||||
s421->devices[1] = d632;
|
||||
s421->adapter->fe[0].frontend_attach = m88rs2000_frontend_attach;
|
||||
|
||||
if (0 == dvb_usb_device_init(intf, &dw2102_properties,
|
||||
THIS_MODULE, NULL, adapter_nr) ||
|
||||
0 == dvb_usb_device_init(intf, &dw2104_properties,
|
||||
THIS_MODULE, NULL, adapter_nr) ||
|
||||
0 == dvb_usb_device_init(intf, &dw3101_properties,
|
||||
THIS_MODULE, NULL, adapter_nr) ||
|
||||
0 == dvb_usb_device_init(intf, &s6x0_properties,
|
||||
THIS_MODULE, NULL, adapter_nr) ||
|
||||
0 == dvb_usb_device_init(intf, p1100,
|
||||
THIS_MODULE, NULL, adapter_nr) ||
|
||||
0 == dvb_usb_device_init(intf, s660,
|
||||
THIS_MODULE, NULL, adapter_nr) ||
|
||||
0 == dvb_usb_device_init(intf, p7500,
|
||||
THIS_MODULE, NULL, adapter_nr) ||
|
||||
0 == dvb_usb_device_init(intf, s421,
|
||||
THIS_MODULE, NULL, adapter_nr) ||
|
||||
0 == dvb_usb_device_init(intf, &su3000_properties,
|
||||
THIS_MODULE, NULL, adapter_nr) ||
|
||||
0 == dvb_usb_device_init(intf, &t220_properties,
|
||||
THIS_MODULE, NULL, adapter_nr) ||
|
||||
0 == dvb_usb_device_init(intf, &tt_s2_4600_properties,
|
||||
THIS_MODULE, NULL, adapter_nr)) {
|
||||
|
||||
/* clean up copied properties */
|
||||
kfree(s421);
|
||||
kfree(p7500);
|
||||
kfree(s660);
|
||||
kfree(p1100);
|
||||
if (!(dvb_usb_device_init(intf, &dw2102_properties,
|
||||
THIS_MODULE, NULL, adapter_nr) &&
|
||||
dvb_usb_device_init(intf, &dw2104_properties,
|
||||
THIS_MODULE, NULL, adapter_nr) &&
|
||||
dvb_usb_device_init(intf, &dw3101_properties,
|
||||
THIS_MODULE, NULL, adapter_nr) &&
|
||||
dvb_usb_device_init(intf, &s6x0_properties,
|
||||
THIS_MODULE, NULL, adapter_nr) &&
|
||||
dvb_usb_device_init(intf, &p1100_properties,
|
||||
THIS_MODULE, NULL, adapter_nr) &&
|
||||
dvb_usb_device_init(intf, &s660_properties,
|
||||
THIS_MODULE, NULL, adapter_nr) &&
|
||||
dvb_usb_device_init(intf, &p7500_properties,
|
||||
THIS_MODULE, NULL, adapter_nr) &&
|
||||
dvb_usb_device_init(intf, &s421_properties,
|
||||
THIS_MODULE, NULL, adapter_nr) &&
|
||||
dvb_usb_device_init(intf, &su3000_properties,
|
||||
THIS_MODULE, NULL, adapter_nr) &&
|
||||
dvb_usb_device_init(intf, &t220_properties,
|
||||
THIS_MODULE, NULL, adapter_nr) &&
|
||||
dvb_usb_device_init(intf, &tt_s2_4600_properties,
|
||||
THIS_MODULE, NULL, adapter_nr))) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
retval = -ENODEV;
|
||||
kfree(s421);
|
||||
err3:
|
||||
kfree(p7500);
|
||||
err2:
|
||||
kfree(s660);
|
||||
err1:
|
||||
kfree(p1100);
|
||||
err0:
|
||||
return retval;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static void dw2102_disconnect(struct usb_interface *intf)
|
||||
|
|
Загрузка…
Ссылка в новой задаче