All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
Cc: robh@kernel.org, conor+dt@kernel.org, devicetree@vger.kernel.org
Subject: Re: [PATCH 4/4] iio: adc: ti-ads112c14: add measurement channel support
Date: Mon, 15 Jun 2026 22:13:17 +0000	[thread overview]
Message-ID: <20260615221317.9FFDA1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260615-iio-adc-ti-ads122c14-v1-4-e6bdadf7cb2b@baylibre.com>

Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:

New issues:
- [Critical] Heap buffer overflow in `ads112c14_populate_tables` due to incorrectly incremented `data->num_measurements`.
- [High] Incorrect error check for `devm_regulator_get_enable_read_voltage` causes valid probe successes to fail.
- [High] Uninitialized variable dereference in `ads112c14_read_raw()` for system monitor channels.
- [High] Integer overflow in `ads112c14_populate_scale_available()` breaks scaling factor calculation on 32-bit platforms.

Pre-existing issues:
- [High] Probe exits early and silently fails to register the IIO device if the reset command succeeds.
- [High] Short reads from I2C block reads leak uninitialized stack memory.
--

commit 6b05c003c593f091ad7d3f52a3dc20d0fab7fc26
Author: David Lechner (TI) <dlechner@baylibre.com>

iio: adc: ti-ads112c14: add measurement channel support

This patch adds support for parsing devicetree properties to dynamically
create measurement channels. It also adds the required algorithms and state
to do direct reads on these channels.

> diff --git a/drivers/iio/adc/ti-ads112c14.c b/drivers/iio/adc/ti-ads112c14.c
> index 202a449b4234f..d1297445025f7 100644
> --- a/drivers/iio/adc/ti-ads112c14.c
> +++ b/drivers/iio/adc/ti-ads112c14.c
[ ... ]
> @@ -383,7 +512,8 @@ static int ads112c14_read_raw(struct iio_dev *indio_dev,
>  			return -EINVAL;
>  		}

[Severity: High]
This isn't a bug introduced by this patch, but can a short read from
ads112c14_single_conversion() leak uninitialized stack memory?

If i2c_smbus_read_i2c_block_data() returns fewer bytes than requested
(e.g., 1 instead of 3), the return value is a positive integer. The check
`if (ret < 0)` earlier in ads112c14_read_raw() passes, and extracting the
value will read uninitialized bytes from the stack-allocated buffer.

>  
> -		*val = sign_extend32(*val, fsr_bits);
> +		if (!measurement || measurement->bipolar)

[Severity: High]
Can `measurement` be uninitialized when dereferenced here?

If the requested channel is a system monitor channel (`chan->channel >= 100`),
the `measurement` pointer is left uninitialized at the start of
ads112c14_read_raw(). It is then evaluated in this condition, which could
lead to undefined behavior.

> +			*val = sign_extend32(*val, fsr_bits);
>  
>  		return IIO_VAL_INT;
>  	}
[ ... ]
> @@ -519,26 +687,187 @@ static const struct iio_info ads112c14_info = {
>  	.read_label = ads112c14_read_label,
>  };
>  
> +static int ads112c14_parse_channels(struct iio_dev *indio_dev,
> +				    bool *need_avdd_ref, bool *need_ext_ref)
> +{
[ ... ]
> +	data->num_measurements = device_get_named_child_node_count(dev, "channel");
> +
> +	data->measurements = devm_kcalloc(dev, data->num_measurements,
> +					  sizeof(*data->measurements), GFP_KERNEL);
> +	if (!data->measurements)
> +		return -ENOMEM;
> +
> +	data->num_measurements += ARRAY_SIZE(ads112c14_sys_mon_channels);

[Severity: Critical]
Does this incorrectly inflate the measurement count?

By incrementing `data->num_measurements` by the size of the system monitor
channels here, the boundary for the measurements array becomes too large.
Later in ads112c14_populate_tables(), looping over `data->num_measurements`
will access `data->measurements` out-of-bounds, potentially corrupting
adjacent heap memory.

> +
> +	channels = devm_kcalloc(dev, data->num_measurements +
> +				ARRAY_SIZE(ads112c14_sys_mon_channels),
> +				sizeof(*channels), GFP_KERNEL);
[ ... ]
> +static void ads112c14_populate_scale_available(int scale_avail[][2],
> +					       u32 vref_uV, u32 fsr_bits)
> +{
> +	for (u32 i = 0; i < ARRAY_SIZE(ads112c14_pga_gains_x10); i++) {
> +		int *entry = scale_avail[i];
> +		u32 gain_x10 = ads112c14_pga_gains_x10[i];
> +
> +		entry[0] = div_u64_rem(div64_u64((u64)(NANO * 10 /
> +						       (MICRO / MILLI)) * vref_uV,

[Severity: High]
Does this calculation overflow on 32-bit platforms?

`NANO` is defined as a 32-bit unsigned long, so multiplying it by 10 overflows
before the cast to `u64`. This truncates the value used to compute the scale
factor, leading to incorrect scaling values on 32-bit architectures.

> +						 (u64)gain_x10 * BIT(fsr_bits)),
> +				       NANO, &entry[1]);
> +	}
> +}
> +
>  static void ads112c14_populate_tables(struct ads112c14_data *data)
>  {
>  	u32 vref_uV, fsr_bits;
> -	int i;
> +
> +	for (u32 i = 0; i < data->num_measurements; i++) {
> +		struct ads112c14_measurement *measurement = &data->measurements[i];

[Severity: Critical]
Does this loop cause an out-of-bounds access?

Because `data->num_measurements` was artificially inflated in
ads112c14_parse_channels(), this loop goes past the allocated elements for
`data->measurements`. Writing to `measurement->scale_available` further down
in the loop will result in a heap buffer overflow.

[ ... ]
> @@ -560,13 +892,75 @@ static int ads112c14_probe(struct i2c_client *client)
>  	data->chip_info = info;
>  	data->client = client;
>  
> +	ret = ads112c14_parse_channels(indio_dev, &need_avdd_ref, &need_ext_ref);
> +	if (ret)
> +		return ret;
> +
>  	ret = devm_regulator_get_enable(&client->dev, "dvdd");
>  	if (ret)
>  		return dev_err_probe(dev, ret, "failed to get dvdd regulator\n");
>  
> -	ret = devm_regulator_get_enable(&client->dev, "avdd");
> -	if (ret)
> -		return dev_err_probe(dev, ret, "failed to get avdd regulator\n");
> +	if (need_avdd_ref) {
> +		ret = devm_regulator_get_enable_read_voltage(&client->dev, "avdd");
> +		if (ret)
> +			return dev_err_probe(dev, ret, "failed to get avdd voltage\n");

[Severity: High]
Does this incorrectly fail on success?

`devm_regulator_get_enable_read_voltage()` returns the voltage in microvolts on
success, which is a positive integer. Checking `if (ret)` will evaluate to true
and abort the probe when the voltage is successfully read. This same pattern
appears below for the 'refp' and 'refn' regulators.

[ ... ]
>  	data->regmap = devm_regmap_init_i2c(client, &ads112c14_regmap_config);
>  	if (IS_ERR(data->regmap))

[Severity: High]
This isn't a bug introduced by this patch, but does the probe fail to
register the device if the reset command succeeds?

Just below this context, during probe, a software reset is sent via
regmap_write() and the return value is checked with:

	if (ret != -EREMOTEIO)
		return ret;

If the device acknowledges the write and regmap_write() successfully returns 0,
the check evaluates to true (`0 != -EREMOTEIO`), causing the driver to
prematurely return 0 without ever calling devm_iio_device_register(), leaving
the device entirely unusable.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260615-iio-adc-ti-ads122c14-v1-0-e6bdadf7cb2b@baylibre.com?part=4

  reply	other threads:[~2026-06-15 22:13 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-15 21:59 [PATCH 0/4] iio: adc: new ti-ads112c14 driver David Lechner (TI)
2026-06-15 21:59 ` [PATCH 1/4] dt-bindings: iio: adc: add ti,ads122c14 David Lechner (TI)
2026-06-15 22:10   ` sashiko-bot
2026-06-16  0:26   ` Kurt Borja
2026-06-16 15:22     ` David Lechner
2026-06-16 17:31       ` Kurt Borja
2026-06-16 16:07   ` Conor Dooley
2026-06-15 22:00 ` [PATCH 2/4] iio: adc: add ti-ads112c14 driver David Lechner (TI)
2026-06-15 22:11   ` sashiko-bot
2026-06-16  7:32   ` Andy Shevchenko
2026-06-16 15:38     ` David Lechner
2026-06-15 22:00 ` [PATCH 3/4] iio: adc: ti-ads112c14: implement gain on internal short SYS_MON channel David Lechner (TI)
2026-06-15 22:14   ` sashiko-bot
2026-06-16  7:58   ` Andy Shevchenko
2026-06-16 10:03     ` Nuno Sá
2026-06-15 22:00 ` [PATCH 4/4] iio: adc: ti-ads112c14: add measurement channel support David Lechner (TI)
2026-06-15 22:13   ` sashiko-bot [this message]
2026-06-16  8:36   ` Andy Shevchenko
2026-06-16 15:55     ` David Lechner
2026-06-16 15:30   ` David Lechner
2026-06-16  0:18 ` [PATCH 0/4] iio: adc: new ti-ads112c14 driver Kurt Borja
2026-06-16 15:21   ` David Lechner
2026-06-16 17:26     ` Kurt Borja

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=20260615221317.9FFDA1F000E9@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 \
    /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.