[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