aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci-driver.c
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2008-08-17 15:06:59 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2008-10-20 13:48:35 -0400
commitb41d6cf38e27a940d998d989526a9748de1bf028 (patch)
treea2ae90005e000d4f9d16637171ff11dd31a4917a /drivers/pci/pci-driver.c
parentedbc25caaa492a82e19baa915f1f6b0a0db6554d (diff)
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>
Diffstat (limited to 'drivers/pci/pci-driver.c')
-rw-r--r--drivers/pci/pci-driver.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 4940a53c56a3..b4cdd690ae71 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -43,18 +43,32 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
43{ 43{
44 struct pci_dynid *dynid; 44 struct pci_dynid *dynid;
45 struct pci_driver *pdrv = to_pci_driver(driver); 45 struct pci_driver *pdrv = to_pci_driver(driver);
46 const struct pci_device_id *ids = pdrv->id_table;
46 __u32 vendor, device, subvendor=PCI_ANY_ID, 47 __u32 vendor, device, subvendor=PCI_ANY_ID,
47 subdevice=PCI_ANY_ID, class=0, class_mask=0; 48 subdevice=PCI_ANY_ID, class=0, class_mask=0;
48 unsigned long driver_data=0; 49 unsigned long driver_data=0;
49 int fields=0; 50 int fields=0;
50 int retval = 0; 51 int retval;
51 52
52 fields = sscanf(buf, "%x %x %x %x %x %x %lux", 53 fields = sscanf(buf, "%x %x %x %x %x %x %lx",
53 &vendor, &device, &subvendor, &subdevice, 54 &vendor, &device, &subvendor, &subdevice,
54 &class, &class_mask, &driver_data); 55 &class, &class_mask, &driver_data);
55 if (fields < 2) 56 if (fields < 2)
56 return -EINVAL; 57 return -EINVAL;
57 58
59 /* Only accept driver_data values that match an existing id_table
60 entry */
61 retval = -EINVAL;
62 while (ids->vendor || ids->subvendor || ids->class_mask) {
63 if (driver_data == ids->driver_data) {
64 retval = 0;
65 break;
66 }
67 ids++;
68 }
69 if (retval) /* No match */
70 return retval;
71
58 dynid = kzalloc(sizeof(*dynid), GFP_KERNEL); 72 dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
59 if (!dynid) 73 if (!dynid)
60 return -ENOMEM; 74 return -ENOMEM;