From: sashiko-bot@kernel.org
To: "Runyu Xiao" <runyu.xiao@seu.edu.cn>
Cc: linux-hwmon@vger.kernel.org
Subject: Re: [PATCH] hwmon: (occ) unregister hwmon device outside occ lock
Date: Wed, 17 Jun 2026 20:18:21 +0000 [thread overview]
Message-ID: <20260617201822.3B46E1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260617150859.741453-1-runyu.xiao@seu.edu.cn>
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
New issues:
- [High] Sysfs callbacks can initiate hardware polling after the device has been deactivated.
Pre-existing issues:
- [High] The patch fixes an ABBA deadlock for hwmon sysfs attributes but leaves an identical deadlock for the driver's own occ_sysfs attributes.
- [High] Unbounded memory leak when toggling the OCC active state via sysfs.
- [High] A NULL pointer dereference crash occurs during sysfs group creation if the hardware reports multiple capability sensors.
- [High] Malformed device responses can cause an out-of-bounds kernel memory read when parsing sensor data blocks.
--
commit c52f29d2e70bdddb1a59be767e0322ae3c29585d
Author: Runyu Xiao <runyu.xiao@seu.edu.cn>
hwmon: (occ) unregister hwmon device outside occ lock
Serialize hwmon registration and removal with a separate hwmon_lock.
Under that lock, detach occ->hwmon and update occ->active while occ->lock
is held so concurrent OCC state changes still see a stable state, then
drop occ->lock before calling hwmon_device_unregister().
Cc: stable@vger.kernel.org
Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn>
> diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c
> index 42cc6068bb08b..b8461da29e36f 100644
> --- a/drivers/hwmon/occ/common.c
> +++ b/drivers/hwmon/occ/common.c
> @@ -1105,11 +1105,16 @@ static void occ_parse_poll_response(struct occ *occ)
>
> int occ_active(struct occ *occ, bool active)
> {
> - int rc = mutex_lock_interruptible(&occ->lock);
> + struct device *hwmon = NULL;
> + int rc = mutex_lock_interruptible(&occ->hwmon_lock);
>
> if (rc)
> return rc;
>
> + rc = mutex_lock_interruptible(&occ->lock);
> + if (rc)
> + goto unlock_hwmon;
> +
[Severity: High]
This is a pre-existing issue, but can this cause an unbounded memory leak when
toggling the OCC active state via sysfs?
When the device is activated, occ_setup_sensor_attrs() unconditionally
allocates the sensor attribute arrays using devm_kzalloc(). Because devres
allocations are bound to the device's lifetime, the memory is not freed when
occ_active() is called with active set to false.
Will repeatedly writing '1' and '0' to the occ_active sysfs file continuously
allocate new memory and overwrite the pointers?
[Severity: High]
This is a pre-existing issue, but does the hardware reporting multiple
capability sensors cause a NULL pointer dereference during sysfs group
creation?
In occ_setup_sensor_attrs(), the driver expects sensors->caps.num_sensors
attributes and allocates array space accordingly, but it only populates the
first capability sensor because it uses an
if (sensors->caps.num_sensors >= 1) condition instead of a loop:
occ_setup_sensor_attrs() {
...
if (sensors->caps.num_sensors >= 1) {
snprintf(attr->name, sizeof(attr->name), "power%d_label", s);
...
}
Are the remaining attributes left zero-initialized, causing
sysfs_create_group() to read a NULL attr->name and crash?
[Severity: High]
This is a pre-existing issue, but can malformed device responses cause an
out-of-bounds kernel memory read when parsing sensor data blocks?
In occ_parse_poll_response(), the bounds check is performed after reading the
block header:
occ_parse_poll_response() {
...
offset = (block->header.num_sensors * block->header.sensor_length) +
sizeof(block->header);
size += offset;
if ((size + sizeof(*header)) >= OCC_RESP_DATA_BYTES) {
...
}
If the response buffer is almost full, will the next iteration read the block
header out of bounds?
Additionally, the driver trusts the hardware-provided sensor_length without
verifying it matches the C struct size. Could a malicious or faulty OCC
provide a large num_sensors and small sensor_length, passing the bounds
check but causing sysfs functions like occ_show_power_a0() to read arbitrary
out-of-bounds kernel memory?
[ ... ]
> @@ -1154,14 +1159,17 @@ int occ_active(struct occ *occ, bool active)
> goto unlock;
> }
>
> - if (occ->hwmon)
> - hwmon_device_unregister(occ->hwmon);
> + hwmon = occ->hwmon;
> occ->active = false;
> occ->hwmon = NULL;
> }
>
> unlock:
> mutex_unlock(&occ->lock);
> + if (hwmon)
> + hwmon_device_unregister(hwmon);
> +unlock_hwmon:
> + mutex_unlock(&occ->hwmon_lock);
> return rc;
> }
[Severity: High]
Can sysfs callbacks initiate hardware polling after the device has been
deactivated?
By moving hwmon_device_unregister() outside of occ->lock and occ->hwmon_lock,
pending hwmon sysfs callbacks that were waiting for occ->lock can execute
after occ->active is set to false.
Since functions like occ_update_response() do not verify occ->active inside
their critical sections:
occ_update_response() {
...
if (time_after(jiffies, occ->next_update)) {
rc = occ_poll(occ);
...
}
will they proceed to call occ_poll() and send hardware commands to the OCC
after it has been deactivated?
[ ... ]
> @@ -1190,15 +1199,22 @@ EXPORT_SYMBOL_GPL(occ_setup);
>
> void occ_shutdown(struct occ *occ)
> {
> + struct device *hwmon;
> +
> + mutex_lock(&occ->hwmon_lock);
> mutex_lock(&occ->lock);
>
> occ_shutdown_sysfs(occ);
[Severity: High]
This is a pre-existing issue, but does holding both occ->hwmon_lock and
occ->lock before draining sysfs callbacks in occ_shutdown_sysfs() create
a deadlock?
If occ_shutdown_sysfs() blocks in kernfs_drain() waiting for active sysfs
references to drop, and concurrently a read/write to driver attributes
(like occ_active_store()) holds a kernfs active reference and attempts to
acquire occ->lock or occ->hwmon_lock, will this result in an unresolvable
circular dependency during driver unbind/shutdown?
>
> - if (occ->hwmon)
> - hwmon_device_unregister(occ->hwmon);
> + hwmon = occ->hwmon;
> + occ->active = false;
> occ->hwmon = NULL;
>
> mutex_unlock(&occ->lock);
> +
> + if (hwmon)
> + hwmon_device_unregister(hwmon);
> + mutex_unlock(&occ->hwmon_lock);
> }
> EXPORT_SYMBOL_GPL(occ_shutdown);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260617150859.741453-1-runyu.xiao@seu.edu.cn?part=1
next prev parent reply other threads:[~2026-06-17 20:18 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-17 15:08 [PATCH] hwmon: (occ) unregister hwmon device outside occ lock Runyu Xiao
2026-06-17 20:18 ` sashiko-bot [this message]
2026-06-19 1:59 ` [PATCH v2] hwmon: (occ) unregister sysfs devices " Runyu Xiao
2026-06-19 2:16 ` sashiko-bot
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=20260617201822.3B46E1F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=linux-hwmon@vger.kernel.org \
--cc=runyu.xiao@seu.edu.cn \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox