summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco Chen <marcochen.dev@gmail.com>2026-08-08 15:54:50 -0400
committerJonathan Cameron <jonathan.cameron@oss.qualcomm.com>2026-08-31 00:52:39 +0100
commitf0ea4824deebf21dacfbe397c4b0a5fd3e745a8d (patch)
tree4ada3eaf6cef7e4083d75a72cf00a4bf64fee135
parentcee9395acd8043be0644b25c34bfa86623f2b935 (diff)
downloadlinux-next-f0ea4824deebf21dacfbe397c4b0a5fd3e745a8d.tar.gz
linux-next-f0ea4824deebf21dacfbe397c4b0a5fd3e745a8d.zip
iio: health: max30102: fix NULL dereference in interrupt handler
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> Cc: <stable@vger.kernel.org> Signed-off-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com>
-rw-r--r--drivers/iio/health/max30102.c12
1 files 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);