All of lore.kernel.org
 help / color / mirror / Atom feed
From: Adrian Hunter <adrian.hunter@intel.com>
To: Frank Li <Frank.li@oss.nxp.com>, <sashiko-reviews@lists.linux.dev>
Cc: <Frank.Li@kernel.org>, <linux-pci@vger.kernel.org>,
	<linux-i3c@lists.infradead.org>,
	Alexandre Belloni <alexandre.belloni@bootlin.com>
Subject: Re: [PATCH V2 1/8] i3c: master: Fix recursive locking during device registration
Date: Mon, 3 Aug 2026 17:00:21 +0300	[thread overview]
Message-ID: <cd96321c-3ca2-4b11-95e1-17d0a411ce8f@intel.com> (raw)
In-Reply-To: <amkJi8010zem-2O9@lizhi-Precision-Tower-5810>

On 28/07/2026 22:56, Frank Li wrote:
> On Tue, Jul 28, 2026 at 04:19:35PM +0000, sashiko-bot@kernel.org wrote:
>> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
>>
>> New issues:
>> - [High] Dropping the bus maintenance lock around device_register() exposes i3c_device_uevent() and driver probe functions to a Use-After-Free if a concurrent DAA replaces the device.
>>
>> Pre-existing issues:
>> - [High] i3c_device_uevent() leaks uninitialized stack memory to userspace when i3cdev->desc is NULL.
>> --
>>
>> --- Patch [1]: [PATCH V2 1/8] i3c: master: Fix recursive locking during device registration ---
>> commit 33a4dcd6c5626faef95bc7cd02ec4c56c6710c78
>> Author: Adrian Hunter <adrian.hunter@intel.com>
>>
>> i3c: master: Fix recursive locking during device registration
>>
>> This commit separates device creation from registration to fix a recursive
>> locking issue. It drops the bus maintenance lock around device_register()
>> to prevent deadlocks when probe callbacks invoke I3C helpers.
>>
>> diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
>> index fd3e79d10c840..874f6e11b296d 100644
>> --- a/drivers/i3c/master.c
>> +++ b/drivers/i3c/master.c
>> [ ... ]
>>> @@ -1999,25 +2008,37 @@ i3c_master_register_new_i3c_devs(struct i3c_master_controller *master)
>>>  		if (desc->boardinfo)
>>>  			desc->dev->dev.of_node = desc->boardinfo->of_node;
>>>
>>> -		ret = device_register(&desc->dev->dev);
>>> -		if (ret) {
>>> -			dev_err(&master->dev,
>>> -				"Failed to add I3C device (err = %d)\n", ret);
>>> -			desc->dev->desc = NULL;
>>> -			put_device(&desc->dev->dev);
>>> -			desc->dev = NULL;
>>> -		}
>>> +		list_add_tail(&desc->dev->node, &i3c_unreg_devs);
>>> +	}
>>> +
>>> +	i3c_bus_maintenance_unlock(&master->bus);
>>> +
>>> +	list_for_each_entry_safe(i3cdev, tmp, &i3c_unreg_devs, node) {
>>> +		ret = device_register(&i3cdev->dev);
>>
>> [Severity: High]
>> Does dropping the maintenance lock around device_register() expose
>> i3c_device_uevent() and driver probes to a use-after-free?
> 
> look like make sense.

Yes, but it is not new.  A plain sysfs read like:

	cat /sys/bus/i3c/devices/<bus.id>-<pid>/uevent

will invoke i3c_device_uevent() without any lock.  It has been that
way since commit 6cf7b65f7029 ("i3c: Use i3cdev->desc->info instead
of calling i3c_device_get_info() to avoid deadlock")

After this patch it should now be possible to take a lock in
i3c_device_uevent(), or alternatively, put a copy of pid and dcr on
struct i3c_device for use by i3c_device_uevent() so no lock is needed.

In any case, it is a separate fix.

> 
> Frank
> 
>>
>> If a concurrent I3C hot-join event or a sysfs write to do_daa occurs while
>> device_register() is running without the lock,
>> __i3c_master_add_i3c_dev_locked() could find a duplicate PID:
>>
>> __i3c_master_add_i3c_dev_locked() {
>>         olddev = i3c_master_search_i3c_dev_duplicate(newdev);
>>         if (olddev) {
>>                 newdev->dev = olddev->dev;
>>                 if (newdev->dev)
>>                         newdev->dev->desc = newdev;
>>                 ...
>>                 i3c_master_detach_i3c_dev(olddev);
>>                 i3c_master_free_i3c_dev(olddev);
>>         }
>> }
>>
>> Meanwhile, device_register() triggers a KOBJ_ADD uevent. i3c_device_uevent()
>> reads i3cdev->desc locklessly:
>>
>> i3c_device_uevent() {
>>         if (i3cdev->desc)
>>                 devinfo = i3cdev->desc->info;
>> }
>>
>> Could this lead to i3c_device_uevent() or driver probe functions dereferencing
>> the old descriptor while it is being freed?
>>
>>> +		if (ret)
>>> +			dev_err(&master->dev, "Failed to add I3C device (err = %d)\n", ret);
>>> +		else
>>> +			list_del_init(&i3cdev->node);
>>> +	}
>>> +
>>> +	i3c_bus_maintenance_lock(&master->bus);
>>> +
>>> +	list_for_each_entry_safe(i3cdev, tmp, &i3c_unreg_devs, node) {
>>> +		list_del(&i3cdev->node);
>>> +		desc = i3cdev->desc;
>>> +		i3cdev->desc = NULL;
>>
>> [Severity: High]
>> This is a pre-existing issue, but does setting i3cdev->desc to NULL before
>> unregistration or cleanup lead to leaking uninitialized stack memory in
>> i3c_device_uevent()?
>>
>> When a device is unregistered (or if registration fails and triggers a uevent),
>> i3cdev->desc is set to NULL. This bypasses the initialization of devinfo
>> in i3c_device_uevent():
>>
>> i3c_device_uevent() {
>>         struct i3c_device_info devinfo;
>>         u16 manuf, part, ext;
>>
>>         if (i3cdev->desc)
>>                 devinfo = i3cdev->desc->info;
>>
>>         manuf = I3C_PID_MANUF_ID(devinfo.pid);
>>         ...
>>         return add_uevent_var(env, "MODALIAS=i3c:dcr%02Xmanuf%04X",
>>                               devinfo.dcr, manuf);
>> }
>>
>> Since devinfo is uninitialized on the stack when desc is NULL, could this
>> broadcast uninitialized kernel stack data to userspace processes listening
>> to netlink uevents?
>>
>>> +		put_device(&i3cdev->dev);
>>> +		desc->dev = NULL;
>>>  	}
>>> +
>>> +	i3c_bus_maintenance_unlock(&master->bus);
>>>  }
>>
>> --
>> Sashiko AI review · https://sashiko.dev/#/patchset/20260728155308.142713-1-adrian.hunter@intel.com?part=1


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

WARNING: multiple messages have this Message-ID (diff)
From: Adrian Hunter <adrian.hunter@intel.com>
To: Frank Li <Frank.li@oss.nxp.com>, <sashiko-reviews@lists.linux.dev>
Cc: <Frank.Li@kernel.org>, <linux-pci@vger.kernel.org>,
	<linux-i3c@lists.infradead.org>,
	Alexandre Belloni <alexandre.belloni@bootlin.com>
Subject: Re: [PATCH V2 1/8] i3c: master: Fix recursive locking during device registration
Date: Mon, 3 Aug 2026 17:00:21 +0300	[thread overview]
Message-ID: <cd96321c-3ca2-4b11-95e1-17d0a411ce8f@intel.com> (raw)
In-Reply-To: <amkJi8010zem-2O9@lizhi-Precision-Tower-5810>

On 28/07/2026 22:56, Frank Li wrote:
> On Tue, Jul 28, 2026 at 04:19:35PM +0000, sashiko-bot@kernel.org wrote:
>> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
>>
>> New issues:
>> - [High] Dropping the bus maintenance lock around device_register() exposes i3c_device_uevent() and driver probe functions to a Use-After-Free if a concurrent DAA replaces the device.
>>
>> Pre-existing issues:
>> - [High] i3c_device_uevent() leaks uninitialized stack memory to userspace when i3cdev->desc is NULL.
>> --
>>
>> --- Patch [1]: [PATCH V2 1/8] i3c: master: Fix recursive locking during device registration ---
>> commit 33a4dcd6c5626faef95bc7cd02ec4c56c6710c78
>> Author: Adrian Hunter <adrian.hunter@intel.com>
>>
>> i3c: master: Fix recursive locking during device registration
>>
>> This commit separates device creation from registration to fix a recursive
>> locking issue. It drops the bus maintenance lock around device_register()
>> to prevent deadlocks when probe callbacks invoke I3C helpers.
>>
>> diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
>> index fd3e79d10c840..874f6e11b296d 100644
>> --- a/drivers/i3c/master.c
>> +++ b/drivers/i3c/master.c
>> [ ... ]
>>> @@ -1999,25 +2008,37 @@ i3c_master_register_new_i3c_devs(struct i3c_master_controller *master)
>>>  		if (desc->boardinfo)
>>>  			desc->dev->dev.of_node = desc->boardinfo->of_node;
>>>
>>> -		ret = device_register(&desc->dev->dev);
>>> -		if (ret) {
>>> -			dev_err(&master->dev,
>>> -				"Failed to add I3C device (err = %d)\n", ret);
>>> -			desc->dev->desc = NULL;
>>> -			put_device(&desc->dev->dev);
>>> -			desc->dev = NULL;
>>> -		}
>>> +		list_add_tail(&desc->dev->node, &i3c_unreg_devs);
>>> +	}
>>> +
>>> +	i3c_bus_maintenance_unlock(&master->bus);
>>> +
>>> +	list_for_each_entry_safe(i3cdev, tmp, &i3c_unreg_devs, node) {
>>> +		ret = device_register(&i3cdev->dev);
>>
>> [Severity: High]
>> Does dropping the maintenance lock around device_register() expose
>> i3c_device_uevent() and driver probes to a use-after-free?
> 
> look like make sense.

Yes, but it is not new.  A plain sysfs read like:

	cat /sys/bus/i3c/devices/<bus.id>-<pid>/uevent

will invoke i3c_device_uevent() without any lock.  It has been that
way since commit 6cf7b65f7029 ("i3c: Use i3cdev->desc->info instead
of calling i3c_device_get_info() to avoid deadlock")

After this patch it should now be possible to take a lock in
i3c_device_uevent(), or alternatively, put a copy of pid and dcr on
struct i3c_device for use by i3c_device_uevent() so no lock is needed.

In any case, it is a separate fix.

> 
> Frank
> 
>>
>> If a concurrent I3C hot-join event or a sysfs write to do_daa occurs while
>> device_register() is running without the lock,
>> __i3c_master_add_i3c_dev_locked() could find a duplicate PID:
>>
>> __i3c_master_add_i3c_dev_locked() {
>>         olddev = i3c_master_search_i3c_dev_duplicate(newdev);
>>         if (olddev) {
>>                 newdev->dev = olddev->dev;
>>                 if (newdev->dev)
>>                         newdev->dev->desc = newdev;
>>                 ...
>>                 i3c_master_detach_i3c_dev(olddev);
>>                 i3c_master_free_i3c_dev(olddev);
>>         }
>> }
>>
>> Meanwhile, device_register() triggers a KOBJ_ADD uevent. i3c_device_uevent()
>> reads i3cdev->desc locklessly:
>>
>> i3c_device_uevent() {
>>         if (i3cdev->desc)
>>                 devinfo = i3cdev->desc->info;
>> }
>>
>> Could this lead to i3c_device_uevent() or driver probe functions dereferencing
>> the old descriptor while it is being freed?
>>
>>> +		if (ret)
>>> +			dev_err(&master->dev, "Failed to add I3C device (err = %d)\n", ret);
>>> +		else
>>> +			list_del_init(&i3cdev->node);
>>> +	}
>>> +
>>> +	i3c_bus_maintenance_lock(&master->bus);
>>> +
>>> +	list_for_each_entry_safe(i3cdev, tmp, &i3c_unreg_devs, node) {
>>> +		list_del(&i3cdev->node);
>>> +		desc = i3cdev->desc;
>>> +		i3cdev->desc = NULL;
>>
>> [Severity: High]
>> This is a pre-existing issue, but does setting i3cdev->desc to NULL before
>> unregistration or cleanup lead to leaking uninitialized stack memory in
>> i3c_device_uevent()?
>>
>> When a device is unregistered (or if registration fails and triggers a uevent),
>> i3cdev->desc is set to NULL. This bypasses the initialization of devinfo
>> in i3c_device_uevent():
>>
>> i3c_device_uevent() {
>>         struct i3c_device_info devinfo;
>>         u16 manuf, part, ext;
>>
>>         if (i3cdev->desc)
>>                 devinfo = i3cdev->desc->info;
>>
>>         manuf = I3C_PID_MANUF_ID(devinfo.pid);
>>         ...
>>         return add_uevent_var(env, "MODALIAS=i3c:dcr%02Xmanuf%04X",
>>                               devinfo.dcr, manuf);
>> }
>>
>> Since devinfo is uninitialized on the stack when desc is NULL, could this
>> broadcast uninitialized kernel stack data to userspace processes listening
>> to netlink uevents?
>>
>>> +		put_device(&i3cdev->dev);
>>> +		desc->dev = NULL;
>>>  	}
>>> +
>>> +	i3c_bus_maintenance_unlock(&master->bus);
>>>  }
>>
>> --
>> Sashiko AI review · https://sashiko.dev/#/patchset/20260728155308.142713-1-adrian.hunter@intel.com?part=1


  reply	other threads:[~2026-08-03 14:00 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-28 15:53 [PATCH V2 0/8] i3c: Support IBI-based system wakeup Adrian Hunter
2026-07-28 15:53 ` Adrian Hunter
2026-07-28 15:53 ` [PATCH V2 1/8] i3c: master: Fix recursive locking during device registration Adrian Hunter
2026-07-28 15:53   ` Adrian Hunter
2026-07-28 16:19   ` sashiko-bot
2026-07-28 16:19     ` sashiko-bot
2026-07-28 19:56     ` Frank Li
2026-07-28 19:56       ` Frank Li
2026-08-03 14:00       ` Adrian Hunter [this message]
2026-08-03 14:00         ` Adrian Hunter
2026-07-28 15:53 ` [PATCH V2 2/8] i3c: master: Support IBI-based wakeup capability Adrian Hunter
2026-07-28 15:53   ` Adrian Hunter
2026-07-28 16:32   ` sashiko-bot
2026-07-28 16:32     ` sashiko-bot
2026-07-28 15:53 ` [PATCH V2 3/8] i3c: master: Report wakeup events for IBIs Adrian Hunter
2026-07-28 15:53   ` Adrian Hunter
2026-07-28 16:47   ` sashiko-bot
2026-07-28 16:47     ` sashiko-bot
2026-08-03 14:22     ` Adrian Hunter
2026-08-03 14:22       ` Adrian Hunter
2026-07-28 15:53 ` [PATCH V2 4/8] i3c: master: Add helper to query bus wakeup requirements Adrian Hunter
2026-07-28 15:53   ` Adrian Hunter
2026-07-28 16:57   ` sashiko-bot
2026-07-28 16:57     ` sashiko-bot
2026-07-28 20:03   ` Frank Li
2026-07-28 20:03     ` Frank Li
2026-08-03 14:48     ` Adrian Hunter
2026-08-03 14:48       ` Adrian Hunter
2026-07-28 15:53 ` [PATCH V2 5/8] i3c: master: Reject IBI requests from non-IBI-capable devices Adrian Hunter
2026-07-28 15:53   ` Adrian Hunter
2026-07-28 17:06   ` sashiko-bot
2026-07-28 17:06     ` sashiko-bot
2026-07-28 20:05   ` Frank Li
2026-07-28 20:05     ` Frank Li
2026-07-28 15:53 ` [PATCH V2 6/8] i3c: mipi-i3c-hci-pci: Propagate I3C wakeup requirements to PCI Adrian Hunter
2026-07-28 15:53   ` Adrian Hunter
2026-07-28 17:18   ` sashiko-bot
2026-07-28 17:18     ` sashiko-bot
2026-08-03 15:51     ` Adrian Hunter
2026-08-03 15:51       ` Adrian Hunter
2026-07-28 15:53 ` [PATCH V2 7/8] i3c: mipi-i3c-hci: Factor out i3c_hci_sysdev() Adrian Hunter
2026-07-28 15:53   ` Adrian Hunter
2026-07-28 17:22   ` sashiko-bot
2026-07-28 17:22     ` sashiko-bot
2026-07-28 20:10   ` Frank Li
2026-07-28 20:10     ` Frank Li
2026-08-03 15:57     ` Adrian Hunter
2026-08-03 15:57       ` Adrian Hunter
2026-07-28 15:53 ` [PATCH V2 8/8] i3c: mipi-i3c-hci: Advertise IBI wakeup capability Adrian Hunter
2026-07-28 15:53   ` Adrian Hunter
2026-07-28 17:25   ` sashiko-bot
2026-07-28 17:25     ` sashiko-bot
2026-07-28 20:12   ` Frank Li
2026-07-28 20:12     ` Frank Li

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=cd96321c-3ca2-4b11-95e1-17d0a411ce8f@intel.com \
    --to=adrian.hunter@intel.com \
    --cc=Frank.Li@kernel.org \
    --cc=Frank.li@oss.nxp.com \
    --cc=alexandre.belloni@bootlin.com \
    --cc=linux-i3c@lists.infradead.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.