]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
PCI: Pass domain number to pci_bus_release_domain_nr() explicitly
authorManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Thu, 12 Sep 2024 05:30:25 +0000 (11:00 +0530)
committerKrzysztof Wilczyński <kwilczynski@kernel.org>
Fri, 13 Sep 2024 22:12:29 +0000 (22:12 +0000)
The pci_bus_release_domain_nr() API is supposed to free the domain
number allocated by pci_bus_find_domain_nr(). Most of the callers of
pci_bus_find_domain_nr(), store the domain number in pci_bus::domain_nr.

As such, the pci_bus_release_domain_nr() implicitly frees the domain
number by dereferencing 'struct pci_bus'. However, one of the callers
of this API, the PCI endpoint subsystem, doesn't have 'struct pci_bus',
so it only passes NULL. Due to this, the API will end up dereferencing
the NULL pointer.

To fix this issue, pass the domain number to this API explicitly. Since
'struct pci_bus' is not used for anything else other than extracting the
domain number, it makes sense to pass the domain number directly.

Fixes: 0328947c5032 ("PCI: endpoint: Assign PCI domain number for endpoint controllers")
Closes: https://lore.kernel.org/linux-pci/c0c40ddb-bf64-4b22-9dd1-8dbb18aa2813@stanley.mountain
Link: https://lore.kernel.org/linux-pci/20240912053025.25314-1-manivannan.sadhasivam@linaro.org
Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
[kwilczynski: commit log]
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
drivers/pci/endpoint/pci-epc-core.c
drivers/pci/pci.c
drivers/pci/probe.c
drivers/pci/remove.c
include/linux/pci.h

index 085a2de8b923d7b52f44bc04dfd52e853a5031f2..17f00710925508e60fbd21116af5b424abdcd3e7 100644 (file)
@@ -840,7 +840,7 @@ void pci_epc_destroy(struct pci_epc *epc)
        device_unregister(&epc->dev);
 
 #ifdef CONFIG_PCI_DOMAINS_GENERIC
-       pci_bus_release_domain_nr(NULL, &epc->dev);
+       pci_bus_release_domain_nr(&epc->dev, epc->domain_nr);
 #endif
 }
 EXPORT_SYMBOL_GPL(pci_epc_destroy);
index e3a49f66982d52fc8a30f3dbf387a2ea95be1deb..b86693c917534f0f58e3f4ad535baba5ea235c28 100644 (file)
@@ -6801,16 +6801,16 @@ static int of_pci_bus_find_domain_nr(struct device *parent)
        return ida_alloc(&pci_domain_nr_dynamic_ida, GFP_KERNEL);
 }
 
-static void of_pci_bus_release_domain_nr(struct pci_bus *bus, struct device *parent)
+static void of_pci_bus_release_domain_nr(struct device *parent, int domain_nr)
 {
-       if (bus->domain_nr < 0)
+       if (domain_nr < 0)
                return;
 
        /* Release domain from IDA where it was allocated. */
-       if (of_get_pci_domain_nr(parent->of_node) == bus->domain_nr)
-               ida_free(&pci_domain_nr_static_ida, bus->domain_nr);
+       if (of_get_pci_domain_nr(parent->of_node) == domain_nr)
+               ida_free(&pci_domain_nr_static_ida, domain_nr);
        else
-               ida_free(&pci_domain_nr_dynamic_ida, bus->domain_nr);
+               ida_free(&pci_domain_nr_dynamic_ida, domain_nr);
 }
 
 int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
@@ -6819,11 +6819,11 @@ int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
                               acpi_pci_bus_find_domain_nr(bus);
 }
 
-void pci_bus_release_domain_nr(struct pci_bus *bus, struct device *parent)
+void pci_bus_release_domain_nr(struct device *parent, int domain_nr)
 {
        if (!acpi_disabled)
                return;
-       of_pci_bus_release_domain_nr(bus, parent);
+       of_pci_bus_release_domain_nr(parent, domain_nr);
 }
 #endif
 
index b14b9876c0303ff0d5fe92a63039f8217003a558..e9e56bbb3b59d1081ac319be80d539504b301d78 100644 (file)
@@ -1061,7 +1061,7 @@ unregister:
 
 free:
 #ifdef CONFIG_PCI_DOMAINS_GENERIC
-       pci_bus_release_domain_nr(bus, parent);
+       pci_bus_release_domain_nr(parent, bus->domain_nr);
 #endif
        kfree(bus);
        return err;
index 910387e5bdbf985a3f1fa3184348e7d0bc8cb524..d2523fdf9bae47e0bd19ce6af2301402297532a5 100644 (file)
@@ -163,7 +163,7 @@ void pci_remove_root_bus(struct pci_bus *bus)
 #ifdef CONFIG_PCI_DOMAINS_GENERIC
        /* Release domain_nr if it was dynamically allocated */
        if (host_bridge->domain_nr == PCI_DOMAIN_NR_NOT_SET)
-               pci_bus_release_domain_nr(bus, host_bridge->dev.parent);
+               pci_bus_release_domain_nr(host_bridge->dev.parent, bus->domain_nr);
 #endif
 
        pci_remove_bus(bus);
index 4cf89a4b4cbcf03ec093376092178a1fd4efd9a4..37d97bef060f9ebd26bd4ab1c74aab36c09576d7 100644 (file)
@@ -1884,7 +1884,7 @@ static inline int acpi_pci_bus_find_domain_nr(struct pci_bus *bus)
 { return 0; }
 #endif
 int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent);
-void pci_bus_release_domain_nr(struct pci_bus *bus, struct device *parent);
+void pci_bus_release_domain_nr(struct device *parent, int domain_nr);
 #endif
 
 /* Some architectures require additional setup to direct VGA traffic */