Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] Clearing `device->driver_data = NULL` followed immediately by `kfree(root)` leaves a Use-After-Free race window for concurrent lockless readers.
- [High] Publishing `root` to `device->driver_data` before full initialization and without memory barriers allows readers to see uninitialized fields.
--
--- Patch [1]: [PATCH v2] ACPI: PCI: Clear driver_data on all paths that free the acpi_pci_root ---
commit df0768c14918e7decb436f5ec80561fb6dbd2aed
Author: Chen Pei <[email protected]>
ACPI: PCI: Clear driver_data on all paths that free the acpi_pci_root
This commit fixes dangling pointers in the ACPI PCI root code by ensuring
device->driver_data is cleared to NULL before the root bridge structure
is freed in both error and removal paths.
Link: https://sashiko.dev/#/patchset/[email protected]
Link: https://sashiko.dev/#/patchset/[email protected]
> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
> index 4c06c3ffd0cbb..408ba12362a79 100644
> --- a/drivers/acpi/pci_root.c
> +++ b/drivers/acpi/pci_root.c
> @@ -725,7 +725,6 @@ static int acpi_pci_root_add(struct acpi_device *device,
> dev_err(&device->dev,
> "Bus %04x:%02x not present in PCI namespace\n",
> root->segment, (unsigned int)root->secondary.start);
> - device->driver_data = NULL;
[Severity: High]
This isn't a bug introduced by this patch, but does the earlier assignment
of device->driver_data = root allow readers to see uninitialized fields?
Earlier in acpi_pci_root_add(), the pointer is published to
device->driver_data before critical fields like root->bus are initialized
later in the function:
acpi_pci_root_add() {
...
device->driver_data = root;
...
root->bus = pci_acpi_scan_root(root);
...
}
If a concurrent caller (such as bus_for_each_dev iteration in
cxl_acpi_probe()) fetches the root object, could it observe a NULL root->bus
and dereference it before initialization is complete?
Furthermore, without memory barriers, could the CPU reorder the
initialization such that readers observe partially written state?
> result = -ENODEV;
> goto remove_dmar;
> }
[ ... ]
> @@ -765,6 +764,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
> if (hotadd)
> dmar_device_remove(handle);
> end:
> + device->driver_data = NULL;
> kfree(root);
> return result;
> }
[Severity: High]
This is a pre-existing issue, but does clearing device->driver_data
immediately before kfree(root) leave a use-after-free window for concurrent
lockless readers?
If a lockless reader like hisi_pcie_handle_error() or add_host_bridge_uport()
calls acpi_pci_find_root(), it reads device->driver_data without taking a
lock:
acpi_pci_find_root() {
...
root = acpi_driver_data(device);
...
}
If the reader fetches the pointer just before device->driver_data is set
to NULL, and then this code proceeds to kfree(root), wouldn't the concurrent
reader dereference freed memory?
> @@ -788,6 +788,7 @@ static void acpi_pci_root_remove(struct acpi_device *device)
>
> pci_unlock_rescan_remove();
>
> + device->driver_data = NULL;
> kfree(root);
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.