All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Chris Morgan" <macroalpha82@gmail.com>
Cc: devicetree@vger.kernel.org, krzk+dt@kernel.org, robh@kernel.org,
	conor+dt@kernel.org
Subject: Re: [PATCH V5 06/11] iio: imu: inv_icm42607: Add Buffer support for icm42607
Date: Sat, 09 May 2026 19:44:51 +0000	[thread overview]
Message-ID: <20260509194451.E82A1C2BCB2@smtp.kernel.org> (raw)
In-Reply-To: <20260509191907.24734-7-macroalpha82@gmail.com>

Thank you for your contribution! Sashiko AI review found 10 potential issue(s) to consider:
- [Critical] Uninitialized variable usage and kernel heap buffer overflow during FIFO read.
- [Critical] Uninitialized pointer dereference and infinite loop vulnerability due to integer type mismatch.
- [High] Hardware FIFO stream corruption due to oversized register read.
- [High] Logic inversion completely breaks watermark truncation.
- [High] Integer underflow on internal state variable permanently disables the device on error rollback.
- [High] Race condition due to missing lock in `hwfifo_flush` callback.
- [High] Data corruption due to missing bounds check on partial hardware FIFO packets.
- [Medium] Missing hardware delays during buffer postdisable.
- [Medium] Watermark interrupt is leaked/permanently disabled on regmap error path.
- [Medium] Ignored return value leads to silent failure during system resume.
--

commit bdccadc0097311be50ac67b485f5dccd2b087eff
Author: Chris Morgan <macromorgan@hotmail.com>

iio: imu: inv_icm42607: Add Buffer support for icm42607

This commit adds FIFO parsing and reading functions to support buffer
transfers on the inv_icm42607 hardware.

diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_buffer.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_buffer.c
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_buffer.c
@@ -148,15 +148,12 @@
 
 [ ... ]
 
> +static unsigned int inv_icm42607_wm_truncate(unsigned int watermark,
> +					     size_t packet_size)
> +{
> +	size_t wm_size;
> +
> +	wm_size = watermark * packet_size;
> +	wm_size = max(wm_size, INV_ICM42607_FIFO_WATERMARK_MAX);

Is this max() intentional? It forces the watermark to always be greater
than or equal to the maximum hardware limit. Should this be min() instead?

> +
> +	return wm_size / packet_size;
> +}
> +
> +/**
> + * inv_icm42607_buffer_update_watermark - update watermark FIFO threshold

[ ... ]

> +	/* changing FIFO watermark requires to turn off watermark interrupt */
> +	ret = regmap_update_bits_check(st->map, INV_ICM42607_REG_INT_SOURCE0,
> +				       INV_ICM42607_INT_SOURCE0_FIFO_THS_INT1_EN,
> +				       0, &restore);
> +	if (ret)
> +		return ret;
> +
> +	/* compute watermark value in bytes */
> +	wm_size = watermark * packet_size;
> +	raw_wm = INV_ICM42607_FIFO_WATERMARK_VAL(wm_size);
> +	memcpy(st->buffer, &raw_wm, sizeof(raw_wm));
> +	ret = regmap_bulk_write(st->map, INV_ICM42607_REG_FIFO_CONFIG2,
> +				st->buffer, sizeof(raw_wm));
> +	if (ret)
> +		return ret;

If this regmap_bulk_write() fails, the function returns immediately without
restoring the interrupt. Could this leave the watermark interrupt permanently
disabled?

> +
> +	/* restore watermark interrupt */
> +	if (restore) {
> +		ret = regmap_update_bits(st->map, INV_ICM42607_REG_INT_SOURCE0,
> +					 INV_ICM42607_INT_SOURCE0_FIFO_THS_INT1_EN,
> +					 INV_ICM42607_INT_SOURCE0_FIFO_THS_INT1_EN);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}

[ ... ]

> +static int inv_icm42607_buffer_predisable(struct iio_dev *indio_dev)
> +{
> +	struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev);
> +	int ret;
> +
> +	guard(mutex)(&st->lock);
> +
> +	if (st->fifo.on > 1) {
> +		st->fifo.on--;
> +		return 0;
> +	}
> +
> +	/* set FIFO in bypass mode */
> +	ret = regmap_write(st->map, INV_ICM42607_REG_FIFO_CONFIG1,
> +			   INV_ICM42607_FIFO_CONFIG1_BYPASS);
> +	if (ret)
> +		return ret;
> +
> +	/* flush FIFO data */
> +	ret = regmap_write(st->map, INV_ICM42607_REG_SIGNAL_PATH_RESET,
> +			   INV_ICM42607_SIGNAL_PATH_RESET_FIFO_FLUSH);
> +	if (ret)
> +		return ret;
> +
> +	/* disable FIFO threshold interrupt */
> +	ret = regmap_update_bits(st->map, INV_ICM42607_REG_INT_SOURCE0,
> +				 INV_ICM42607_INT_SOURCE0_FIFO_THS_INT1_EN, 0);
> +	if (ret)
> +		return ret;
> +
> +	st->fifo.on--;

If inv_icm42607_buffer_postenable() fails early before incrementing
st->fifo.on, and the IIO core rolls back by calling this predisable
function, st->fifo.on would be 0 here. Since it is unsigned, could this
decrement cause it to underflow to UINT_MAX, leaving the device permanently
disabled for future calls?

> +
> +	return 0;
> +}
> +
> +static int inv_icm42607_buffer_postdisable(struct iio_dev *indio_dev)
> +{
> +	struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev);
> +	struct device *dev = regmap_get_device(st->map);
> +	unsigned int sensor;
> +	unsigned int *watermark;
> +	unsigned int sleep_temp = 0;
> +	unsigned int sleep_sensor = 0;
> +	unsigned int sleep;
> +	int ret;

[ ... ]

> +	*watermark = 0;
> +	ret = inv_icm42607_buffer_update_watermark(st);
> +	if (ret)
> +		goto out_unlock;
> +
> +out_unlock:
> +	mutex_unlock(&st->lock);
> +
> +	/* sleep maximum required time */
> +	sleep = max(sleep_sensor, sleep_temp);
> +	if (sleep)
> +		msleep(sleep);

Both sleep_temp and sleep_sensor are initialized to 0 and never modified
before this check. Does this mean the required hardware shutdown
power-transition delays are skipped completely?

[ ... ]

> +int inv_icm42607_buffer_fifo_read(struct inv_icm42607_state *st,
> +				  unsigned int max)
> +{
> +	const void *accel, *gyro, *timestamp;
> +	size_t i, max_count, size;
> +	const s8 *temp;
> +	int ret;
> +
> +	/* reset all samples counters */
> +	st->fifo.count = 0;
> +	st->fifo.nb.gyro = 0;
> +	st->fifo.nb.accel = 0;
> +	st->fifo.nb.total = 0;
> +
> +	/* compute maximum FIFO read size */
> +	if (max == 0)
> +		max_count = sizeof(st->fifo.data);
> +	else
> +		max_count = clamp(max_count,
> +				  (max * inv_icm42607_get_packet_size(st->fifo.en)),
> +				  sizeof(st->fifo.data));

If max != 0, max_count is passed uninitialized to clamp(). Could this lead
to undefined behavior?

> +
> +	/* read FIFO count value */
> +	ret = regmap_bulk_read(st->map, INV_ICM42607_REG_FIFO_COUNTH,
> +			       st->buffer, sizeof(st->buffer));

Is it safe to use sizeof(st->buffer) here? st->buffer is declared as an
array of 3 __be16 elements (6 bytes). The hardware FIFO count register is 2
bytes, so a 6-byte read would spill over into the adjacent FIFO_DATA
registers, unintentionally popping 4 bytes of data and breaking alignment.

> +	if (ret)
> +		return ret;
> +	st->fifo.count = be16_to_cpup(st->buffer);
> +
> +	/* check and clamp FIFO count value */
> +	if (st->fifo.count == 0)
> +		return 0;
> +
> +	st->fifo.count = max(st->fifo.count, max_count);

Should this be min() instead of max()? Using max() forces the count to be
at least the potentially uninitialized max_count value. This could cause
regmap_noinc_read() to read past the hardware count and overflow the
st->fifo.data buffer.

> +
> +	/* read all FIFO data in internal buffer */
> +	ret = regmap_noinc_read(st->map, INV_ICM42607_REG_FIFO_DATA,
> +				st->fifo.data, st->fifo.count);
> +	if (ret)
> +		return ret;
> +
> +	/* compute number of samples for each sensor */
> +	for (i = 0; i < st->fifo.count; i += size) {
> +		size = inv_icm42607_fifo_decode_packet(&st->fifo.data[i],
> +				&accel, &gyro, &temp, &timestamp);
> +		if (size <= 0)
> +			break;

inv_icm42607_fifo_decode_packet() returns a ssize_t which can be -EINVAL.
Since size is of type size_t, the negative error code becomes a huge
unsigned integer. The size <= 0 check will evaluate to false, skipping
error handling.

Since decode_packet() does not initialize accel and gyro on error, could
this result in dereferencing uninitialized pointers below?

Also, if the hardware returns a byte count that ends with a partial packet,
could this loop access memory beyond what was populated from the hardware
since there is no check for i + size > st->fifo.count?

> +		if (gyro != NULL && inv_icm42607_fifo_is_data_valid(gyro))
> +			st->fifo.nb.gyro++;
> +		if (accel != NULL && inv_icm42607_fifo_is_data_valid(accel))
> +			st->fifo.nb.accel++;
> +		st->fifo.nb.total++;
> +	}
> +
> +	return 0;
> +}
> +
> +int inv_icm42607_buffer_hwfifo_flush(struct inv_icm42607_state *st,
> +				     unsigned int count)
> +{
> +	s64 gyro_ts, accel_ts;
> +	int ret;
> +
> +	gyro_ts = iio_get_time_ns(st->indio_gyro);
> +	accel_ts = iio_get_time_ns(st->indio_accel);

These timestamps appear to be unused. Should they be passed to the buffer
logic or are they just dead code?

> +
> +	ret = inv_icm42607_buffer_fifo_read(st, count);

Does this need to be protected by mutex_lock(&st->lock)? Since this
callback can be triggered via sysfs concurrently with the normal interrupt
handler, it seems possible to have interleaved regmap reads or corrupted
internal FIFO sample counters.

> +
> +	return ret;
> +}

diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
--- a/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
@@ -404,8 +404,11 @@
 	if (ret)
 		return ret;
 
-	/* Nothing else to restore at this time. */
+	if (st->fifo.on) {
+		ret = regmap_write(st->map, INV_ICM42607_REG_FIFO_CONFIG1,
+				   INV_ICM42607_FIFO_CONFIG1_MODE);
+	}
 
 	return 0;
 }

Is the return value from regmap_write() meant to be checked? Currently, ret
is assigned but not used, so the function unconditionally returns 0 even if
the write fails.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260509191907.24734-1-macroalpha82@gmail.com?part=6

  reply	other threads:[~2026-05-09 19:44 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-09 19:18 [PATCH V5 00/11] Add Invensense ICM42607 Chris Morgan
2026-05-09 19:18 ` Chris Morgan
2026-05-09 19:18 ` [PATCH V5 01/11] dt-bindings: iio: imu: icm42600: Add mount-matrix to icm42600 Chris Morgan
2026-05-09 19:18   ` Chris Morgan
2026-05-09 19:18 ` [PATCH V5 02/11] dt-bindings: iio: imu: icm42600: Add icm42607 binding Chris Morgan
2026-05-09 19:18   ` Chris Morgan
2026-05-09 19:18 ` [PATCH V5 03/11] iio: imu: inv_icm42607: Add inv_icm42607 Core Driver Chris Morgan
2026-05-09 19:18   ` Chris Morgan
2026-05-09 19:41   ` sashiko-bot
2026-05-11 17:28   ` Jonathan Cameron
2026-05-11 17:28     ` Jonathan Cameron
2026-05-11 19:25     ` Chris Morgan
2026-05-11 19:25       ` Chris Morgan
2026-05-09 19:18 ` [PATCH V5 04/11] iio: imu: inv_icm42607: Add I2C and SPI For icm42607 Chris Morgan
2026-05-09 19:18   ` Chris Morgan
2026-05-09 20:08   ` sashiko-bot
2026-05-11 17:47   ` Jonathan Cameron
2026-05-11 17:47     ` Jonathan Cameron
2026-05-12 20:06     ` Andy Shevchenko
2026-05-12 20:06       ` Andy Shevchenko
2026-05-09 19:18 ` [PATCH V5 05/11] iio: imu: inv_icm42607: Add PM support for icm42607 Chris Morgan
2026-05-09 19:18   ` Chris Morgan
2026-05-09 19:58   ` sashiko-bot
2026-05-11 18:11   ` Jonathan Cameron
2026-05-11 18:11     ` Jonathan Cameron
2026-05-09 19:19 ` [PATCH V5 06/11] iio: imu: inv_icm42607: Add Buffer " Chris Morgan
2026-05-09 19:19   ` Chris Morgan
2026-05-09 19:44   ` sashiko-bot [this message]
2026-05-11 18:17   ` Jonathan Cameron
2026-05-11 18:17     ` Jonathan Cameron
2026-05-09 19:19 ` [PATCH V5 07/11] iio: imu: inv_icm42607: Add Temp Support in icm42607 Chris Morgan
2026-05-09 19:19   ` Chris Morgan
2026-05-09 19:19 ` [PATCH V5 08/11] iio: imu: inv_icm42607: Add Accelerometer for icm42607 Chris Morgan
2026-05-09 19:19   ` Chris Morgan
2026-05-09 20:02   ` sashiko-bot
2026-05-09 19:19 ` [PATCH V5 09/11] iio: imu: inv_icm42607: Add Wake on Movement to icm42607 Chris Morgan
2026-05-09 19:19   ` Chris Morgan
2026-05-09 19:52   ` sashiko-bot
2026-05-09 19:19 ` [PATCH V5 10/11] iio: imu: inv_icm42607: Add Gyroscope " Chris Morgan
2026-05-09 19:19   ` Chris Morgan
2026-05-09 20:02   ` sashiko-bot
2026-05-09 19:19 ` [PATCH V5 11/11] arm64: dts: rockchip: Add icm42607p IMU for RG-DS Chris Morgan
2026-05-09 19:19   ` Chris Morgan

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=20260509194451.E82A1C2BCB2@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=krzk+dt@kernel.org \
    --cc=macroalpha82@gmail.com \
    --cc=robh@kernel.org \
    --cc=sashiko@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.