[PATCH v14 2/8] i3c: master: Fix IBI request and free cleanup paths

Lakshay Piplani lakshay.piplani at nxp.com
Tue Jul 14 02:20:47 PDT 2026


i3c_dev_request_ibi_locked() allocates the generic IBI object and its
workqueue before calling the controller request_ibi() callback. If the
callback fails, destroy the workqueue before freeing the IBI object.

Also, a controller callback may clear dev->ibi while forwarding the request
or free operation to another controller. Avoid touching dev->ibi after the
callback if it has already been cleared.

This prevents a workqueue leak in the request failure path and avoids NULL
pointer dereference in the free path when the callback has already released
the IBI object.

Signed-off-by: Lakshay Piplani <lakshay.piplani at nxp.com>
Signed-off-by: Vikash Bansal <vikash.bansal at nxp.com>
Signed-off-by: Aman Kumar Pandey <aman.kumarpandey at nxp.com>

---
Changes in v14:
 - Destroy the allocated IBI workqueue when request_ibi() callback fails
 - Avoid touching dev->ibi after request/free callbacks if a forwarding
   controller callback has already cleared it
---
---
 drivers/i3c/master.c | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 2cb94face156..01c6e048485c 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -3499,8 +3499,18 @@ int i3c_dev_request_ibi_locked(struct i3c_dev_desc *dev,
 
 	dev->ibi = ibi;
 	ret = master->ops->request_ibi(dev, req);
-	if (ret) {
-		kfree(ibi);
+
+	/*
+	 * The controller callback may have already released and cleared dev->ibi
+	 * when the request is forwarded by a virtual controller. Only clean up the
+	 * IBI object if the callback left dev->ibi valid.
+	 */
+	if (ret && dev->ibi) {
+		/* Avoid leaking the workqueue allocated for this IBI request. */
+		if (dev->ibi->wq)
+			destroy_workqueue(dev->ibi->wq);
+
+		kfree(dev->ibi);
 		dev->ibi = NULL;
 	}
 
@@ -3540,6 +3550,13 @@ void i3c_dev_free_ibi_locked(struct i3c_dev_desc *dev)
 
 	master->ops->free_ibi(dev);
 
+	/*
+	 * The controller callback may have already released dev->ibi, for example
+	 * when the request was forwarded by a virtual controller.
+	 */
+	if (!dev->ibi)
+		return;
+
 	if (dev->ibi->wq) {
 		destroy_workqueue(dev->ibi->wq);
 		dev->ibi->wq = NULL;
-- 
2.25.1




More information about the linux-i3c mailing list