Skip to content

Commit 67b9f18

Browse files
committed
Merge branch 'pci/devres'
- Enlarge the devres table[] to accommodate bridge windows, ROM, IOV BARs, etc (Philipp Stanner) - Validate BAR index in devres interfaces (Philipp Stanner) * pci/devres: PCI: Check BAR index for validity PCI: Fix wrong length of devres array
2 parents 4d1a2a9 + b1a7f99 commit 67b9f18

File tree

4 files changed

+58
-11
lines changed

4 files changed

+58
-11
lines changed

drivers/pci/devres.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
* Legacy struct storing addresses to whole mapped BARs.
4141
*/
4242
struct pcim_iomap_devres {
43-
void __iomem *table[PCI_STD_NUM_BARS];
43+
void __iomem *table[PCI_NUM_RESOURCES];
4444
};
4545

4646
/* Used to restore the old INTx state on driver detach. */
@@ -577,7 +577,7 @@ static int pcim_add_mapping_to_legacy_table(struct pci_dev *pdev,
577577
{
578578
void __iomem **legacy_iomap_table;
579579

580-
if (bar >= PCI_STD_NUM_BARS)
580+
if (!pci_bar_index_is_valid(bar))
581581
return -EINVAL;
582582

583583
legacy_iomap_table = (void __iomem **)pcim_iomap_table(pdev);
@@ -622,7 +622,7 @@ static void pcim_remove_bar_from_legacy_table(struct pci_dev *pdev, int bar)
622622
{
623623
void __iomem **legacy_iomap_table;
624624

625-
if (bar >= PCI_STD_NUM_BARS)
625+
if (!pci_bar_index_is_valid(bar))
626626
return;
627627

628628
legacy_iomap_table = (void __iomem **)pcim_iomap_table(pdev);
@@ -655,6 +655,9 @@ void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen)
655655
void __iomem *mapping;
656656
struct pcim_addr_devres *res;
657657

658+
if (!pci_bar_index_is_valid(bar))
659+
return NULL;
660+
658661
res = pcim_addr_devres_alloc(pdev);
659662
if (!res)
660663
return NULL;
@@ -722,6 +725,9 @@ void __iomem *pcim_iomap_region(struct pci_dev *pdev, int bar,
722725
int ret;
723726
struct pcim_addr_devres *res;
724727

728+
if (!pci_bar_index_is_valid(bar))
729+
return IOMEM_ERR_PTR(-EINVAL);
730+
725731
res = pcim_addr_devres_alloc(pdev);
726732
if (!res)
727733
return IOMEM_ERR_PTR(-ENOMEM);
@@ -823,6 +829,9 @@ static int _pcim_request_region(struct pci_dev *pdev, int bar, const char *name,
823829
int ret;
824830
struct pcim_addr_devres *res;
825831

832+
if (!pci_bar_index_is_valid(bar))
833+
return -EINVAL;
834+
826835
res = pcim_addr_devres_alloc(pdev);
827836
if (!res)
828837
return -ENOMEM;
@@ -991,6 +1000,9 @@ void __iomem *pcim_iomap_range(struct pci_dev *pdev, int bar,
9911000
void __iomem *mapping;
9921001
struct pcim_addr_devres *res;
9931002

1003+
if (!pci_bar_index_is_valid(bar))
1004+
return IOMEM_ERR_PTR(-EINVAL);
1005+
9941006
res = pcim_addr_devres_alloc(pdev);
9951007
if (!res)
9961008
return IOMEM_ERR_PTR(-ENOMEM);

drivers/pci/iomap.c

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
#include <linux/export.h>
1111

12+
#include "pci.h" /* for pci_bar_index_is_valid() */
13+
1214
/**
1315
* pci_iomap_range - create a virtual mapping cookie for a PCI BAR
1416
* @dev: PCI device that owns the BAR
@@ -33,12 +35,19 @@ void __iomem *pci_iomap_range(struct pci_dev *dev,
3335
unsigned long offset,
3436
unsigned long maxlen)
3537
{
36-
resource_size_t start = pci_resource_start(dev, bar);
37-
resource_size_t len = pci_resource_len(dev, bar);
38-
unsigned long flags = pci_resource_flags(dev, bar);
38+
resource_size_t start, len;
39+
unsigned long flags;
40+
41+
if (!pci_bar_index_is_valid(bar))
42+
return NULL;
43+
44+
start = pci_resource_start(dev, bar);
45+
len = pci_resource_len(dev, bar);
46+
flags = pci_resource_flags(dev, bar);
3947

4048
if (len <= offset || !start)
4149
return NULL;
50+
4251
len -= offset;
4352
start += offset;
4453
if (maxlen && len > maxlen)
@@ -77,16 +86,20 @@ void __iomem *pci_iomap_wc_range(struct pci_dev *dev,
7786
unsigned long offset,
7887
unsigned long maxlen)
7988
{
80-
resource_size_t start = pci_resource_start(dev, bar);
81-
resource_size_t len = pci_resource_len(dev, bar);
82-
unsigned long flags = pci_resource_flags(dev, bar);
89+
resource_size_t start, len;
90+
unsigned long flags;
8391

84-
85-
if (flags & IORESOURCE_IO)
92+
if (!pci_bar_index_is_valid(bar))
8693
return NULL;
8794

95+
start = pci_resource_start(dev, bar);
96+
len = pci_resource_len(dev, bar);
97+
flags = pci_resource_flags(dev, bar);
98+
8899
if (len <= offset || !start)
89100
return NULL;
101+
if (flags & IORESOURCE_IO)
102+
return NULL;
90103

91104
len -= offset;
92105
start += offset;

drivers/pci/pci.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3929,6 +3929,9 @@ EXPORT_SYMBOL(pci_enable_atomic_ops_to_root);
39293929
*/
39303930
void pci_release_region(struct pci_dev *pdev, int bar)
39313931
{
3932+
if (!pci_bar_index_is_valid(bar))
3933+
return;
3934+
39323935
/*
39333936
* This is done for backwards compatibility, because the old PCI devres
39343937
* API had a mode in which the function became managed if it had been
@@ -3973,6 +3976,9 @@ EXPORT_SYMBOL(pci_release_region);
39733976
static int __pci_request_region(struct pci_dev *pdev, int bar,
39743977
const char *name, int exclusive)
39753978
{
3979+
if (!pci_bar_index_is_valid(bar))
3980+
return -EINVAL;
3981+
39763982
if (pci_is_managed(pdev)) {
39773983
if (exclusive == IORESOURCE_EXCLUSIVE)
39783984
return pcim_request_region_exclusive(pdev, bar, name);

drivers/pci/pci.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,22 @@ static inline void pci_wakeup_event(struct pci_dev *dev)
167167
pm_wakeup_event(&dev->dev, 100);
168168
}
169169

170+
/**
171+
* pci_bar_index_is_valid - Check whether a BAR index is within valid range
172+
* @bar: BAR index
173+
*
174+
* Protects against overflowing &struct pci_dev.resource array.
175+
*
176+
* Return: true for valid index, false otherwise.
177+
*/
178+
static inline bool pci_bar_index_is_valid(int bar)
179+
{
180+
if (bar >= 0 && bar < PCI_NUM_RESOURCES)
181+
return true;
182+
183+
return false;
184+
}
185+
170186
static inline bool pci_has_subordinate(struct pci_dev *pci_dev)
171187
{
172188
return !!(pci_dev->subordinate);

0 commit comments

Comments
 (0)