From: "Javier Carrasco" <javier.carrasco.cruz@gmail.com>
To: <sashiko-reviews@lists.linux.dev>,
"Javier Carrasco" <javier.carrasco.cruz@gmail.com>
Cc: <robh@kernel.org>, <devicetree@vger.kernel.org>, <conor+dt@kernel.org>
Subject: Re: [PATCH v5 4/4] iio: light: veml6031x00: add support for events and trigger
Date: Sat, 08 Aug 2026 08:35:08 +0200 [thread overview]
Message-ID: <DKJCQRNBH477.3C9CC4KCFAMNK@gmail.com> (raw)
In-Reply-To: <20260807150823.49A101F000E9@smtp.kernel.org>
On Fri Aug 7, 2026 at 5:08 PM CEST, sashiko-bot wrote:
> Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider:
> - [High] Unbalanced PM runtime usage counter causes an underflow on device unbind or probe error.
> - [High] Uninitialized padding in the local `scan` buffer leaks kernel stack memory to userspace.
> - [High] Spurious interrupts cause I2C reads while the device is runtime suspended.
> - [High] Initialization order and use-after-destroy race due to early IRQ/trigger registration.
> - [High] Triggered buffer is unconditionally registered on the no-IRQ path with a malformed channels array.
> - [Medium] Missing timestamp acquisition for nested trigger handler.
> - [Medium] Trigger disable sequence violates hardware constraints by clearing AF before AF_TRIG.
> --
>
> --- Patch [4]: [PATCH v5 4/4] iio: light: veml6031x00: add support for events and trigger ---
> commit aeccd415dcc79cfa9463cf8b5eec2292ee46dfab
> Author: Javier Carrasco <javier.carrasco.cruz@gmail.com>
>
> iio: light: veml6031x00: add support for events and trigger
>
> The device provides a shared interrupt line for to notify events and
> data ready, which can be used as a trigger. The interrupt line is not a
> requirement for the device to work. Implement variants for the cases
> whether the interrupt line is provided or not.
>
>> diff --git a/drivers/iio/light/veml6031x00.c b/drivers/iio/light/veml6031x00.c
>> index 0cccd40d729eb..e193f87e6740f 100644
>> --- a/drivers/iio/light/veml6031x00.c
>> +++ b/drivers/iio/light/veml6031x00.c
> [ ... ]
>> @@ -494,13 +686,205 @@ static int veml6031x00_write_raw_get_fmt(struct iio_dev *indio_dev,
> [ ... ]
>> +static irqreturn_t veml6031x00_interrupt(int irq, void *private)
>> +{
>> + struct iio_dev *iio = private;
>> + struct veml6031x00_data *data = iio_priv(iio);
>> + s64 timestamp;
>> + int regval, ret;
>> + bool trigger_poll;
>> +
>> + scoped_guard(mutex, &data->irq_lock) {
>> + ret = regmap_read(data->regmap, VEML6031X00_REG_INT, ®val);
>
> [Severity: High]
> If a spurious interrupt fires while both ev_en and trig_en are false,
> could this unconditionally read from the I2C bus while the device is
> runtime suspended?
>
> It looks like this might hit a powered-off device since it doesn't
> use pm_runtime_get_if_active() or check software state before
> the register read.
>
The I2C interface stays accessible even while the device is powered down,
so this read doesn't fail or have side effects in case of a spurious
interrupt.
>> + if (ret) {
>> + dev_dbg(regmap_get_device(data->regmap),
>> + "Failed to read interrupt register %d\n", ret);
>> + return IRQ_NONE;
>> + }
> [ ... ]
>> @@ -535,11 +919,78 @@ static int veml6031x00_buffer_postdisable(struct iio_dev *iio)
>> return 0;
>> }
>>
>> +static int veml6031x00_set_trigger_state(struct iio_trigger *trig, bool state)
>> +{
>> + struct iio_dev *iio = iio_trigger_get_drvdata(trig);
>> + struct veml6031x00_data *data = iio_priv(iio);
>> + int ret;
>> +
>> + guard(mutex)(&data->irq_lock);
>> +
>> + if (state == data->trig_en)
>> + return 0;
>> +
>> + ret = veml6031x00_set_interrupt(data, state);
>> + if (ret)
>> + return ret;
>> +
>> + /* The AF bit must be set before setting AF_TRIG */
>> + ret = regmap_update_bits(data->regmap, VEML6031X00_REG_CONF0,
>> + VEML6031X00_CONF0_AF,
>> + FIELD_PREP(VEML6031X00_CONF0_AF, state));
>
> [Severity: Medium]
> Since the AF bit must be set before setting AF_TRIG, does the
> disable sequence need to happen in reverse order?
>
> When state is false, this clears the AF bit first, creating a window
> where AF_TRIG is still active but AF is disabled.
>
Disabling AF is what actually turns off auto-force mode, so it should be
done in the current order.
>> + if (ret) {
>> + veml6031x00_set_interrupt(data, !state);
>> +
>> + return ret;
>> + }
>> +
>> + ret = regmap_update_bits(data->regmap, VEML6031X00_REG_CONF0,
>> + VEML6031X00_CONF0_AF_TRIG,
>> + FIELD_PREP(VEML6031X00_CONF0_AF_TRIG, state));
> [ ... ]
>> +static irqreturn_t veml6031x00_trig_handler(int irq, void *p)
>> +{
>> + struct iio_poll_func *pf = p;
>> + struct iio_dev *iio = pf->indio_dev;
>> + struct veml6031x00_data *data = iio_priv(iio);
>> + IIO_DECLARE_BUFFER_WITH_TS(__le16, scan, 2);
>
> [Severity: High]
> Could this leak uninitialized kernel stack memory to userspace?
>
> The IIO_DECLARE_BUFFER_WITH_TS macro allocates the buffer on the stack
> without zeroing the padding bytes between the channel data and the
> timestamp.
>
Already addressed in the reply to Sashiko's feedback about [3/4].
>> + unsigned int i = 0;
>> + int ch, ret;
>> +
>> + if (test_bit(VEML6031X00_SCAN_ALS, iio->active_scan_mask) &&
>> + test_bit(VEML6031X00_SCAN_IR, iio->active_scan_mask)) {
>> + ret = regmap_bulk_read(data->regmap,
>> + VEML6031X00_REG_ALS_L,
>> + scan,
>> + 2 * sizeof(*scan));
>> + if (ret)
>> + goto done;
>> + } else {
>> + iio_for_each_active_channel(iio, ch) {
>> + ret = regmap_bulk_read(data->regmap,
>> + iio->channels[ch].address,
>> + &scan[i++],
>> + sizeof(*scan));
>> + if (ret)
>> + goto done;
>> + }
>> + }
>> +
>> + iio_push_to_buffers_with_ts(iio, scan, sizeof(scan), pf->timestamp);
>
> [Severity: Medium]
> Since this trigger handler is executed synchronously from the interrupt
> handler via iio_trigger_poll_nested() bypassing the top-half
> iio_pollfunc_store_time(), will pf->timestamp always be zero here?
>
The timestamp is already captured in the interrupt handler. I will assign
it to pollfunc->timestamp before calling iio_trigger_poll_nested().
>> +
>> +done:
>> + iio_trigger_notify_done(iio->trig);
>> +
>> + return IRQ_HANDLED;
>> +}
> [ ... ]
>> @@ -636,15 +1142,29 @@ static int veml6031x00_probe(struct i2c_client *i2c)
>> "Failed to set regmap\n");
>>
>> iio->name = data->chip->name;
>> - iio->channels = veml6031x00_channels;
>> - iio->num_channels = ARRAY_SIZE(veml6031x00_channels);
>> iio->modes = INDIO_DIRECT_MODE;
>> - iio->info = &veml6031x00_info;
>> + if (i2c->irq) {
>> + iio->channels = veml6031x00_channels_irq;
>> + iio->num_channels = ARRAY_SIZE(veml6031x00_channels_irq);
>> + ret = veml6031x00_setup_irq(i2c, iio);
>
> [Severity: High]
> Does registering the IRQ and trigger here expose a race condition?
>
> veml6031x00_setup_irq() requests the threaded IRQ before devm_mutex_init()
> allocates data->irq_lock and veml6031x00_regfield_init() allocates
> data->rf.int_en. If an interrupt fires immediately, the handler will try
> to lock an uninitialized mutex.
>
> Additionally, since devres cleans up in reverse order, won't the mutex
> be destroyed before the IRQ is unregistered during unbind?
>
For V6: mutex_init and regfield_init moved before setup_irq().
>> + if (ret)
>> + return ret;
>> +
>> + iio->info = &veml6031x00_info;
>> + } else {
>> + iio->channels = veml6031x00_channels;
>
> [Severity: High]
> If the device does not provide an interrupt, it falls back to
> veml6031x00_channels which lacks scan_index and scan_type definitions.
>
> Will setting up a triggered buffer unconditionally at the end of probe
> cause IIO core undefined behavior if a user attaches an external
> sysfs/hrtimer trigger, since both channels would default to a
> scan_index of 0 and 0 storage bits?
>
Already addressed in the reply to Sashiko's feedback about [3/4].
>> + iio->num_channels = ARRAY_SIZE(veml6031x00_channels);
>> + iio->info = &veml6031x00_info_no_irq;
>> + }
>>
>> ret = devm_mutex_init(&i2c->dev, &data->scale_lock);
>> if (ret)
>> return ret;
>>
>> + ret = devm_mutex_init(&i2c->dev, &data->irq_lock);
>> + if (ret)
>> + return ret;
>> +
>> ret = veml6031x00_regfield_init(data);
>> if (ret)
>> return dev_err_probe(&i2c->dev, ret, "Failed to init regfield\n");
>> @@ -672,6 +1192,12 @@ static int veml6031x00_probe(struct i2c_client *i2c)
>> if (ret)
>> return dev_err_probe(&i2c->dev, ret, "Failed to get runtime PM\n");
>>
>
> [Severity: High]
> Could the devm_pm_runtime_get_noresume() call just above this hunk cause
> a usage counter underflow?
>
> The devres action will eventually call pm_runtime_put_noidle() during
> driver unbind. However, the driver also manually calls
> pm_runtime_put_autosuspend() at the end of veml6031x00_probe() to drop
> the initial reference.
>
> This double-put could underflow the usage counter to -1 and corrupt
> device power management. If the driver manually manages the initial
> reference, should it use the non-devm pm_runtime_get_noresume() variant?
>
Already addressed in the reply to Sashiko's feedback about [3/4].
Best regards,
Javier
prev parent reply other threads:[~2026-08-08 6:35 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-07 13:51 [PATCH v5 0/4] iio: light: add support for veml6031x00 ALS series Javier Carrasco
2026-08-07 13:51 ` [PATCH v5 1/4] dt-bindings: iio: light: veml6030: add " Javier Carrasco
2026-08-07 14:06 ` sashiko-bot
2026-08-07 14:34 ` Javier Carrasco
2026-08-07 15:33 ` Rob Herring (Arm)
2026-08-07 13:51 ` [PATCH v5 2/4] iio: light: add support for " Javier Carrasco
2026-08-07 14:19 ` sashiko-bot
2026-08-07 14:53 ` Javier Carrasco
2026-08-07 21:02 ` Uwe Kleine-König
2026-08-07 13:51 ` [PATCH v5 3/4] iio: light: veml6031x00: add support for triggered buffers Javier Carrasco
2026-08-07 14:49 ` sashiko-bot
2026-08-07 20:33 ` Javier Carrasco
2026-08-07 13:51 ` [PATCH v5 4/4] iio: light: veml6031x00: add support for events and trigger Javier Carrasco
2026-08-07 15:08 ` sashiko-bot
2026-08-08 6:35 ` Javier Carrasco [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=DKJCQRNBH477.3C9CC4KCFAMNK@gmail.com \
--to=javier.carrasco.cruz@gmail.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=robh@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox