[PATCH v2] iio: adc: stm32-adc: fix possible division by zero in processed channel

Andy Shevchenko andriy.shevchenko at intel.com
Wed Sep 16 07:39:05 PDT 2026


On Wed, Sep 16, 2026 at 04:10:05PM +0200, Fabrice Gasnier wrote:
> In case the conversion has failed or returned zero, processing *val
> can lead to a division by zero. Need to check for errors, or converted
> value is zero, before processing the data. In case the converted value
> is zero, e.g. the Vrefint channel, this should be considered as invalid
> in all cases.

...

> Reported-by: Sashiko <sashiko-bot at kernel.org>
> Link: https://lore.kernel.org/all/20260911161555.244F31F000FF@smtp.kernel.org/

Closes: ^^^


> +		if (mask == IIO_CHAN_INFO_PROCESSED) {
> +			int vrefint_raw;
> +
> +			if (ret < 0) {
> +				iio_device_release_direct(indio_dev);
> +				return ret;
> +			}
> +
> +			vrefint_raw = *val;

> +

Unneeded blank line.

> +			if (vrefint_raw == 0) {
> +				iio_device_release_direct(indio_dev);
> +				return -EINVAL;
> +			}
> +
> +			*val = STM32_ADC_VREFINT_VOLTAGE * adc->vrefint.vrefint_cal / vrefint_raw;
> +		}

Let's look at the current code in this switch-case

	case IIO_CHAN_INFO_PROCESSED:
		if (!iio_device_claim_direct(indio_dev))
			return -EBUSY;
		if (chan->type == IIO_VOLTAGE)
			ret = stm32_adc_single_conv(indio_dev, chan, val);
		else
			ret = -EINVAL;

		if (mask == IIO_CHAN_INFO_PROCESSED)
			*val = STM32_ADC_VREFINT_VOLTAGE * adc->vrefint.vrefint_cal / *val;

		iio_device_release_direct(indio_dev);
		return ret;

In the previous version you were trying to keep goto-less approach.
However in the current state of affairs I don't think the goto is
too bad (after all we need to backport this to the kernels that may
not have IIO_DEV_ACQUIRE_DIRECT_MODE() macro).

Also checking 'ret' under another condition seems unusual.

What about

	case IIO_CHAN_INFO_PROCESSED:
		if (!iio_device_claim_direct(indio_dev))
			return -EBUSY;
		if (chan->type == IIO_VOLTAGE)
			ret = stm32_adc_single_conv(indio_dev, chan, val);
		else
			ret = -EINVAL;
		iio_device_release_direct(indio_dev);
		if (ret)
			return ret;

		if (*val == 0)
			return -EINVAL;

		if (mask == IIO_CHAN_INFO_PROCESSED)
			*val = STM32_ADC_VREFINT_VOLTAGE * adc->vrefint.vrefint_cal / *val;

		return 0;

? (Yes, we leave that line untouched, but we get the change cleaner.)


-- 
With Best Regards,
Andy Shevchenko





More information about the linux-arm-kernel mailing list