aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--Documentation/PCI/pci.txt4
-rw-r--r--drivers/i2c/busses/i2c-amd756.c4
-rw-r--r--drivers/i2c/busses/i2c-viapro.c4
-rw-r--r--drivers/pci/pci-driver.c18
4 files changed, 20 insertions, 10 deletions
diff --git a/Documentation/PCI/pci.txt b/Documentation/PCI/pci.txt
index 8d4dc6250c58..fd4907a2968c 100644
--- a/Documentation/PCI/pci.txt
+++ b/Documentation/PCI/pci.txt
@@ -163,6 +163,10 @@ need pass only as many optional fields as necessary:
163 o class and classmask fields default to 0 163 o class and classmask fields default to 0
164 o driver_data defaults to 0UL. 164 o driver_data defaults to 0UL.
165 165
166Note that driver_data must match the value used by any of the pci_device_id
167entries defined in the driver. This makes the driver_data field mandatory
168if all the pci_device_id entries have a non-zero driver_data value.
169
166Once added, the driver probe routine will be invoked for any unclaimed 170Once added, the driver probe routine will be invoked for any unclaimed
167PCI devices listed in its (newly updated) pci_ids list. 171PCI devices listed in its (newly updated) pci_ids list.
168 172
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
index a3542b053c8e..424dad6f18d8 100644
--- a/drivers/i2c/busses/i2c-amd756.c
+++ b/drivers/i2c/busses/i2c-amd756.c
@@ -332,10 +332,6 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
332 int error; 332 int error;
333 u8 temp; 333 u8 temp;
334 334
335 /* driver_data might come from user-space, so check it */
336 if (id->driver_data >= ARRAY_SIZE(chipname))
337 return -EINVAL;
338
339 if (amd756_ioport) { 335 if (amd756_ioport) {
340 dev_err(&pdev->dev, "Only one device supported " 336 dev_err(&pdev->dev, "Only one device supported "
341 "(you have a strange motherboard, btw)\n"); 337 "(you have a strange motherboard, btw)\n");
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index 2324780484c0..9f194d9efd91 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -332,10 +332,6 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
332 unsigned char temp; 332 unsigned char temp;
333 int error = -ENODEV; 333 int error = -ENODEV;
334 334
335 /* driver_data might come from user-space, so check it */
336 if (id->driver_data & 1 || id->driver_data > 0xff)
337 return -EINVAL;
338
339 /* Determine the address of the SMBus areas */ 335 /* Determine the address of the SMBus areas */
340 if (force_addr) { 336 if (force_addr) {
341 vt596_smba = force_addr & 0xfff0; 337 vt596_smba = force_addr & 0xfff0;
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;