Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b41d6cf3 authored by Jean Delvare's avatar Jean Delvare Committed by Jesse Barnes
Browse files

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: default avatarGreg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent edbc25ca
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -163,6 +163,10 @@ need pass only as many optional fields as necessary:
	o class and classmask fields default to 0
	o driver_data defaults to 0UL.

Note that driver_data must match the value used by any of the pci_device_id
entries defined in the driver. This makes the driver_data field mandatory
if all the pci_device_id entries have a non-zero driver_data value.

Once added, the driver probe routine will be invoked for any unclaimed
PCI devices listed in its (newly updated) pci_ids list.

+0 −4
Original line number Diff line number Diff line
@@ -332,10 +332,6 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
	int error;
	u8 temp;
	
	/* driver_data might come from user-space, so check it */
	if (id->driver_data >= ARRAY_SIZE(chipname))
		return -EINVAL;

	if (amd756_ioport) {
		dev_err(&pdev->dev, "Only one device supported "
		       "(you have a strange motherboard, btw)\n");
+0 −4
Original line number Diff line number Diff line
@@ -332,10 +332,6 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
	unsigned char temp;
	int error = -ENODEV;

	/* driver_data might come from user-space, so check it */
	if (id->driver_data & 1 || id->driver_data > 0xff)
		return -EINVAL;

	/* Determine the address of the SMBus areas */
	if (force_addr) {
		vt596_smba = force_addr & 0xfff0;
+16 −2
Original line number Diff line number Diff line
@@ -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;