diff mbox

fix size checks for mmap() on /proc/bus/pci files (resent)

Message ID 4cbffbf8.Qhs/h1a0ymU/N8ON%martin.wilck@ts.fujitsu.com (mailing list archive)
State Superseded, archived
Headers show

Commit Message

Martin Wilck Oct. 21, 2010, 8:38 a.m. UTC
None
diff mbox

Patch

--- a/drivers/pci/pci.h.orig	2010-09-01 06:57:20.000000000 +0200
+++ a/drivers/pci/pci.h	2010-10-20 18:44:22.000000000 +0200
@@ -14,7 +14,7 @@  extern void pci_remove_sysfs_dev_files(s
 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);
+			 struct vm_area_struct *vmai, int is_proc);
 #endif
 int pci_probe_reset_function(struct pci_dev *dev);
 
--- a/drivers/pci/proc.c.orig	2010-09-01 06:57:17.000000000 +0200
+++ a/drivers/pci/proc.c	2010-10-20 18:53:37.000000000 +0200
@@ -259,7 +259,7 @@  static int proc_bus_pci_mmap(struct file
 
 	/* 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))
+		if (pci_mmap_fits(dev, i, vma,  1))
 			break;
 	}
 
--- linux-2.6.32-71.el6.x86_64/drivers/pci/pci-sysfs.c	2010-09-01 06:57:17.000000000 +0200
+++ linux-2.6.32-71.el6.x86_64/drivers/pci/pci-sysfs.c.new	2010-10-21 01:34:58.000000000 +0200
@@ -675,17 +675,18 @@  void pci_remove_legacy_files(struct pci_
 
 #ifdef HAVE_PCI_MMAP
 
-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, int is_proc)
 {
-	unsigned long nr, start, size;
+	unsigned long nr, start, size, pci_start;
 
+	if (pci_resource_len(pdev, resno) == 0)
+		return 0;
 	nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
 	start = vma->vm_pgoff;
 	size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1;
-	if (start < size && size - start >= nr)
+	pci_start = is_proc ? pci_resource_start(pdev, resno) >> PAGE_SHIFT : 0;
+	if (start >= pci_start && start < pci_start + size && start + nr <= pci_start + size)
 		return 1;
-	WARN(1, "process \"%s\" tried to map 0x%08lx-0x%08lx on %s BAR %d (size 0x%08lx)\n",
-		current->comm, start, start+nr, pci_name(pdev), resno, size);
 	return 0;
 }
 
@@ -715,8 +716,12 @@  pci_mmap_resource(struct kobject *kobj, 
 	if (i >= PCI_ROM_RESOURCE)
 		return -ENODEV;
 
-	if (!pci_mmap_fits(pdev, i, vma))
+	if (!pci_mmap_fits(pdev, i, vma, 0)) {
+		WARN(1, "process \"%s\" tried to map 0x%08lx bytes at page 0x%08lx on %s BAR %d (start 0x%16Lx, size 0x%16Lx)\n",
+			current->comm, vma->vm_end-vma->vm_start, vma->vm_pgoff, pci_name(pdev), i,
+			pci_resource_start(pdev, i), pci_resource_len(pdev, i));
 		return -EINVAL;
+	}
 
 	/* pci_mmap_page_range() expects the same kind of entry as coming
 	 * from /proc/bus/pci/ which is a "user visible" value. If this is