On Fri, Mar 07, 2025 at 11:46:41AM +0300, Dan Carpenter wrote: > Calling put_device(&bus->dev) will call release_pcibus_dev() which will > free the bus. It leads to a use after free when we dereference "bus" in > the cleanup code and the kfree(bus) is a double free. > > Fixes: b80b4d4972e6 ("PCI: Fix reference leak in pci_register_host_bridge()") > Signed-off-by: Dan Carpenter <dan.carpenter@xxxxxxxxxx> Squashed into the b80b4d4972e6 commit on pci/enumeration for v6.15, thanks! > --- > drivers/pci/probe.c | 13 ++++++++----- > 1 file changed, 8 insertions(+), 5 deletions(-) > > diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c > index 819d23ce3565..c13f2c957002 100644 > --- a/drivers/pci/probe.c > +++ b/drivers/pci/probe.c > @@ -957,6 +957,7 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge) > resource_size_t offset, next_offset; > LIST_HEAD(resources); > struct resource *res, *next_res; > + bool bus_registered = false; > char addr[64], *fmt; > const char *name; > int err; > @@ -1020,10 +1021,9 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge) > name = dev_name(&bus->dev); > > err = device_register(&bus->dev); > - if (err) { > - put_device(&bus->dev); > + bus_registered = true; > + if (err) > goto unregister; > - } > > pcibios_add_bus(bus); > > @@ -1110,12 +1110,15 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge) > unregister: > put_device(&bridge->dev); > device_del(&bridge->dev); > - > free: > #ifdef CONFIG_PCI_DOMAINS_GENERIC > pci_bus_release_domain_nr(parent, bus->domain_nr); > #endif > - kfree(bus); > + if (bus_registered) > + put_device(&bus->dev); > + else > + kfree(bus); > + > return err; > } > > -- > 2.47.2 >