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

[Xen-devel] [PATCH 3/3] linux-2.6.18/pciback: improve input validation


  • To: "xen-devel" <xen-devel@xxxxxxxxxxxxx>
  • From: "Jan Beulich" <JBeulich@xxxxxxxx>
  • Date: Mon, 24 Sep 2012 16:55:09 +0100
  • Delivery-date: Mon, 24 Sep 2012 15:55:31 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xen.org>

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>

--- a/drivers/xen/pciback/pci_stub.c
+++ b/drivers/xen/pciback/pci_stub.c
@@ -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;
@@ -1153,13 +1176,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;


Attachment: xen-pciback-strict.patch
Description: Text document

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel

 


Rackspace

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