Re: [PATCH v4 8/9] PCI: Fix dyn_id add TOCTOU

[email protected] Fri, 24 Jul 2026 22:02:07 +0000
Newsgroups org.kernel.vger.linux-ide,org.freedesktop.lists.dri-devel,org.kernel.vger.linux-pci,org.kernel.vger.linux-scsi
Message-ID <[email protected]>
Thank you for your contribution! Sashiko AI review found 1 potential issue(=
s) to consider:

Pre-existing issues:
- [High] `pci_match_device()` returns a pointer to the `id` field of a dyna=
mically allocated `struct pci_dynid` after releasing the `drv->dynids.lock`=
 spinlock, which can result in a Use-After-Free in the probe path if the ID=
 is concurrently removed via sysfs.
--

--- Patch [8]: [PATCH v4 8/9] PCI: Fix dyn_id add TOCTOU ---
commit b2b9cd8b65d097234cb7fc1e84df45480eb112de
Author: Gary Guo <[email protected]>

PCI: Fix dyn_id add TOCTOU

Currently there is a TOCTOU issue in new_id_store() as the dyn ID insertion
in pci_add_dynid() and the pci_match_device() are in separate critical
sections.

Fix this by moving the existing ID check to inside pci_add_dynid() and only
check against the static ID table outside the critical section.

> diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
> index c9424edb45481..ab3bb756ce89a 100644
> --- a/drivers/pci/pci-driver.c
> +++ b/drivers/pci/pci-driver.c
[ ... ]
> @@ -153,7 +190,7 @@ static const struct pci_device_id *pci_match_device(s=
truct pci_driver *drv,
>  						    struct pci_dev *dev)
>  {
>  	struct pci_dynid *dynid;
> -	const struct pci_device_id *found_id =3D NULL, *ids;
> +	const struct pci_device_id *found_id =3D NULL;

[Severity: High]
This isn't a bug introduced by this patch, but does pci_match_device() have=
 a
use-after-free risk when returning dynamic IDs?

It looks like it returns a pointer to the id field of a dynamically allocat=
ed
struct pci_dynid after releasing the drv->dynids.lock spinlock:

pci_match_device()
    spin_lock(&drv->dynids.lock);
    list_for_each_entry(dynid, &drv->dynids.list, node) {
        if (pci_match_one_id(&dynid->id, &dev_id)) {
            found_id =3D &dynid->id;
            break;
        }
    }
    spin_unlock(&drv->dynids.lock);

    if (found_id)
        return found_id;

If remove_id_store() is triggered via sysfs concurrently, it can acquire
dynids.lock, remove the dynamic ID, and call kfree() on the structure:

remove_id_store()
    list_del(&dynid->node);
    kfree(dynid);

If this happens while __pci_device_probe() has matched the dynamic ID but
hasn't finished executing the driver's probe() routine, could the driver
dereference a freed struct pci_device_id?

__pci_device_probe()
    id =3D pci_match_device(drv, pci_dev);
    if (id)
        error =3D pci_call_probe(drv, pci_dev, id);

>  	struct pci_device_id dev_id;
>  	int ret;

--=20
Sashiko AI review =C2=B7 https://sashiko.dev/#/patchset/20260723-pci_id_fix=
[email protected]?part=3D8