Re: [PATCH v1] resource: report a devm_request_resource() conflict under the lock
From: Tejun Heo
Date: Fri Oct 16 2026 - 13:07:30 EST
On Fri, Oct 16, 2026 at 10:00:43AM -0400, Nickolai Zeldovich wrote:
> devm_request_resource() calls request_resource_conflict(), which takes
> resource_lock, tries to insert the new resource and returns a pointer to
> the conflicting resource after dropping the lock. The error message is
> then formatted from that pointer: conflict->name and the %pR argument
> read the name, start, end, flags and desc of a resource that nothing
> pins any more. The owner of the conflicting resource may call
> release_resource() and free it the moment the lock is dropped.
>
> The conflicting resource normally belongs to another device. With two
> devices whose drivers claim overlapping regions (two PCI host bridges
> whose "ranges" windows overlap, two instances of a controller on the
> same aperture, or a stale claim an administrator is replacing), the
> following interleaving reads freed memory:
>
> CPU 0: driver B probe CPU 1: driver A unbind
> devm_request_resource(devB, root, resB)
> request_resource_conflict()
> write_lock(&resource_lock)
> __request_resource() -> resA
> write_unlock(&resource_lock)
> devres_release_all(devA)
> devm_resource_release()
> release_resource(resA)
> put_device() -> kfree(resA)
> dev_err(..., resA->name, resA) use after free
>
> Both halves are reachable from userspace on any kernel: a write to the
> "unbind" file of the driver that holds the region and a write to the
> "bind" file of the driver that wants it. One in-tree path is
> drivers/pci/bus.c devm_request_pci_bus_resources(), called from host
> bridge probe for every bridge window; the windows are the embedded
> struct resource of kzalloc'ed resource_entry objects that
> pci_free_resource_list() frees when the other bridge is released.
> In the common case the "resource collision" message is garbled; with
> the slab object poisoned (CONFIG_SLUB_DEBUG) or reused, formatting
> conflict->name oopses, and KASAN reports a slab-use-after-free read in
> devm_request_resource(). All of this happens in a probe that is
> already failing with -EBUSY. The window is a few hundred instructions
> wide and exists only when two devices actually collide, so the race
> has not been observed outside of analysis.
>
> Do the same here: take resource_lock, insert with __request_resource()
> and print the diagnostic while the lock still keeps the conflicting
> resource in the tree, then drop the lock. The return values and the
> devres handling are unchanged.
>
> The change was built for x86_64 and RISC-V; the resource KUnit tests
> pass on both.
>
> Found by formal verification of kernel/resource.c against the kernel
> binary.
>
> Fixes: 8d38821cbcf5 ("resources: Add device-managed request/release_resource()")
> Assisted-by: LLM
> Signed-off-by: Nickolai Zeldovich <nickolai@xxxxxxxxxxxxx>
Acked-by: Tejun Heo <tj@xxxxxxxxxx>
Thanks.
--
tejun