]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/2.6.36.2/pci-fix-size-checks-for-mmap-on-proc-bus-pci-files.patch
Fixes for 4.19
[thirdparty/kernel/stable-queue.git] / releases / 2.6.36.2 / pci-fix-size-checks-for-mmap-on-proc-bus-pci-files.patch
CommitLineData
19fe9a56
GKH
1From 3b519e4ea618b6943a82931630872907f9ac2c2b Mon Sep 17 00:00:00 2001
2From: Martin Wilck <martin.wilck@ts.fujitsu.com>
3Date: Wed, 10 Nov 2010 11:03:21 +0100
4Subject: PCI: fix size checks for mmap() on /proc/bus/pci files
5
6From: Martin Wilck <martin.wilck@ts.fujitsu.com>
7
8commit 3b519e4ea618b6943a82931630872907f9ac2c2b upstream.
9
10The checks for valid mmaps of PCI resources made through /proc/bus/pci files
11that were introduced in 9eff02e2042f96fb2aedd02e032eca1c5333d767 have several
12problems:
13
141. mmap() calls on /proc/bus/pci files are made with real file offsets > 0,
15whereas under /sys/bus/pci/devices, the start of the resource corresponds
16to offset 0. This may lead to false negatives in pci_mmap_fits(), which
17implicitly assumes the /sys/bus/pci/devices layout.
18
192. The loop in proc_bus_pci_mmap doesn't skip empty resouces. This leads
20to false positives, because pci_mmap_fits() doesn't treat empty resources
21correctly (the calculated size is 1 << (8*sizeof(resource_size_t)-PAGE_SHIFT)
22in this case!).
23
243. If a user maps resources with BAR > 0, pci_mmap_fits will emit bogus
25WARNINGS for the first resources that don't fit until the correct one is found.
26
27On many controllers the first 2-4 BARs are used, and the others are empty.
28In this case, an mmap attempt will first fail on the non-empty BARs
29(including the "right" BAR because of 1.) and emit bogus WARNINGS because
30of 3., and finally succeed on the first empty BAR because of 2.
31This is certainly not the intended behaviour.
32
33This patch addresses all 3 issues.
34Updated with an enum type for the additional parameter for pci_mmap_fits().
35
36Signed-off-by: Martin Wilck <martin.wilck@ts.fujitsu.com>
37Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
38Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
39
40---
41 drivers/pci/pci-sysfs.c | 22 ++++++++++++++++------
42 drivers/pci/pci.h | 7 ++++++-
43 drivers/pci/proc.c | 2 +-
44 3 files changed, 23 insertions(+), 8 deletions(-)
45
46--- a/drivers/pci/pci-sysfs.c
47+++ b/drivers/pci/pci-sysfs.c
48@@ -705,17 +705,21 @@ void pci_remove_legacy_files(struct pci_
49
50 #ifdef HAVE_PCI_MMAP
51
52-int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma)
53+int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma,
54+ enum pci_mmap_api mmap_api)
55 {
56- unsigned long nr, start, size;
57+ unsigned long nr, start, size, pci_start;
58
59+ if (pci_resource_len(pdev, resno) == 0)
60+ return 0;
61 nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
62 start = vma->vm_pgoff;
63 size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1;
64- if (start < size && size - start >= nr)
65+ pci_start = (mmap_api == PCI_MMAP_SYSFS) ?
66+ pci_resource_start(pdev, resno) >> PAGE_SHIFT : 0;
67+ if (start >= pci_start && start < pci_start + size &&
68+ start + nr <= pci_start + size)
69 return 1;
70- WARN(1, "process \"%s\" tried to map 0x%08lx-0x%08lx on %s BAR %d (size 0x%08lx)\n",
71- current->comm, start, start+nr, pci_name(pdev), resno, size);
72 return 0;
73 }
74
75@@ -745,8 +749,14 @@ pci_mmap_resource(struct kobject *kobj,
76 if (i >= PCI_ROM_RESOURCE)
77 return -ENODEV;
78
79- if (!pci_mmap_fits(pdev, i, vma))
80+ if (!pci_mmap_fits(pdev, i, vma, PCI_MMAP_SYSFS)) {
81+ WARN(1, "process \"%s\" tried to map 0x%08lx bytes "
82+ "at page 0x%08lx on %s BAR %d (start 0x%16Lx, size 0x%16Lx)\n",
83+ current->comm, vma->vm_end-vma->vm_start, vma->vm_pgoff,
84+ pci_name(pdev), i,
85+ pci_resource_start(pdev, i), pci_resource_len(pdev, i));
86 return -EINVAL;
87+ }
88
89 /* pci_mmap_page_range() expects the same kind of entry as coming
90 * from /proc/bus/pci/ which is a "user visible" value. If this is
91--- a/drivers/pci/pci.h
92+++ b/drivers/pci/pci.h
93@@ -22,8 +22,13 @@ extern void pci_remove_firmware_label_fi
94 #endif
95 extern void pci_cleanup_rom(struct pci_dev *dev);
96 #ifdef HAVE_PCI_MMAP
97+enum pci_mmap_api {
98+ PCI_MMAP_SYSFS, /* mmap on /sys/bus/pci/devices/<BDF>/resource<N> */
99+ PCI_MMAP_PROCFS /* mmap on /proc/bus/pci/<BDF> */
100+};
101 extern int pci_mmap_fits(struct pci_dev *pdev, int resno,
102- struct vm_area_struct *vma);
103+ struct vm_area_struct *vmai,
104+ enum pci_mmap_api mmap_api);
105 #endif
106 int pci_probe_reset_function(struct pci_dev *dev);
107
108--- a/drivers/pci/proc.c
109+++ b/drivers/pci/proc.c
110@@ -260,7 +260,7 @@ static int proc_bus_pci_mmap(struct file
111
112 /* Make sure the caller is mapping a real resource for this device */
113 for (i = 0; i < PCI_ROM_RESOURCE; i++) {
114- if (pci_mmap_fits(dev, i, vma))
115+ if (pci_mmap_fits(dev, i, vma, PCI_MMAP_PROCFS))
116 break;
117 }
118