* [PATCH v3] iio: imu: inv_icm45600: clamp the device-reported FIFO sample count
@ 2026-06-17 1:57 Bryam Vargas via B4 Relay
2026-06-17 10:18 ` Andy Shevchenko
2026-06-21 18:08 ` Jonathan Cameron
0 siblings, 2 replies; 4+ messages in thread
From: Bryam Vargas via B4 Relay @ 2026-06-17 1:57 UTC (permalink / raw)
To: Remi Buisson, Jonathan Cameron
Cc: linux-iio, linux-kernel, David Lechner, Andy Shevchenko, Nuno Sá
From: Bryam Vargas <hexlabsecurity@proton.me>
inv_icm45600_buffer_fifo_read() uses the FIFO_COUNT the device reports,
unclamped, as the length of a regmap_noinc_read() into the fixed 8 KiB
st->fifo.data buffer. The only bound is the caller's "max", which the
interrupt path skips (it passes 0). A device, or an attacker on the bus,
reporting up to 65535 makes the read as large as ~1 MiB: a heap
out-of-bounds write of device-controlled data.
Clamp fifo_nb to the buffer capacity (INV_ICM45600_FIFO_SIZE_MAX /
packet_size) before the read, mirroring the watermark cap in
inv_icm45600_wm_truncate() and the sibling inv_icm42600 driver. The clamp
is a no-op for conforming hardware.
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
---
v3 (Andy [2]): shrink the commit message; the register/byte detail, the
not-for-stable rationale and the introducing commit moved below the cut.
v2 (Jonathan [1]): use min() instead of min_t(size_t, ...), and drop the
backport tags -- this is hardening against a malformed device-reported
count, not reachable with conforming hardware ("nice to have hardening",
Jonathan).
[1] https://lore.kernel.org/all/20260614144557.196a5c4c@jic23-huawei/
[2] https://lore.kernel.org/all/ajEMfH-_76M1OBqE@ashevche-desk.local/
v1: https://lore.kernel.org/all/20260613-b4-disp-58b984f3-v1-1-352b2f925f58@proton.me/
v2: https://lore.kernel.org/all/20260615-b4-disp-feb19207-v2-1-2d36f1e5fc54@proton.me/
fifo_nb = le16_to_cpup(raw_fifo_count) is 0..65535; the interrupt handler
calls inv_icm45600_buffer_fifo_read(st, 0), so the "max" clamp is skipped,
and fifo_nb * packet_size (16 bytes per packet) reaches ~1 MiB into the
8 KiB st->fifo.data buffer. Present since 06674a72cf7a ("iio: imu:
inv_icm45600: add buffer support in iio devices"); not marked for stable as
it needs a malicious or defective device, or bus tampering.
Reproduced with an in-kernel KASAN litmus and a userspace ASan model:
without the clamp a FIFO_COUNT of 0x208 (520 packets -> 8320 bytes) gives a
slab-out-of-bounds write past the 8192-byte region, and the full magnitude
(0xFFFF -> 1048560 bytes) reproduces under ASan on x86_64 and i386; with the
clamp the read is bounded to the buffer. Reproducer and full logs available
on request.
---
drivers/iio/imu/inv_icm45600/inv_icm45600_buffer.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/iio/imu/inv_icm45600/inv_icm45600_buffer.c b/drivers/iio/imu/inv_icm45600/inv_icm45600_buffer.c
index 2b9ea317385c..5cde42f70c2e 100644
--- a/drivers/iio/imu/inv_icm45600/inv_icm45600_buffer.c
+++ b/drivers/iio/imu/inv_icm45600/inv_icm45600_buffer.c
@@ -422,6 +422,9 @@ int inv_icm45600_buffer_fifo_read(struct inv_icm45600_state *st,
if (max > 0 && fifo_nb > max)
fifo_nb = max;
+ /* Limit to the internal buffer capacity; the count is device-provided. */
+ fifo_nb = min(fifo_nb, INV_ICM45600_FIFO_SIZE_MAX / packet_size);
+
/* Try to read all FIFO data in internal buffer. */
st->fifo.count = fifo_nb * packet_size;
ret = regmap_noinc_read(st->map, INV_ICM45600_REG_FIFO_DATA,
---
base-commit: 8e65320d91cdc3b241d4b94855c88459b91abf66
change-id: 20260616-b4-disp-76e3f743-98d24c7e6ae4
Best regards,
--
Bryam Vargas <hexlabsecurity@proton.me>
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH v3] iio: imu: inv_icm45600: clamp the device-reported FIFO sample count
2026-06-17 1:57 [PATCH v3] iio: imu: inv_icm45600: clamp the device-reported FIFO sample count Bryam Vargas via B4 Relay
@ 2026-06-17 10:18 ` Andy Shevchenko
2026-06-21 18:08 ` Jonathan Cameron
1 sibling, 0 replies; 4+ messages in thread
From: Andy Shevchenko @ 2026-06-17 10:18 UTC (permalink / raw)
To: hexlabsecurity
Cc: Remi Buisson, Jonathan Cameron, linux-iio, linux-kernel,
David Lechner, Andy Shevchenko, Nuno Sá
On Tue, Jun 16, 2026 at 08:57:28PM -0500, Bryam Vargas via B4 Relay wrote:
> inv_icm45600_buffer_fifo_read() uses the FIFO_COUNT the device reports,
> unclamped, as the length of a regmap_noinc_read() into the fixed 8 KiB
> st->fifo.data buffer. The only bound is the caller's "max", which the
> interrupt path skips (it passes 0). A device, or an attacker on the bus,
> reporting up to 65535 makes the read as large as ~1 MiB: a heap
> out-of-bounds write of device-controlled data.
>
> Clamp fifo_nb to the buffer capacity (INV_ICM45600_FIFO_SIZE_MAX /
> packet_size) before the read, mirroring the watermark cap in
> inv_icm45600_wm_truncate() and the sibling inv_icm42600 driver. The clamp
> is a no-op for conforming hardware.
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v3] iio: imu: inv_icm45600: clamp the device-reported FIFO sample count
2026-06-17 1:57 [PATCH v3] iio: imu: inv_icm45600: clamp the device-reported FIFO sample count Bryam Vargas via B4 Relay
2026-06-17 10:18 ` Andy Shevchenko
@ 2026-06-21 18:08 ` Jonathan Cameron
2026-06-22 8:55 ` Bryam Vargas
1 sibling, 1 reply; 4+ messages in thread
From: Jonathan Cameron @ 2026-06-21 18:08 UTC (permalink / raw)
To: Bryam Vargas via B4 Relay
Cc: hexlabsecurity, Remi Buisson, linux-iio, linux-kernel,
David Lechner, Andy Shevchenko, Nuno Sá
On Tue, 16 Jun 2026 20:57:28 -0500
Bryam Vargas via B4 Relay <devnull+hexlabsecurity.proton.me@kernel.org> wrote:
> From: Bryam Vargas <hexlabsecurity@proton.me>
>
> inv_icm45600_buffer_fifo_read() uses the FIFO_COUNT the device reports,
> unclamped, as the length of a regmap_noinc_read() into the fixed 8 KiB
> st->fifo.data buffer. The only bound is the caller's "max", which the
> interrupt path skips (it passes 0). A device, or an attacker on the bus,
> reporting up to 65535 makes the read as large as ~1 MiB: a heap
> out-of-bounds write of device-controlled data.
>
> Clamp fifo_nb to the buffer capacity (INV_ICM45600_FIFO_SIZE_MAX /
> packet_size) before the read, mirroring the watermark cap in
> inv_icm45600_wm_truncate() and the sibling inv_icm42600 driver. The clamp
> is a no-op for conforming hardware.
>
> Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
> ---
> v3 (Andy [2]): shrink the commit message; the register/byte detail, the
> not-for-stable rationale and the introducing commit moved below the cut.
> v2 (Jonathan [1]): use min() instead of min_t(size_t, ...), and drop the
> backport tags -- this is hardening against a malformed device-reported
> count, not reachable with conforming hardware ("nice to have hardening",
> Jonathan).
>
> [1] https://lore.kernel.org/all/20260614144557.196a5c4c@jic23-huawei/
> [2] https://lore.kernel.org/all/ajEMfH-_76M1OBqE@ashevche-desk.local/
> v1: https://lore.kernel.org/all/20260613-b4-disp-58b984f3-v1-1-352b2f925f58@proton.me/
> v2: https://lore.kernel.org/all/20260615-b4-disp-feb19207-v2-1-2d36f1e5fc54@proton.me/
>
> fifo_nb = le16_to_cpup(raw_fifo_count) is 0..65535; the interrupt handler
> calls inv_icm45600_buffer_fifo_read(st, 0), so the "max" clamp is skipped,
> and fifo_nb * packet_size (16 bytes per packet) reaches ~1 MiB into the
> 8 KiB st->fifo.data buffer. Present since 06674a72cf7a ("iio: imu:
> inv_icm45600: add buffer support in iio devices"); not marked for stable as
> it needs a malicious or defective device, or bus tampering.
>
> Reproduced with an in-kernel KASAN litmus and a userspace ASan model:
> without the clamp a FIFO_COUNT of 0x208 (520 packets -> 8320 bytes) gives a
> slab-out-of-bounds write past the 8192-byte region, and the full magnitude
> (0xFFFF -> 1048560 bytes) reproduces under ASan on x86_64 and i386; with the
> clamp the read is bounded to the buffer. Reproducer and full logs available
> on request.
> ---
> drivers/iio/imu/inv_icm45600/inv_icm45600_buffer.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/drivers/iio/imu/inv_icm45600/inv_icm45600_buffer.c b/drivers/iio/imu/inv_icm45600/inv_icm45600_buffer.c
> index 2b9ea317385c..5cde42f70c2e 100644
> --- a/drivers/iio/imu/inv_icm45600/inv_icm45600_buffer.c
> +++ b/drivers/iio/imu/inv_icm45600/inv_icm45600_buffer.c
> @@ -422,6 +422,9 @@ int inv_icm45600_buffer_fifo_read(struct inv_icm45600_state *st,
> if (max > 0 && fifo_nb > max)
> fifo_nb = max;
>
> + /* Limit to the internal buffer capacity; the count is device-provided. */
> + fifo_nb = min(fifo_nb, INV_ICM45600_FIFO_SIZE_MAX / packet_size);
> +
It is a little odd to clamp against a value / packet size just to multiply it
by packet size. However there is an oddity here in that we might not have
a fully number of packets in the 8KiB buffer.
Hmm. It actually is a though as the packets are either 8 or 16 bytes
(only the bigger one relevant here).
So could we just do this instead?
st->fifo.count = min(fifo_nb * packet_size, INV_ICM45600_FIFO_SIZE_MAX);
Also to make this much easier to spot, can we actually use the define in
the allocation in _core.c to allocate the buffer? That can be in the same
patch as it's all related, but needs a tiny comment in the patch description.
st->fifo.data = devm_kzalloc(dev, INV_ICM45600_FIFO_SIZE_MAX, GFP_KERNEL);
> /* Try to read all FIFO data in internal buffer. */
> st->fifo.count = fifo_nb * packet_size;
> ret = regmap_noinc_read(st->map, INV_ICM45600_REG_FIFO_DATA,
>
> ---
> base-commit: 8e65320d91cdc3b241d4b94855c88459b91abf66
> change-id: 20260616-b4-disp-76e3f743-98d24c7e6ae4
>
> Best regards,
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH v3] iio: imu: inv_icm45600: clamp the device-reported FIFO sample count
2026-06-21 18:08 ` Jonathan Cameron
@ 2026-06-22 8:55 ` Bryam Vargas
0 siblings, 0 replies; 4+ messages in thread
From: Bryam Vargas @ 2026-06-22 8:55 UTC (permalink / raw)
To: Jonathan Cameron, Remi Buisson
Cc: Andy Shevchenko, David Lechner, Nuno Sá, linux-iio, linux-kernel
On 2026-06-21, Jonathan Cameron wrote:
> So could we just do this instead?
> st->fifo.count = min(fifo_nb * packet_size, INV_ICM45600_FIFO_SIZE_MAX);
Yes, cleaner -- and safe here: fifo_nb isn't used past that line (the read, the
one-by-one fallback and the decode loop all bound on st->fifo.count), so
clamping the byte count is enough. fifo_nb is size_t and packet_size ssize_t, so
the multiply is 64-bit with no narrowing before the min. v4 will use it.
> can we actually use the define in the allocation in _core.c
Will do. It's devm_kzalloc(dev, 8192, ...) today and INV_ICM45600_FIFO_SIZE_MAX
is SZ_8K, so it's a no-op rename that ties the allocation to the clamp; folded
into the same patch with a changelog note.
v4 shortly.
Bryam
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-06-22 8:55 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-17 1:57 [PATCH v3] iio: imu: inv_icm45600: clamp the device-reported FIFO sample count Bryam Vargas via B4 Relay
2026-06-17 10:18 ` Andy Shevchenko
2026-06-21 18:08 ` Jonathan Cameron
2026-06-22 8:55 ` Bryam Vargas
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®