PCI: Check dynids driver_data value for validity
Only accept dynids whose driver_data value matches one of the driver's pci_driver_id entries. This prevents the user from accidentally passing values the drivers do not expect. Cc: Milton Miller <miltonm@bga.com> Acked-by: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: Jean Delvare <khali@linux-fr.org> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
This commit is contained in:
committed by
Jesse Barnes
parent
edbc25caaa
commit
b41d6cf38e
@@ -43,18 +43,32 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
|
||||
{
|
||||
struct pci_dynid *dynid;
|
||||
struct pci_driver *pdrv = to_pci_driver(driver);
|
||||
const struct pci_device_id *ids = pdrv->id_table;
|
||||
__u32 vendor, device, subvendor=PCI_ANY_ID,
|
||||
subdevice=PCI_ANY_ID, class=0, class_mask=0;
|
||||
unsigned long driver_data=0;
|
||||
int fields=0;
|
||||
int retval = 0;
|
||||
int retval;
|
||||
|
||||
fields = sscanf(buf, "%x %x %x %x %x %x %lux",
|
||||
fields = sscanf(buf, "%x %x %x %x %x %x %lx",
|
||||
&vendor, &device, &subvendor, &subdevice,
|
||||
&class, &class_mask, &driver_data);
|
||||
if (fields < 2)
|
||||
return -EINVAL;
|
||||
|
||||
/* Only accept driver_data values that match an existing id_table
|
||||
entry */
|
||||
retval = -EINVAL;
|
||||
while (ids->vendor || ids->subvendor || ids->class_mask) {
|
||||
if (driver_data == ids->driver_data) {
|
||||
retval = 0;
|
||||
break;
|
||||
}
|
||||
ids++;
|
||||
}
|
||||
if (retval) /* No match */
|
||||
return retval;
|
||||
|
||||
dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
|
||||
if (!dynid)
|
||||
return -ENOMEM;
|
||||
|
||||
Reference in New Issue
Block a user