[PATCH] bus: moxtet: fix use-after-free in of_register_moxtet_devices()

Wentao Liang posted 1 patch 2 months, 1 week ago
drivers/bus/moxtet.c | 19 ++++++++-----------
1 file changed, 8 insertions(+), 11 deletions(-)
[PATCH] bus: moxtet: fix use-after-free in of_register_moxtet_devices()
Posted by Wentao Liang 2 months, 1 week ago
In of_register_moxtet_device(), one error paths release the device
node via of_node_put(nc) before returning an error pointer. However,
the caller of_register_moxtet_devices() continues to access the node
when it clears the OF_POPULATED flag on error, leading to a
use-after-free condition.

Fix this by moving the OF_POPULATED flag clearing into the callee's
error paths, before the of_node_put() is performed. Remove the
redundant error handling and warning in the caller, which is no longer
needed after the change.

Fixes: 5bc7f990cd98 ("bus: Add support for Moxtet bus")
Cc: stable@vger.kernel.org
Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
---
 drivers/bus/moxtet.c | 19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/drivers/bus/moxtet.c b/drivers/bus/moxtet.c
index 0d68c1a9f493..dc6b41cb4e2f 100644
--- a/drivers/bus/moxtet.c
+++ b/drivers/bus/moxtet.c
@@ -212,6 +212,7 @@ of_register_moxtet_device(struct moxtet *moxtet, struct device_node *nc)
 	if (!dev) {
 		dev_err(moxtet->dev,
 			"Moxtet device alloc error for %pOF\n", nc);
+		of_node_clear_flag(nc, OF_POPULATED);
 		return ERR_PTR(-ENOMEM);
 	}
 
@@ -219,7 +220,7 @@ of_register_moxtet_device(struct moxtet *moxtet, struct device_node *nc)
 	if (ret) {
 		dev_err(moxtet->dev, "%pOF has no valid 'reg' property (%d)\n",
 			nc, ret);
-		goto err_put;
+		goto err_clean;
 	}
 
 	dev->idx = val;
@@ -228,7 +229,7 @@ of_register_moxtet_device(struct moxtet *moxtet, struct device_node *nc)
 		dev_err(moxtet->dev, "%pOF Moxtet address 0x%x out of range\n",
 			nc, dev->idx);
 		ret = -EINVAL;
-		goto err_put;
+		goto err_clean;
 	}
 
 	dev->id = moxtet->modules[dev->idx];
@@ -237,7 +238,7 @@ of_register_moxtet_device(struct moxtet *moxtet, struct device_node *nc)
 		dev_err(moxtet->dev, "%pOF Moxtet address 0x%x is empty\n", nc,
 			dev->idx);
 		ret = -ENODEV;
-		goto err_put;
+		goto err_clean;
 	}
 
 	of_node_get(nc);
@@ -247,12 +248,15 @@ of_register_moxtet_device(struct moxtet *moxtet, struct device_node *nc)
 	if (ret) {
 		dev_err(moxtet->dev,
 			"Moxtet device register error for %pOF\n", nc);
+		of_node_clear_flag(nc, OF_POPULATED);
 		of_node_put(nc);
 		goto err_put;
 	}
 
 	return dev;
 
+err_clean:
+	of_node_clear_flag(nc, OF_POPULATED);
 err_put:
 	put_device(&dev->dev);
 	return ERR_PTR(ret);
@@ -260,7 +264,6 @@ of_register_moxtet_device(struct moxtet *moxtet, struct device_node *nc)
 
 static void of_register_moxtet_devices(struct moxtet *moxtet)
 {
-	struct moxtet_device *dev;
 	struct device_node *nc;
 
 	if (!moxtet->dev->of_node)
@@ -269,13 +272,7 @@ static void of_register_moxtet_devices(struct moxtet *moxtet)
 	for_each_available_child_of_node(moxtet->dev->of_node, nc) {
 		if (of_node_test_and_set_flag(nc, OF_POPULATED))
 			continue;
-		dev = of_register_moxtet_device(moxtet, nc);
-		if (IS_ERR(dev)) {
-			dev_warn(moxtet->dev,
-				 "Failed to create Moxtet device for %pOF\n",
-				 nc);
-			of_node_clear_flag(nc, OF_POPULATED);
-		}
+		of_register_moxtet_device(moxtet, nc);
 	}
 }
 
-- 
2.34.1