Re: [PATCH 2/2] PCI: Fix pci_host_bridge struct device release/free handling

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, May 14, 2020 at 12:39 AM Rob Herring <robh@xxxxxxxxxx> wrote:
>
> The PCI code has several paths where the struct pci_host_bridge is freed
> directly. This is wrong because it contains a struct device which is
> refcounted and should be freed using put_device(). This can result in
> use-after-free errors. I think this problem has existed since 2012 with
> commit 7b5436635800 ("PCI: add generic device into pci_host_bridge
> struct"). It generally hasn't mattered as most host bridge drivers are
> still built-in and can't unbind.
>
> The problem is a struct device should never be freed directly once
> device_initialize() is called and a ref is held, but that doesn't happen
> until pci_register_host_bridge(). There's then a window between
> allocating the host bridge and pci_register_host_bridge() where kfree
> should be used. This is fragile and requires callers to do the right
> thing. To fix this, we need to split device_register() into
> device_initialize() and device_add() calls, so that the host bridge
> struct is always freed by using a put_device().
>
> devm_pci_alloc_host_bridge() is using devm_kzalloc() to allocate struct
> pci_host_bridge which will be freed directly. Instead, we can use a
> custom devres action to call put_device().
>
> Reported-by: Anders Roxell <anders.roxell@xxxxxxxxxx>
> Cc: Arnd Bergmann <arnd@xxxxxxxx>
> Cc: Bjorn Helgaas <bhelgaas@xxxxxxxxxx>
> Signed-off-by: Rob Herring <robh@xxxxxxxxxx>

Thanks for working your way through that bit of code
and fixing my mistakes!

Your description makes a lot of sense and the code looks
reasonable, but I don't understand my own work enough any
more to be sure I didn't miss anything.

Acked-by: Arnd Bergmann <arnd@xxxxxxxx>



[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux