[PATCH] spmi: Fix potential use-after-free by grabbing of_node reference

AngeloGioacchino Del Regno posted 1 patch 2 weeks, 4 days ago
drivers/spmi/spmi.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
[PATCH] spmi: Fix potential use-after-free by grabbing of_node reference
Posted by AngeloGioacchino Del Regno 2 weeks, 4 days ago
As noticed by Sashiko during a review run of an unrelated patch,
in of_spmi_register_devices(), for_each_available_child_of_node()
is used to loop through children, and to also assign a node to a
newly created SPMI child device.

Problem is that the refcount is dropped at every iteration so, in
the specific case of DT overlays, a use-after-free may occur when
an overlay is dynamically unloaded!

To resolve this, increase the of_node refcount when assigning (in
function of_spmi_register_devices) and release the reference in
spmi_device_remove().

Fixes: bc32bbd04011 ("spmi: Set fwnode for spmi devices")
Cc: stable@vger.kernel.org
Reported-by: Sashiko Bot <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260608100949.36309-1-angelogioacchino.delregno@collabora.com?part=2
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
 drivers/spmi/spmi.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/spmi/spmi.c b/drivers/spmi/spmi.c
index 05915176f21e..b4f30e7e9372 100644
--- a/drivers/spmi/spmi.c
+++ b/drivers/spmi/spmi.c
@@ -97,6 +97,9 @@ EXPORT_SYMBOL_GPL(spmi_device_add);
  */
 void spmi_device_remove(struct spmi_device *sdev)
 {
+	if (IS_ENABLED(CONFIG_OF))
+		of_node_put(sdev->dev.of_node);
+
 	device_unregister(&sdev->dev);
 }
 EXPORT_SYMBOL_GPL(spmi_device_remove);
@@ -592,13 +595,14 @@ static void of_spmi_register_devices(struct spmi_controller *ctrl)
 		if (!sdev)
 			continue;
 
-		device_set_node(&sdev->dev, of_fwnode_handle(node));
+		device_set_node(&sdev->dev, of_fwnode_handle(of_node_get(node)));
 		sdev->usid = (u8)reg[0];
 
 		err = spmi_device_add(sdev);
 		if (err) {
 			dev_err(&sdev->dev,
 				"failure adding device. status %pe\n", ERR_PTR(err));
+			of_node_put(node);
 			spmi_device_put(sdev);
 		}
 	}
-- 
2.54.0