diff options
author | Rob Herring <[email protected]> | 2020-05-13 17:38:59 -0500 |
---|---|---|
committer | Bjorn Helgaas <[email protected]> | 2020-05-14 16:36:35 -0500 |
commit | 9885440b16b8fc1dd7275800fd28f56a92f60896 (patch) | |
tree | d9d0b84f87a9a1271b03cabc7217e713b55fe104 /drivers/fpga/fpga-bridge.c | |
parent | 1b54ae8327a4d630111c8d88ba7906483ec6010b (diff) |
PCI: Fix pci_host_bridge struct device release/free handling
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().
Link: https://lore.kernel.org/r/[email protected]
Reported-by: Anders Roxell <[email protected]>
Tested-by: Anders Roxell <[email protected]>
Signed-off-by: Rob Herring <[email protected]>
Signed-off-by: Bjorn Helgaas <[email protected]>
Reviewed-by: Lorenzo Pieralisi <[email protected]>
Acked-by: Arnd Bergmann <[email protected]>
Diffstat (limited to 'drivers/fpga/fpga-bridge.c')
0 files changed, 0 insertions, 0 deletions