[PATCH V4 04/14] i3c: master: Fix use-after-free of master->this
Frank Li
Frank.li at oss.nxp.com
Thu Aug 6 11:30:17 PDT 2026
On Thu, Aug 06, 2026 at 04:18:47PM +0300, Adrian Hunter wrote:
> sysfs attribute callbacks for the master controller device dereference
> master->this. However, master->this is freed in
> i3c_master_detach_free_devs() before the master device itself is
> released.
>
> As a result, sysfs accesses can dereference a freed master->this
> pointer, leading to a use-after-free.
>
> Keep master->this alive until i3c_masterdev_release(), which is called
> after the master device and its sysfs state are being torn down. Do not
> free master->this as part of the normal device detach path.
>
> On the error path in i3c_master_set_info(), reset master->this and
> bus.cur_master to NULL before freeing the allocated device.
>
> Fixes: 3a379bbcea0a ("i3c: Add core I3C infrastructure")
> Cc: stable at vger.kernel.org
> Signed-off-by: Adrian Hunter <adrian.hunter at intel.com>
> ---
Reviewed-by: Frank Li <Frank.Li at nxp.com>
>
>
> Changes in V4:
>
> Also reset master->this and bus.cur_master to NULL on the
> i3c_master_set_info() error path before freeing the allocated
> device. Tidied up the commit message wording.
>
> Changes in V3:
>
> New patch
>
>
> drivers/i3c/master.c | 17 +++++++++++------
> 1 file changed, 11 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
> index abb582645a2e..2357874bb9d6 100644
> --- a/drivers/i3c/master.c
> +++ b/drivers/i3c/master.c
> @@ -842,6 +842,11 @@ static struct attribute *i3c_masterdev_attrs[] = {
> };
> ATTRIBUTE_GROUPS(i3c_masterdev);
>
> +static void i3c_master_free_i3c_dev(struct i3c_dev_desc *dev)
> +{
> + kfree(dev);
> +}
> +
> static void i3c_masterdev_release(struct device *dev)
> {
> struct i3c_master_controller *master = dev_to_i3cmaster(dev);
> @@ -854,6 +859,8 @@ static void i3c_masterdev_release(struct device *dev)
> i3c_bus_cleanup(bus);
>
> fwnode_handle_put(dev->fwnode);
> +
> + i3c_master_free_i3c_dev(master->this);
> }
>
> static const struct device_type i3c_masterdev_type = {
> @@ -1125,11 +1132,6 @@ static void i3c_device_release(struct device *dev)
> kfree(i3cdev);
> }
>
> -static void i3c_master_free_i3c_dev(struct i3c_dev_desc *dev)
> -{
> - kfree(dev);
> -}
> -
> static struct i3c_dev_desc *
> i3c_master_alloc_i3c_dev(struct i3c_master_controller *master,
> const struct i3c_device_info *info)
> @@ -2266,6 +2268,8 @@ int i3c_master_set_info(struct i3c_master_controller *master,
> return 0;
>
> err_free_dev:
> + master->bus.cur_master = NULL;
> + master->this = NULL;
> i3c_master_free_i3c_dev(i3cdev);
>
> return ret;
> @@ -2286,7 +2290,8 @@ static void i3c_master_detach_free_devs(struct i3c_master_controller *master)
> i3cdev->boardinfo->init_dyn_addr,
> I3C_ADDR_SLOT_FREE);
>
> - i3c_master_free_i3c_dev(i3cdev);
> + if (i3cdev != master->this)
> + i3c_master_free_i3c_dev(i3cdev);
> }
>
> list_for_each_entry_safe(i2cdev, i2ctmp, &master->bus.devs.i2c,
> --
> 2.53.0
>
More information about the linux-i3c
mailing list