]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
i3c: dw: Fix memory leak in dw_i3c_master_i3c_xfers()
authorFelix Gu <ustc.gu@gmail.com>
Sat, 4 Apr 2026 10:32:30 +0000 (18:32 +0800)
committerAlexandre Belloni <alexandre.belloni@bootlin.com>
Sun, 12 Apr 2026 14:52:32 +0000 (16:52 +0200)
The dw_i3c_master_i3c_xfers() function allocates memory for the xfer
structure using dw_i3c_master_alloc_xfer(). If pm_runtime_resume_and_get()
fails, the function returns without freeing the allocated xfer, resulting
in a memory leak.

Since dw_i3c_master_free_xfer() is a thin wrapper around kfree(), use
the __free(kfree) cleanup attribute to handle the free automatically on
all exit paths.

Fixes: 62fe9d06f570 ("i3c: dw: Add power management support")
Signed-off-by: Felix Gu <ustc.gu@gmail.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20260404-dw-i3c-2-v3-1-8f7d146549c1@gmail.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
drivers/i3c/master/dw-i3c-master.c

index b87073d2f8afaf84febdca2a072f02f5a2653072..259e4f5276655a47b3afe87d8c733a6b6e8f281d 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <linux/bitfield.h>
 #include <linux/bitops.h>
+#include <linux/cleanup.h>
 #include <linux/clk.h>
 #include <linux/completion.h>
 #include <linux/err.h>
@@ -924,7 +925,6 @@ static int dw_i3c_master_i3c_xfers(struct i3c_dev_desc *dev,
        struct i3c_master_controller *m = i3c_dev_get_master(dev);
        struct dw_i3c_master *master = to_dw_i3c_master(m);
        unsigned int nrxwords = 0, ntxwords = 0;
-       struct dw_i3c_xfer *xfer;
        int i, ret = 0;
 
        if (!i3c_nxfers)
@@ -944,7 +944,7 @@ static int dw_i3c_master_i3c_xfers(struct i3c_dev_desc *dev,
            nrxwords > master->caps.datafifodepth)
                return -EOPNOTSUPP;
 
-       xfer = dw_i3c_master_alloc_xfer(master, i3c_nxfers);
+       struct dw_i3c_xfer *xfer __free(kfree) = dw_i3c_master_alloc_xfer(master, i3c_nxfers);
        if (!xfer)
                return -ENOMEM;
 
@@ -995,7 +995,6 @@ static int dw_i3c_master_i3c_xfers(struct i3c_dev_desc *dev,
        }
 
        ret = xfer->ret;
-       dw_i3c_master_free_xfer(xfer);
 
        pm_runtime_put_autosuspend(master->dev);
        return ret;