]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
PCI/sysfs: Only allow supported resource types in I/O and MMIO helpers
authorKrzysztof Wilczyński <kwilczynski@kernel.org>
Fri, 8 May 2026 04:35:22 +0000 (04:35 +0000)
committerBjorn Helgaas <bhelgaas@google.com>
Fri, 8 May 2026 22:44:47 +0000 (17:44 -0500)
Currently, when the sysfs attributes for PCI resources are added
dynamically, the resource access callbacks are only set when the underlying
BAR type matches, using .read and .write for IORESOURCE_IO, and .mmap for
IORESOURCE_MEM or IORESOURCE_IO with arch_can_pci_mmap_io() support.  As
such, when the callback is not set, the operation inherently fails.

After the conversion to static attributes, visibility callbacks will
control which resource files appear for each BAR, but the callbacks
themselves will always be set.

Add a type check to pci_resource_io() and pci_mmap_resource() to return
-EIO for an unsupported resource type.

Use the new pci_resource_is_io() and pci_resource_is_mem() helpers for the
type checks, replacing the open-coded bitwise flag tests and also drop the
local struct resource pointer in pci_mmap_resource().

Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Tested-by: Shivaprasad G Bhat <sbhat@linux.ibm.com>
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Link: https://patch.msgid.link/20260508043543.217179-4-kwilczynski@kernel.org
drivers/pci/pci-sysfs.c

index 1fbc3daf87cc57734f19f3b8ceb2977fe39f03cc..2e4e226e78d4145c265114a010977de695d21c99 100644 (file)
@@ -1082,20 +1082,24 @@ static int pci_mmap_resource(struct kobject *kobj, const struct bin_attribute *a
        struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
        int bar = (unsigned long)attr->private;
        enum pci_mmap_state mmap_type;
-       struct resource *res = pci_resource_n(pdev, bar);
        int ret;
 
        ret = security_locked_down(LOCKDOWN_PCI_ACCESS);
        if (ret)
                return ret;
 
-       if (res->flags & IORESOURCE_MEM && iomem_is_exclusive(res->start))
+       if (!pci_resource_is_mem(pdev, bar) &&
+           !(pci_resource_is_io(pdev, bar) && arch_can_pci_mmap_io()))
+               return -EIO;
+
+       if (pci_resource_is_mem(pdev, bar) &&
+           iomem_is_exclusive(pci_resource_start(pdev, bar)))
                return -EINVAL;
 
        if (!pci_mmap_fits(pdev, bar, vma, PCI_MMAP_SYSFS))
                return -EINVAL;
 
-       mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;
+       mmap_type = pci_resource_is_mem(pdev, bar) ? pci_mmap_mem : pci_mmap_io;
 
        return pci_mmap_resource_range(pdev, bar, vma, mmap_type, write_combine);
 }
@@ -1123,6 +1127,9 @@ static ssize_t pci_resource_io(struct file *filp, struct kobject *kobj,
        int bar = (unsigned long)attr->private;
        unsigned long port = off;
 
+       if (!pci_resource_is_io(pdev, bar))
+               return -EIO;
+
        port += pci_resource_start(pdev, bar);
 
        if (port > pci_resource_end(pdev, bar))