The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH v4] iio: health: max30102: fix NULL dereference in interrupt handler
@ 2026-08-08 19:54 Marco Chen
  2026-08-09 23:53 ` Jonathan Cameron
  0 siblings, 1 reply; 2+ messages in thread
From: Marco Chen @ 2026-08-08 19:54 UTC (permalink / raw)
  To: jic23
  Cc: dlechner, nuno.sa, andy, pmeerw, matt, linux-iio, linux-kernel,
	skhan, linux-kernel-mentees

The interrupt is requested in max30102_probe() and stays enabled
for the lifetime of the device, but indio_dev->active_scan_mask is only
valid while a buffer is enabled. When an interrupt arrives while no
buffer is enabled, the handler dereferences the NULL active_scan_mask:

  Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
  Call trace:
   __bitmap_weight+0x64/0x98 (P)
   max30102_interrupt_handler+0x48/0x160 [max30102]

Call max30102_fifo_count() at the top of the handler and return early
unless it reports a FIFO sample is ready. Because FIFO_RDY is the only
interrupt source enabled in max30102_chip_init(), an invocation of
max30102_interrupt_handler() without the FIFO_RDY interrupt status bit
set carries no data to read and can return before touching
active_scan_mask. A negative return from max30102_fifo_count()
indicates a failed interrupt status read and is treated the same way.

Fixes: 90579b69e94b ("iio: health: max30102: Add MAX30105 support")
Suggested-by: Jonathan Cameron <jic23@kernel.org>
Signed-off-by: Marco Chen <marcochen.dev@gmail.com>
---
Changes in v4:
- Trim the backtrace to only relevant frames and unwrap the first line
  as suggested by Andy.

max30102_fifo_count() still has the odd name and int return you mentioned
in v2, so I will send a follow-up patch once this lands.

Tested on a MAX30102 on Raspberry Pi 4 over I2C.

v1: https://lore.kernel.org/linux-iio/20260731184124.112124-1-marcochen.dev@gmail.com/
v2: https://lore.kernel.org/linux-iio/20260804234355.65319-1-marcochen.dev@gmail.com/
v3: https://lore.kernel.org/linux-iio/20260805040621.84843-1-marcochen.dev@gmail.com/

 drivers/iio/health/max30102.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
index c37316c86f14..aee96167f01e 100644
--- a/drivers/iio/health/max30102.c
+++ b/drivers/iio/health/max30102.c
@@ -290,9 +290,15 @@ static irqreturn_t max30102_interrupt_handler(int irq, void *private)
 {
 	struct iio_dev *indio_dev = private;
 	struct max30102_data *data = iio_priv(indio_dev);
-	unsigned int measurements = bitmap_weight(indio_dev->active_scan_mask,
-						  iio_get_masklength(indio_dev));
-	int ret, cnt = 0;
+	unsigned int measurements;
+	int ret, cnt;
+
+	cnt = max30102_fifo_count(data);
+	if (cnt <= 0)
+		return IRQ_HANDLED;
+
+	measurements = bitmap_weight(indio_dev->active_scan_mask,
+				     iio_get_masklength(indio_dev));
 
 	mutex_lock(&data->lock);
 
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH v4] iio: health: max30102: fix NULL dereference in interrupt handler
  2026-08-08 19:54 [PATCH v4] iio: health: max30102: fix NULL dereference in interrupt handler Marco Chen
@ 2026-08-09 23:53 ` Jonathan Cameron
  0 siblings, 0 replies; 2+ messages in thread
From: Jonathan Cameron @ 2026-08-09 23:53 UTC (permalink / raw)
  To: Marco Chen
  Cc: dlechner, nuno.sa, andy, pmeerw, matt, linux-iio, linux-kernel,
	skhan, linux-kernel-mentees

On Sat,  8 Aug 2026 15:54:50 -0400
Marco Chen <marcochen.dev@gmail.com> wrote:

> The interrupt is requested in max30102_probe() and stays enabled
> for the lifetime of the device, but indio_dev->active_scan_mask is only
> valid while a buffer is enabled. When an interrupt arrives while no
> buffer is enabled, the handler dereferences the NULL active_scan_mask:
> 
>   Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
>   Call trace:
>    __bitmap_weight+0x64/0x98 (P)
>    max30102_interrupt_handler+0x48/0x160 [max30102]
> 
> Call max30102_fifo_count() at the top of the handler and return early
> unless it reports a FIFO sample is ready. Because FIFO_RDY is the only
> interrupt source enabled in max30102_chip_init(), an invocation of
> max30102_interrupt_handler() without the FIFO_RDY interrupt status bit
> set carries no data to read and can return before touching
> active_scan_mask. A negative return from max30102_fifo_count()
> indicates a failed interrupt status read and is treated the same way.
> 
> Fixes: 90579b69e94b ("iio: health: max30102: Add MAX30105 support")
> Suggested-by: Jonathan Cameron <jic23@kernel.org>
> Signed-off-by: Marco Chen <marcochen.dev@gmail.com>
Applied to the fixes-togreg branch of iio.git.

Note however that this has missed my last pull request for this cycle
so won't go anywhere until after rc1 which is in about 3 weeks time.

thanks,

Jonathan

> ---
> Changes in v4:
> - Trim the backtrace to only relevant frames and unwrap the first line
>   as suggested by Andy.
> 
> max30102_fifo_count() still has the odd name and int return you mentioned
> in v2, so I will send a follow-up patch once this lands.
> 
> Tested on a MAX30102 on Raspberry Pi 4 over I2C.
> 
> v1: https://lore.kernel.org/linux-iio/20260731184124.112124-1-marcochen.dev@gmail.com/
> v2: https://lore.kernel.org/linux-iio/20260804234355.65319-1-marcochen.dev@gmail.com/
> v3: https://lore.kernel.org/linux-iio/20260805040621.84843-1-marcochen.dev@gmail.com/
> 
>  drivers/iio/health/max30102.c | 12 +++++++++---
>  1 file changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> index c37316c86f14..aee96167f01e 100644
> --- a/drivers/iio/health/max30102.c
> +++ b/drivers/iio/health/max30102.c
> @@ -290,9 +290,15 @@ static irqreturn_t max30102_interrupt_handler(int irq, void *private)
>  {
>  	struct iio_dev *indio_dev = private;
>  	struct max30102_data *data = iio_priv(indio_dev);
> -	unsigned int measurements = bitmap_weight(indio_dev->active_scan_mask,
> -						  iio_get_masklength(indio_dev));
> -	int ret, cnt = 0;
> +	unsigned int measurements;
> +	int ret, cnt;
> +
> +	cnt = max30102_fifo_count(data);
> +	if (cnt <= 0)
> +		return IRQ_HANDLED;
> +
> +	measurements = bitmap_weight(indio_dev->active_scan_mask,
> +				     iio_get_masklength(indio_dev));
>  
>  	mutex_lock(&data->lock);
>  


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-08-09 23:53 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-08 19:54 [PATCH v4] iio: health: max30102: fix NULL dereference in interrupt handler Marco Chen
2026-08-09 23:53 ` Jonathan Cameron

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox