[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [linux-2.6.18-xen] pciback: improve input validation


  • To: xen-changelog@xxxxxxxxxxxxxxxxxxx
  • From: Xen patchbot-linux-2.6.18-xen <patchbot@xxxxxxx>
  • Date: Tue, 25 Sep 2012 09:55:05 +0000
  • Delivery-date: Tue, 25 Sep 2012 09:55:13 +0000
  • List-id: "Change log for Mercurial \(receive only\)" <xen-changelog.lists.xen.org>

# HG changeset patch
# User Jan Beulich <jbeulich@xxxxxxxx>
# Date 1348566584 -7200
# Node ID 50245ed8527a266e614a233102b0994fc86f0151
# Parent  2e2f50c02c3c1b95c41f2e27b40b59b54fd246f2
pciback: improve input validation

Reject - where this is not already being done elsewhere - out of range
values originating from user mode. This goes as far as reasonably
possible considering the non-conformance of the in-kernel sscanf().

At the same time, relax quirk parsing so that 0x prefixes get tolerated
without unnecessarily limiting the range of values (in some cases using
the prefix would make parsing outright fail no matter what value was
intended to be specified) for the (future) case where the in-kernel
sscanf() properly honors field width specifications even for integer
conversions.

Plus, to match parsing of standalone PCI device specifications, allow a
second form of input not having a domain specified (implying domain 0).

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
---


diff -r 2e2f50c02c3c -r 50245ed8527a drivers/xen/pciback/pci_stub.c
--- a/drivers/xen/pciback/pci_stub.c    Tue Sep 25 11:48:19 2012 +0200
+++ b/drivers/xen/pciback/pci_stub.c    Tue Sep 25 11:49:44 2012 +0200
@@ -121,7 +121,8 @@ static struct pcistub_device *pcistub_de
                if (psdev->dev != NULL
                    && domain == pci_domain_nr(psdev->dev->bus)
                    && bus == psdev->dev->bus->number
-                   && PCI_DEVFN(slot, func) == psdev->dev->devfn) {
+                   && slot == PCI_SLOT(psdev->dev->devfn)
+                   && func == PCI_FUNC(psdev->dev->devfn)) {
                        pcistub_device_get(psdev);
                        goto out;
                }
@@ -170,7 +171,8 @@ struct pci_dev *pcistub_get_pci_dev_by_s
                if (psdev->dev != NULL
                    && domain == pci_domain_nr(psdev->dev->bus)
                    && bus == psdev->dev->bus->number
-                   && PCI_DEVFN(slot, func) == psdev->dev->devfn) {
+                   && slot == PCI_SLOT(psdev->dev->devfn)
+                   && func == PCI_FUNC(psdev->dev->devfn)) {
                        found_dev = pcistub_device_get_pci_dev(pdev, psdev);
                        break;
                }
@@ -906,11 +908,18 @@ static inline int str_to_quirk(const cha
 {
        int err;
 
-       err =
-           sscanf(buf, " %04x:%02x:%02x.%1x-%08x:%1x:%08x", domain, bus, slot,
-                  func, reg, size, mask);
+       err = sscanf(buf, " %x:%x:%x.%x-%x:%x:%x", domain, bus, slot, func,
+                    reg, size, mask);
        if (err == 7)
                return 0;
+
+       /* try again without domain */
+       *domain = 0;
+       err = sscanf(buf, " %x:%x.%x-%x:%x:%x", bus, slot, func, reg, size,
+                    mask);
+       if (err == 6)
+               return 0;
+
        return -EINVAL;
 }
 
@@ -918,7 +927,7 @@ static int pcistub_device_id_add(int dom
 {
        struct pcistub_device_id *pci_dev_id;
        unsigned long flags;
-       int rc = 0;
+       int rc = 0, devfn = PCI_DEVFN(slot, func);
 
        if (slot < 0) {
                for (slot = 0; !rc && slot < 32; ++slot)
@@ -932,13 +941,23 @@ static int pcistub_device_id_add(int dom
                return rc;
        }
 
+#ifdef CONFIG_PCI_DOMAINS
+       if (domain < 0 || domain > 0xffff
+#else
+       if (domain
+#endif
+           || bus < 0 || bus > 0xff
+           || PCI_SLOT(devfn) != slot
+           || PCI_FUNC(devfn) != func)
+               return -EINVAL;
+
        pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL);
        if (!pci_dev_id)
                return -ENOMEM;
 
        pci_dev_id->domain = domain;
        pci_dev_id->bus = bus;
-       pci_dev_id->devfn = PCI_DEVFN(slot, func);
+       pci_dev_id->devfn = devfn;
 
        pr_debug("pciback: wants to seize %04x:%02x:%02x.%01x\n",
                 domain, bus, slot, func);
@@ -979,14 +998,18 @@ static int pcistub_device_id_remove(int 
        return err;
 }
 
-static int pcistub_reg_add(int domain, int bus, int slot, int func, int reg,
-                          int size, int mask)
+static int pcistub_reg_add(int domain, int bus, int slot, int func,
+                          unsigned int reg, unsigned int size,
+                          unsigned int mask)
 {
        int err = 0;
        struct pcistub_device *psdev;
        struct pci_dev *dev;
        struct config_field *field;
 
+       if (reg > 0xfff || (size < 4 && (mask >> (size * 8))))
+               return -EINVAL;
+
        psdev = pcistub_device_find(domain, bus, slot, func);
        if (!psdev) {
                err = -ENODEV;
@@ -1149,13 +1172,11 @@ static ssize_t permissive_add(struct dev
        int err;
        struct pcistub_device *psdev;
        struct pciback_dev_data *dev_data;
+
        err = str_to_slot(buf, &domain, &bus, &slot, &func);
        if (err)
                goto out;
-       if (slot < 0 || func < 0) {
-               err = -EINVAL;
-               goto out;
-       }
+
        psdev = pcistub_device_find(domain, bus, slot, func);
        if (!psdev) {
                err = -ENODEV;

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.