From: sashiko-bot@kernel.org
To: "Songwei Chai" <songwei.chai@oss.qualcomm.com>
Cc: devicetree@vger.kernel.org, robh@kernel.org, conor+dt@kernel.org
Subject: Re: [PATCH v15 7/7] qcom-tgu: Add reset node to initialize
Date: Wed, 01 Jul 2026 07:06:08 +0000 [thread overview]
Message-ID: <20260701070609.5BD411F00A3A@smtp.kernel.org> (raw)
In-Reply-To: <20260701055529.445819-8-songwei.chai@oss.qualcomm.com>
Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider:
New issues:
- [High] A TOCTOU race condition in `reset_tgu_store` leads to a permanent PM reference leak.
Pre-existing issues:
- [High] A TOCTOU race condition in `enable_tgu_store(0)` causes a double `pm_runtime_put()`, leading to PM usage counter underflow.
- [High] A TOCTOU race condition in `enable_tgu_store(1)` allows multiple threads to enable the device concurrently, leaking PM references.
- [High] Missing `sysfs_remove_groups()` on the `tgu_probe()` error path leaves sysfs files accessible, leading to a NULL pointer dereference.
- [High] The `tgu_node_visible` function incorrectly modifies a shared global attribute name, corrupting the sysfs structure.
- [High] The PM runtime usage count is leaked if the device is unbound while enabled.
- [Medium] The function `tgu_dataset_show` reads shared array values without holding the required lock.
--
commit 609c4b01711040b0d5156593e5d5c7a06ebc7c31
Author: Songwei Chai <songwei.chai@oss.qualcomm.com>
qcom-tgu: Add reset node to initialize
Add reset node to initialize the value of
priority/condition_decode/condition_select/timer/counter nodes.
> diff --git a/drivers/hwtracing/qcom/tgu.c b/drivers/hwtracing/qcom/tgu.c
> index 6d5bf2621cb05..9fb51f2a912f9 100644
> --- a/drivers/hwtracing/qcom/tgu.c
> +++ b/drivers/hwtracing/qcom/tgu.c
[ ... ]
> @@ -420,8 +420,82 @@ static ssize_t enable_tgu_store(struct device *dev,
> }
> static DEVICE_ATTR_RW(enable_tgu);
>
> +/* reset_tgu_store - Reset Trace and Gating Unit (TGU) configuration. */
> +static ssize_t reset_tgu_store(struct device *dev,
> + struct device_attribute *attr, const char *buf,
> + size_t size)
> +{
> + struct tgu_drvdata *drvdata = dev_get_drvdata(dev);
> + struct value_table *vt = drvdata->value_table;
> + u32 *cond_decode = drvdata->value_table->condition_decode;
> + unsigned long value;
> + int i, j, ret;
> +
> + if (kstrtoul(buf, 0, &value) || value != 1)
> + return -EINVAL;
> +
> + spin_lock(&drvdata->lock);
> + if (!drvdata->enabled) {
> + spin_unlock(&drvdata->lock);
> + ret = pm_runtime_resume_and_get(drvdata->dev);
[Severity: High]
Does unlocking to get the PM reference introduce a TOCTOU race condition?
If a concurrent enable_tgu_store(1) enables the device and increments the
PM usage count before this thread reacquires the lock, reset_tgu_store()
will unconditionally disable the hardware and clear the enabled flag.
Since the device state is now disabled, would the PM reference acquired by
the concurrent enable_tgu_store(1) be permanently leaked?
> + if (ret)
> + return ret;
> + spin_lock(&drvdata->lock);
> + }
[ ... ]
This is a pre-existing issue, but does enable_tgu_store() have TOCTOU race
conditions?
drivers/hwtracing/qcom/tgu.c:enable_tgu_store() {
...
if (val) {
scoped_guard(spinlock, &drvdata->lock) {
if (drvdata->enabled)
return -EBUSY;
}
ret = pm_runtime_resume_and_get(dev);
...
} else {
scoped_guard(spinlock, &drvdata->lock) {
if (!drvdata->enabled)
return -EINVAL;
}
tgu_disable(dev);
pm_runtime_put(dev);
}
...
}
[Severity: High]
For enable_tgu_store(1), if two threads concurrently observe !drvdata->enabled
within the scoped guard, both will drop the lock and acquire PM references.
Both would then independently call tgu_enable(dev), setting the flag to true.
Would this increment the PM usage count multiple times, while disabling the
device only decrements it once?
[Severity: High]
For enable_tgu_store(0), if two threads concurrently verify
drvdata->enabled == true inside the scoped lock guard and then drop the lock,
the first thread calls tgu_disable(dev), sets the flag to false, and calls
pm_runtime_put(dev). The second thread calls tgu_disable(dev), which returns
early because the flag is now false, but then unconditionally calls
pm_runtime_put(dev). Would this double-put cause a PM usage counter underflow?
This is a pre-existing issue, but does tgu_probe() leave sysfs files
accessible if subsequent allocations fail?
drivers/hwtracing/qcom/tgu.c:tgu_probe() {
...
ret = sysfs_create_groups(&dev->kobj, tgu_attr_groups);
if (ret) {
...
}
drvdata->value_table =
devm_kzalloc(dev, sizeof(*drvdata->value_table), GFP_KERNEL);
if (!drvdata->value_table)
return -ENOMEM;
...
}
[Severity: High]
If devm_kzalloc() fails, the probe returns an error, and the driver core sets
drvdata to NULL. Because sysfs_remove_groups() is not called on this error
path, the sysfs attributes remain. If a user subsequently accesses these
dangling attributes, would dev_get_drvdata(dev) return NULL, causing a panic
when dereferencing drvdata?
This is a pre-existing issue, but does tgu_node_visible() incorrectly modify
a shared global attribute name?
drivers/hwtracing/qcom/tgu.c:tgu_node_visible() {
...
case TGU_CONDITION_SELECT:
/* 'default' register is at the end of 'select' region */
if (tgu_attr->reg_num == drvdata->num_condition_select - 1)
attr->name = "default";
...
}
[Severity: High]
The attributes in tgu_attr_groups appear to be statically allocated. Since
this dynamically executes attr->name = "default", does it destructively
overwrite the shared global attribute structure, permanently altering the name
for all TGU devices?
This is a pre-existing issue, but is the PM runtime usage count leaked if the
device is unbound while enabled?
drivers/hwtracing/qcom/tgu.c:tgu_remove() {
...
static void tgu_remove(struct amba_device *adev)
{
struct device *dev = &adev->dev;
sysfs_remove_groups(&dev->kobj, tgu_attr_groups);
tgu_disable(dev);
}
...
}
[Severity: High]
If the user enables the TGU via enable_tgu_store(1), a PM reference is
acquired. When the device is later unbound, tgu_remove() calls tgu_disable(),
which turns off the hardware and sets the enabled flag to false. However, it
fails to call pm_runtime_put() to balance the PM reference. Does this
permanently leak the PM reference?
This is a pre-existing issue, but does tgu_dataset_show() read shared array
values without holding the required lock?
drivers/hwtracing/qcom/tgu.c:tgu_dataset_show() {
...
case TGU_PRIORITY0:
case TGU_PRIORITY1:
case TGU_PRIORITY2:
case TGU_PRIORITY3:
return sysfs_emit(buf, "0x%x\n",
drvdata->value_table->priority[index]);
...
}
[Severity: Medium]
This function reads values from drvdata->value_table without acquiring
drvdata->lock. Since sysfs store operations can concurrently modify or
memset these arrays while holding the lock, does this expose a data race
where sysfs reads might observe partially written values?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260701055529.445819-1-songwei.chai@oss.qualcomm.com?part=7
prev parent reply other threads:[~2026-07-01 7:06 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-01 5:55 [PATCH v15 0/7] Provide support for Trigger Generation Unit Songwei Chai
2026-07-01 5:55 ` [PATCH v15 1/7] dt-bindings: arm: Add support for Qualcomm TGU trace Songwei Chai
2026-07-01 6:07 ` sashiko-bot
2026-07-01 5:55 ` [PATCH v15 2/7] qcom-tgu: Add TGU driver Songwei Chai
2026-07-01 6:17 ` sashiko-bot
2026-07-01 5:55 ` [PATCH v15 3/7] qcom-tgu: Add signal priority support Songwei Chai
2026-07-01 6:25 ` sashiko-bot
2026-07-01 5:55 ` [PATCH v15 4/7] qcom-tgu: Add TGU decode support Songwei Chai
2026-07-01 6:37 ` sashiko-bot
2026-07-01 5:55 ` [PATCH v15 5/7] qcom-tgu: Add support to configure next action Songwei Chai
2026-07-01 6:45 ` sashiko-bot
2026-07-01 5:55 ` [PATCH v15 6/7] qcom-tgu: Add timer/counter functionality for TGU Songwei Chai
2026-07-01 6:54 ` sashiko-bot
2026-07-01 5:55 ` [PATCH v15 7/7] qcom-tgu: Add reset node to initialize Songwei Chai
2026-07-01 7:06 ` sashiko-bot [this message]
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=20260701070609.5BD411F00A3A@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=robh@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=songwei.chai@oss.qualcomm.com \
/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.