media: dw2102: Fix use after free
[ Upstream commit 589a9f0eb799f77de2c09583bf5bad221fa5d685 ]
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:

committed by
Greg Kroah-Hartman

parent
958a8819d4
commit
a79327bb01
@@ -2148,46 +2148,153 @@ static struct dvb_usb_device_properties s6x0_properties = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct dvb_usb_device_description d1100 = {
|
static struct dvb_usb_device_properties p1100_properties = {
|
||||||
"Prof 1100 USB ",
|
.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},
|
{&dw2102_table[PROF_1100], NULL},
|
||||||
{NULL},
|
{NULL},
|
||||||
|
},
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct dvb_usb_device_description d660 = {
|
static struct dvb_usb_device_properties s660_properties = {
|
||||||
"TeVii S660 USB",
|
.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},
|
{&dw2102_table[TEVII_S660], NULL},
|
||||||
{NULL},
|
{NULL},
|
||||||
};
|
},
|
||||||
|
{"TeVii S480.1 USB",
|
||||||
static const struct dvb_usb_device_description d480_1 = {
|
|
||||||
"TeVii S480.1 USB",
|
|
||||||
{&dw2102_table[TEVII_S480_1], NULL},
|
{&dw2102_table[TEVII_S480_1], NULL},
|
||||||
{NULL},
|
{NULL},
|
||||||
};
|
},
|
||||||
|
{"TeVii S480.2 USB",
|
||||||
static const struct dvb_usb_device_description d480_2 = {
|
|
||||||
"TeVii S480.2 USB",
|
|
||||||
{&dw2102_table[TEVII_S480_2], NULL},
|
{&dw2102_table[TEVII_S480_2], NULL},
|
||||||
{NULL},
|
{NULL},
|
||||||
|
},
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct dvb_usb_device_description d7500 = {
|
static struct dvb_usb_device_properties p7500_properties = {
|
||||||
"Prof 7500 USB DVB-S2",
|
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||||
|
.usb_ctrl = DEVICE_SPECIFIC,
|
||||||
|
.size_of_priv = sizeof(struct dw2102_state),
|
||||||
|
.firmware = P7500_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 = 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},
|
{&dw2102_table[PROF_7500], NULL},
|
||||||
{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},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct dvb_usb_device_properties su3000_properties = {
|
static struct dvb_usb_device_properties su3000_properties = {
|
||||||
@@ -2267,6 +2374,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 = {
|
static struct dvb_usb_device_properties t220_properties = {
|
||||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||||
.usb_ctrl = DEVICE_SPECIFIC,
|
.usb_ctrl = DEVICE_SPECIFIC,
|
||||||
@@ -2384,101 +2544,33 @@ static struct dvb_usb_device_properties tt_s2_4600_properties = {
|
|||||||
static int dw2102_probe(struct usb_interface *intf,
|
static int dw2102_probe(struct usb_interface *intf,
|
||||||
const struct usb_device_id *id)
|
const struct usb_device_id *id)
|
||||||
{
|
{
|
||||||
int retval = -ENOMEM;
|
if (!(dvb_usb_device_init(intf, &dw2102_properties,
|
||||||
struct dvb_usb_device_properties *p1100;
|
THIS_MODULE, NULL, adapter_nr) &&
|
||||||
struct dvb_usb_device_properties *s660;
|
dvb_usb_device_init(intf, &dw2104_properties,
|
||||||
struct dvb_usb_device_properties *p7500;
|
THIS_MODULE, NULL, adapter_nr) &&
|
||||||
struct dvb_usb_device_properties *s421;
|
dvb_usb_device_init(intf, &dw3101_properties,
|
||||||
|
THIS_MODULE, NULL, adapter_nr) &&
|
||||||
p1100 = kmemdup(&s6x0_properties,
|
dvb_usb_device_init(intf, &s6x0_properties,
|
||||||
sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
|
THIS_MODULE, NULL, adapter_nr) &&
|
||||||
if (!p1100)
|
dvb_usb_device_init(intf, &p1100_properties,
|
||||||
goto err0;
|
THIS_MODULE, NULL, adapter_nr) &&
|
||||||
|
dvb_usb_device_init(intf, &s660_properties,
|
||||||
/* copy default structure */
|
THIS_MODULE, NULL, adapter_nr) &&
|
||||||
/* fill only different fields */
|
dvb_usb_device_init(intf, &p7500_properties,
|
||||||
p1100->firmware = P1100_FIRMWARE;
|
THIS_MODULE, NULL, adapter_nr) &&
|
||||||
p1100->devices[0] = d1100;
|
dvb_usb_device_init(intf, &s421_properties,
|
||||||
p1100->rc.core.rc_query = prof_rc_query;
|
THIS_MODULE, NULL, adapter_nr) &&
|
||||||
p1100->rc.core.rc_codes = RC_MAP_TBS_NEC;
|
dvb_usb_device_init(intf, &su3000_properties,
|
||||||
p1100->adapter->fe[0].frontend_attach = stv0288_frontend_attach;
|
THIS_MODULE, NULL, adapter_nr) &&
|
||||||
|
dvb_usb_device_init(intf, &t220_properties,
|
||||||
s660 = kmemdup(&s6x0_properties,
|
THIS_MODULE, NULL, adapter_nr) &&
|
||||||
sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
|
dvb_usb_device_init(intf, &tt_s2_4600_properties,
|
||||||
if (!s660)
|
THIS_MODULE, NULL, adapter_nr))) {
|
||||||
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);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = -ENODEV;
|
return -ENODEV;
|
||||||
kfree(s421);
|
|
||||||
err3:
|
|
||||||
kfree(p7500);
|
|
||||||
err2:
|
|
||||||
kfree(s660);
|
|
||||||
err1:
|
|
||||||
kfree(p1100);
|
|
||||||
err0:
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dw2102_disconnect(struct usb_interface *intf)
|
static void dw2102_disconnect(struct usb_interface *intf)
|
||||||
|
Reference in New Issue
Block a user