Commit f8bf2aeb authored by James Sewart's avatar James Sewart Committed by Bjorn Helgaas
Browse files

PCI: Fix pci_add_dma_alias() bitmask size

The number of possible devfns is 256, but pci_add_dma_alias() allocated a
bitmap of size 255.  Fix this off-by-one error.

This fixes commits 338c3149 ("PCI: Add support for multiple DMA
aliases") and c6635792 ("PCI: Allocate dma_alias_mask with
bitmap_zalloc()"), but I doubt it was possible to see a problem because
it takes 4 64-bit longs (or 8 32-bit longs) to hold 255 bits, and
bitmap_zalloc() doesn't save the 255-bit size anywhere.

[bhelgaas: commit log, move #define to drivers/pci/pci.h, include loop
limit fix from Qian Cai:
https://lore.kernel.org/r/20191218170004.5297-1-cai@lca.pw

]
Signed-off-by: default avatarJames Sewart <jamessewart@arista.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Reviewed-by: default avatarLogan Gunthorpe <logang@deltatee.com>
parent 8c386cc8
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -6017,7 +6017,7 @@ EXPORT_SYMBOL_GPL(pci_pr3_present);
void pci_add_dma_alias(struct pci_dev *dev, u8 devfn)
{
	if (!dev->dma_alias_mask)
		dev->dma_alias_mask = bitmap_zalloc(U8_MAX, GFP_KERNEL);
		dev->dma_alias_mask = bitmap_zalloc(MAX_NR_DEVFNS, GFP_KERNEL);
	if (!dev->dma_alias_mask) {
		pci_warn(dev, "Unable to allocate DMA alias mask\n");
		return;
+3 −0
Original line number Diff line number Diff line
@@ -4,6 +4,9 @@

#include <linux/pci.h>

/* Number of possible devfns: 0.0 to 1f.7 inclusive */
#define MAX_NR_DEVFNS 256

#define PCI_FIND_CAP_TTL	48

#define PCI_VSEC_ID_INTEL_TBT	0x1234	/* Thunderbolt */
+2 −2
Original line number Diff line number Diff line
@@ -41,9 +41,9 @@ int pci_for_each_dma_alias(struct pci_dev *pdev,
	 * DMA, iterate over that too.
	 */
	if (unlikely(pdev->dma_alias_mask)) {
		u8 devfn;
		unsigned int devfn;

		for_each_set_bit(devfn, pdev->dma_alias_mask, U8_MAX) {
		for_each_set_bit(devfn, pdev->dma_alias_mask, MAX_NR_DEVFNS) {
			ret = fn(pdev, PCI_DEVID(pdev->bus->number, devfn),
				 data);
			if (ret)