From: Bastien Curutchet bastien.curutchet@bootlin.com
[ Upstream commit 5f4bbee069836e51ed0b6d7e565a292f070ababc ]
When an MFD device is added, a platform_device is allocated. If this device is linked to a DT description, the corresponding OF node is linked to the new platform device but the OF node's refcount isn't incremented. As of_node_put() is called during the platform device release, it leads to a refcount underflow.
Call of_node_get() to increment the OF node's refcount when the node is linked to the newly created platform device.
Signed-off-by: Bastien Curutchet bastien.curutchet@bootlin.com Link: https://lore.kernel.org/r/20250820-mfd-refcount-v1-1-6dcb5eb41756@bootlin.co... Signed-off-by: Lee Jones lee@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org ---
LLM Generated explanations, may be completely bogus:
YES
**Why This Is A Bugfix** - Root cause: `mfd_match_of_node_to_dev()` links a DT node to a new `platform_device` using `device_set_node(&pdev->dev, of_fwnode_handle(np));` but does not take a reference on the OF node. Later, the `platform_device` release path drops a reference unconditionally, causing an underflow. - Current linking without ref: drivers/mfd/mfd-core.c:134 - Platform device release drops the ref: drivers/base/platform.c:556 - `device_set_node()` does not acquire a reference; it only assigns: drivers/base/core.c:5274 - Correct pattern elsewhere: OF-based platform devices explicitly increment the node ref before linking: - Example: `device_set_node(&dev->dev, of_fwnode_handle(of_node_get(np)));` in drivers/of/platform.c:129
**What The Commit Changes** - Adds `of_node_get(np);` immediately before `device_set_node(&pdev->dev, of_fwnode_handle(np));` in `mfd_match_of_node_to_dev()`, balancing the unconditional `of_node_put()` at `platform_device` release. - New line added right before the existing call: drivers/mfd/mfd- core.c:134 - This matches how other subsystems handle device-tree node linkage and ensures the `of_node` refcount is correct when the device is unregistered.
**Evidence In Current Code Path** - During device creation, after a successful match, MFD code drops the loop’s reference to `np`: - `of_node_put(np);` in drivers/mfd/mfd-core.c:195 - Without an extra `of_node_get()` for the device itself, the platform device’s release path performs one more put than gets, leading to a refcount underflow (and potentially a UAF if overlays or dynamic DT are involved).
**Risk, Scope, and Stable Suitability** - Small, contained fix: a single additional `of_node_get()` call in a narrow path. - No architectural changes; only balances reference counting. - Aligns MFD behavior with the broader kernel conventions for DT-backed devices. - Touches a core MFD helper but with minimal regression risk; it only affects CONFIG_OF cases. - Fix addresses a real bug that can manifest at device removal/teardown, producing refcount warnings or worse under dynamic DT.
**Backport Considerations** - APIs used (`of_node_get`, `device_set_node`, `of_fwnode_handle`) exist in stable series. - No dependency on recent reworks; the bug predates switching to `device_set_node` (earlier code also omitted the ref get). - While the commit message does not explicitly carry a “Cc: stable”, it is a classic stable-eligible bugfix: important correctness issue, minimal change, clear benefit, low risk.
In summary, the patch balances OF node refcounting for MFD-created platform devices and should be backported to stable trees.
drivers/mfd/mfd-core.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 76bd316a50afc..7d14a1e7631ee 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -131,6 +131,7 @@ static int mfd_match_of_node_to_dev(struct platform_device *pdev, of_entry->np = np; list_add_tail(&of_entry->list, &mfd_of_node_list);
+ of_node_get(np); device_set_node(&pdev->dev, of_fwnode_handle(np)); #endif return 0;