From: sashiko-bot@kernel.org
To: "Javier Carrasco" <javier.carrasco.cruz@gmail.com>
Cc: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
devicetree@vger.kernel.org
Subject: Re: [PATCH v2 4/4] iio: light: add support for veml6031x00 ALS series
Date: Thu, 14 May 2026 09:29:29 +0000 [thread overview]
Message-ID: <20260514092929.D37E7C2BCB7@smtp.kernel.org> (raw)
In-Reply-To: <20260513-veml6031x00-v2-4-4703ca661a1d@gmail.com>
Thank you for your contribution! Sashiko AI review found 8 potential issue(s) to consider:
- [High] Race Condition and API Violation in `veml6031x00_write_raw`
- [High] Out-of-Bounds Array Access in Trigger Handler
- [High] PM Runtime Usage Counter Underflow and Race Condition in `veml6031x00_write_event_config`
- [High] TOCTOU Race and Lockless Hardware State Rollback in `veml6031x00_set_trigger_state`
- [High] Sensor Left in Hardware Shutdown During Initial Active PM State
- [Medium] PM Runtime Usage Counter Leak on Probe Error Paths
- [Medium] Negative Input Values Bypass Period Validation
- [Medium] `iio_device_claim_direct` Blocks Needlessly Due to Long Sleep in `veml6031x00_single_read`
--
commit a33cd1a810baeac2c7084228357077baf67cdd60
Author: Javier Carrasco <javier.carrasco.cruz@gmail.com>
iio: light: add support for veml6031x00 ALS series
These sensors provide two light channels (ALS and IR), I2C communication
and a multiplexed interrupt line to signal data ready and configurable
threshold alarms.
> diff --git a/drivers/iio/light/veml6031x00.c b/drivers/iio/light/veml6031x00.c
> new file mode 100644
> index 0000000000000..c7808768f45ad
> --- /dev/null
> +++ b/drivers/iio/light/veml6031x00.c
[ ... ]
> +static int veml6031x00_write_period(struct iio_dev *iio, int val)
> +{
> + struct veml6031x00_data *data = iio_priv(iio);
> +
> + if (val > 8 || hweight8(val) != 1)
> + return -EINVAL;
> +
> + return regmap_field_write(data->rf.pers, ffs(val) - 1);
> +}
Is it possible for negative values to bypass this validation?
If val is a negative number such as -128, val > 8 is false, and hweight8(-128)
checks the bottom 8 bits, which evaluates to exactly 1 bit set. This would
bypass the check and allow malformed inputs to be written to the hardware.
[ ... ]
> +static int veml6031x00_single_read(struct iio_dev *iio, enum iio_chan_type type,
> + int *val)
> +{
[ ... ]
> + ret = veml6031x00_get_it(data, &it_sec, &it_usec);
> + if (ret < 0)
> + goto put_autosuspend;
> +
> + /* integration time + 10 % to ensure completion */
> + fsleep((it_sec * MICRO) + it_usec + (it_usec / 10));
> +
> + if (!iio_device_claim_direct(iio)) {
> + ret = -EBUSY;
> + goto put_autosuspend;
> + }
Could iio_device_claim_direct() be called before sleeping?
Currently, if a triggered buffer is actively capturing data, this will sleep
for the entire integration delay (which could be up to 400ms) before returning
-EBUSY and rejecting the direct read.
[ ... ]
> +static int veml6031x00_write_raw(struct iio_dev *iio,
> + struct iio_chan_spec const *chan,
> + int val, int val2, long mask)
> +{
> + switch (mask) {
> + case IIO_CHAN_INFO_INT_TIME:
> + return veml6031x00_set_it(iio, val, val2);
> + case IIO_CHAN_INFO_SCALE:
> + return veml6031x00_set_scale(iio, val, val2);
> + default:
> + return -EINVAL;
> + }
> +}
Does this need to hold a lock or claim direct mode?
The helpers veml6031x00_set_it() and veml6031x00_set_scale() perform multiple
regmap operations.
Without holding a driver-level mutex or claiming direct mode with
iio_device_claim_direct_mode(), concurrent sysfs writes could interleave and
corrupt the configuration. This also allows userspace to alter hardware
settings while a triggered buffer is actively capturing data.
[ ... ]
> +static int veml6031x00_write_event_config(struct iio_dev *iio,
> + const struct iio_chan_spec *chan,
> + enum iio_event_type type,
> + enum iio_event_direction dir,
> + bool state)
> +{
> + struct veml6031x00_data *data = iio_priv(iio);
> + int ret;
> +
> + scoped_guard(mutex, &data->lock) {
> + /* avoid multiple increments/decrements from one source */
> + if (state == data->ev_en)
> + return 0;
> +
> + ret = veml6031x00_set_interrupt(data, state);
> + if (ret)
> + return ret;
> +
> + data->ev_en = state;
> + }
> +
> + if (state)
> + return pm_runtime_resume_and_get(data->dev);
> +
> + pm_runtime_put_autosuspend(data->dev);
> +
> + return 0;
> +}
Could this lead to a PM runtime usage counter underflow or a race condition?
If state is true and pm_runtime_resume_and_get() fails, the function returns
an error but leaves data->ev_en as true and the interrupt enabled. A
subsequent call to disable the event would unconditionally call
pm_runtime_put_autosuspend(), underflowing the usage counter.
Additionally, because the PM runtime calls are outside the mutex, concurrent
calls could execute the PM runtime updates out-of-order, leading to reference
count corruption.
[ ... ]
> +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;
> +
> + scoped_guard(mutex, &data->lock) {
> + if (state == data->trig_en)
> + return 0;
> +
> + ret = veml6031x00_set_interrupt(data, state);
> + if (ret)
> + return ret;
> + }
[ ... ]
> + ret = veml6031x00_set_af_trig(data, state);
> + if (ret)
> + goto err_clear_af;
> +
> + scoped_guard(mutex, &data->lock)
> + data->trig_en = state;
> +
> + return 0;
> +
> +err_clear_af:
> + regmap_update_bits(data->regmap, VEML6031X00_REG_CONF0,
> + VEML6031X00_CONF0_AF,
> + FIELD_PREP(VEML6031X00_CONF0_AF, !state));
> +err_disable_interrupt:
> + veml6031x00_set_interrupt(data, !state);
> + return ret;
> +}
Does this sequence create a race condition with the lock handling?
The function checks state == data->trig_en and increments an internal counter
in veml6031x00_set_interrupt() inside the first scoped_guard, but data->trig_en
isn't updated until the second scoped_guard. Concurrent callers could bypass
the state check before data->trig_en is updated.
Also, if an error occurs, the err_disable_interrupt path calls
veml6031x00_set_interrupt() outside the lock. This could race with other event
configurations and desynchronize the software state from the hardware 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);
> + int ch, ret, i = 0;
> + struct {
> + __le16 chans[2];
> + aligned_s64 timestamp;
> + } scan;
> +
> + memset(&scan, 0, sizeof(scan));
> +
> + if (*iio->active_scan_mask == VEML6031X00_ALL_CH_MASK) {
[ ... ]
> + } else {
> + iio_for_each_active_channel(iio, ch) {
> + ret = regmap_bulk_read(data->regmap,
> + iio->channels[ch].address,
> + &scan.chans[i++], 2);
> + if (ret)
> + goto done;
> + }
> + }
Can this loop overflow scan.chans[]?
If the user enables the IIO timestamp channel alongside ALS and IR, the active
scan mask includes the timestamp bit, so execution falls into the else branch.
The iio_for_each_active_channel() loop doesn't skip the timestamp channel, so
it would execute an I2C read into scan.chans[i++] when i reaches 2, overflowing
the 2-element array.
[ ... ]
> +static int veml6031x00_probe(struct i2c_client *i2c)
> +{
[ ... ]
> + ret = pm_runtime_set_active(dev);
> + if (ret < 0)
> + return dev_err_probe(dev, ret, "Failed to activate PM runtime\n");
> +
> + ret = devm_pm_runtime_enable(dev);
> + if (ret)
> + return dev_err_probe(dev, ret, "Failed to enable PM runtime\n");
> +
> + pm_runtime_get_noresume(dev);
> + pm_runtime_set_autosuspend_delay(dev, VEML6031X00_AUTOSUSPEND_MS);
> + pm_runtime_use_autosuspend(dev);
> +
> + ret = veml6031x00_validate_part_id(data);
> + if (ret)
> + return ret;
Should the sensor be powered on before marking it active?
The hardware powers up in a shutdown state, and veml6031x00_als_power_on() is
not called here before pm_runtime_set_active(). During the initial autosuspend
delay, reads will assume the device is awake and attempt to read from a
powered-down sensor.
Also, does this code leak the PM runtime reference on probe errors?
If an error occurs during veml6031x00_validate_part_id() or subsequent
initialization steps, the function returns without dropping the reference
acquired by pm_runtime_get_noresume(dev).
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260513-veml6031x00-v2-0-4703ca661a1d@gmail.com?part=4
prev parent reply other threads:[~2026-05-14 9:29 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-13 4:49 [PATCH v2 0/4] iio: light: add support for veml6031x00 ALS series Javier Carrasco
2026-05-13 4:49 ` [PATCH v2 1/4] iio: light: veml6030: remove unnecessary read of IT index Javier Carrasco
2026-05-13 16:59 ` Andy Shevchenko
2026-05-13 18:17 ` Javier Carrasco
2026-05-13 19:58 ` Andy Shevchenko
2026-05-14 7:54 ` sashiko-bot
2026-05-13 4:49 ` [PATCH v2 2/4] iio: light: veml6030: fix channel type when pushing events Javier Carrasco
2026-05-13 17:48 ` Andy Shevchenko
2026-05-13 18:13 ` Javier Carrasco
2026-05-13 20:02 ` Andy Shevchenko
2026-05-13 20:44 ` Javier Carrasco
2026-05-13 20:56 ` Andy Shevchenko
2026-05-14 8:08 ` sashiko-bot
2026-05-13 4:49 ` [PATCH v2 3/4] dt-bindings: iio: light: veml6030: add veml6031x00 ALS series Javier Carrasco
2026-05-13 4:49 ` [PATCH v2 4/4] iio: light: add support for " Javier Carrasco
[not found] ` <690B63AD-4429-4045-B413-29911ED7DA3D@gmail.com>
2026-05-13 16:36 ` Andy Shevchenko
2026-05-13 16:37 ` Andy Shevchenko
2026-05-13 16:56 ` Andy Shevchenko
2026-05-13 18:23 ` Javier Carrasco
2026-05-13 20:08 ` Andy Shevchenko
2026-05-14 9:29 ` 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=20260514092929.D37E7C2BCB7@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=javier.carrasco.cruz@gmail.com \
--cc=krzk+dt@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