PCI: check mmap range of /proc/bus/pci files too
authorJesse Barnes <jbarnes@virtuousgeek.org>
Fri, 24 Oct 2008 17:32:33 +0000 (10:32 -0700)
committerJesse Barnes <jbarnes@virtuousgeek.org>
Wed, 7 Jan 2009 19:12:20 +0000 (11:12 -0800)
/proc/bus/pci allows you to mmap resource ranges too, so we should probably be
checking to make sure the mapping is somewhat valid.  Uses the same code as the recent sysfs mmap range checking patch from Linus.

Acked-by: David Miller <davem@davemloft.net>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
drivers/pci/pci-sysfs.c
drivers/pci/pci.h
drivers/pci/proc.c

index c88485860a0ad3dfff19485a417aaf112b051f08..388440e0d22228ac62ef39afd688dc1cc566abb6 100644 (file)
@@ -569,7 +569,7 @@ void pci_remove_legacy_files(struct pci_bus *b)
 
 #ifdef HAVE_PCI_MMAP
 
-static int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma)
+int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma)
 {
        unsigned long nr, start, size;
 
index 9de87e9f98f5ad5d7327a000474eef6b54da689d..d3e65e29df5113e94c9669c239b49a403c059be6 100644 (file)
@@ -10,6 +10,10 @@ extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env);
 extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
 extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
 extern void pci_cleanup_rom(struct pci_dev *dev);
+#ifdef HAVE_PCI_MMAP
+extern int pci_mmap_fits(struct pci_dev *pdev, int resno,
+                        struct vm_area_struct *vma);
+#endif
 
 /**
  * Firmware PM callbacks
index e1098c302c4565d56cdb59e97e276293dd1bbbb5..7fb086d396170d56aca7d26f935ed872cf32fec0 100644 (file)
@@ -252,11 +252,20 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
        const struct proc_dir_entry *dp = PDE(inode);
        struct pci_dev *dev = dp->data;
        struct pci_filp_private *fpriv = file->private_data;
-       int ret;
+       int i, ret;
 
        if (!capable(CAP_SYS_RAWIO))
                return -EPERM;
 
+       /* Make sure the caller is mapping a real resource for this device */
+       for (i = 0; i < PCI_ROM_RESOURCE; i++) {
+               if (pci_mmap_fits(dev, i, vma))
+                       break;
+       }
+
+       if (i >= PCI_ROM_RESOURCE)
+               return -ENODEV;
+
        ret = pci_mmap_page_range(dev, vma,
                                  fpriv->mmap_state,
                                  fpriv->write_combine);