drivers/iio/imu/adis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
From: Radu Sabau <radu.sabau@analog.com>
The adis_init() function dereferences adis->ops to check if the
individual function pointers (write, read, reset) are NULL, but does
not first check if adis->ops itself is NULL.
Drivers like adis16480, adis16490, adis16545 and others do not set
custom ops and rely on adis_init() assigning the defaults. Since struct
adis is zero-initialized by devm_iio_device_alloc(), adis->ops is NULL
when adis_init() is called, causing a NULL pointer dereference:
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
pc : adis_init+0xc0/0x118
Call trace:
adis_init+0xc0/0x118
adis16480_probe+0xe0/0x670
Fix this by checking if adis->ops is NULL before dereferencing it,
falling through to assign the default ops in that case.
Fixes: 3b29bcee8f6f ("iio: imu: adis: Add custom ops struct")
Signed-off-by: Radu Sabau <radu.sabau@analog.com>
---
adis_init() dereferences adis->ops to validate its function pointers
before checking whether adis->ops itself is NULL. Drivers that rely on
the default ops (adis16480, adis16490, adis16545, among others) never
set adis->ops prior to calling adis_init(), so the field is NULL due to
zero-initialisation by devm_iio_device_alloc(). The result is a kernel
crash on probe:
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
Hardware name: Raspberry Pi 5 Model B Rev 1.0 (DT)
pc : adis_init+0xc0/0x118
lr : adis_init+0x50/0x118
Call trace:
adis_init+0xc0/0x118
adis16480_probe+0xe0/0x670
spi_probe+0x8c/0xf8
really_probe+0xc4/0x2b0
The bug was introduced in 3b29bcee8f6f ("iio: imu: adis: Add custom ops struct")
which added the ops validation logic without a prior NULL check
on the pointer itself.
The fix is a one-line addition of !adis->ops to the condition, so that
a NULL ops pointer is treated the same as an ops struct with all-NULL
function pointers, both falling through to the default ops assignment.
The validation path for partially-populated custom ops structs is
unchanged.
Tested on Raspberry Pi 5 with adis16545-3 connected over SPI. Without
the fix the kernel crashes at adis_init+0xc0. With the fix the driver
probes successfully and the device is accessible via the IIO subsystem.
---
Changes in v2:
- put stack trace in a single line in the commit body
- split long line if in multiple statements and removed the redundant ones
- use correct git hash for fixes tag
- Link to v1: https://lore.kernel.org/r/20260220-adis-fix-v1-1-9fa10cce812f@analog.com
---
drivers/iio/imu/adis.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c
index d160147cce0b..a2bc1d14ed91 100644
--- a/drivers/iio/imu/adis.c
+++ b/drivers/iio/imu/adis.c
@@ -526,7 +526,7 @@ int adis_init(struct adis *adis, struct iio_dev *indio_dev,
adis->spi = spi;
adis->data = data;
- if (!adis->ops->write && !adis->ops->read && !adis->ops->reset)
+ if (!adis->ops)
adis->ops = &adis_default_ops;
else if (!adis->ops->write || !adis->ops->read || !adis->ops->reset)
return -EINVAL;
---
base-commit: 8bf22c33e7a172fbc72464f4cc484d23a6b412ba
change-id: 20260220-adis-fix-177ca0405d8a
Best regards,
--
Radu Sabau <radu.sabau@analog.com>
On Fri, Feb 20, 2026 at 04:16:41PM +0200, Radu Sabau via B4 Relay wrote:
> The adis_init() function dereferences adis->ops to check if the
> individual function pointers (write, read, reset) are NULL, but does
> not first check if adis->ops itself is NULL.
>
> Drivers like adis16480, adis16490, adis16545 and others do not set
> custom ops and rely on adis_init() assigning the defaults. Since struct
> adis is zero-initialized by devm_iio_device_alloc(), adis->ops is NULL
> when adis_init() is called, causing a NULL pointer dereference:
>
> Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
> pc : adis_init+0xc0/0x118
> Call trace:
> adis_init+0xc0/0x118
> adis16480_probe+0xe0/0x670
>
> Fix this by checking if adis->ops is NULL before dereferencing it,
> falling through to assign the default ops in that case.
Don't throw versions too quickly. You missed a tag from colleague of yours.
> Fixes: 3b29bcee8f6f ("iio: imu: adis: Add custom ops struct")
...
> - if (!adis->ops->write && !adis->ops->read && !adis->ops->reset)
> + if (!adis->ops)
I hope you have checked that this is indeed the case and we don't need this
check anymore. (I would be glad to see it being replaced as in this patch!)
Assuming this is confirmed,
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Collect the tags and issue a new version only on demand, and not earlier
than 24h from previous one.
> adis->ops = &adis_default_ops;
> else if (!adis->ops->write || !adis->ops->read || !adis->ops->reset)
> return -EINVAL;
--
With Best Regards,
Andy Shevchenko
On Fri, 20 Feb 2026 16:24:40 +0200
Andy Shevchenko <andriy.shevchenko@intel.com> wrote:
> On Fri, Feb 20, 2026 at 04:16:41PM +0200, Radu Sabau via B4 Relay wrote:
>
> > The adis_init() function dereferences adis->ops to check if the
> > individual function pointers (write, read, reset) are NULL, but does
> > not first check if adis->ops itself is NULL.
> >
> > Drivers like adis16480, adis16490, adis16545 and others do not set
> > custom ops and rely on adis_init() assigning the defaults. Since struct
> > adis is zero-initialized by devm_iio_device_alloc(), adis->ops is NULL
> > when adis_init() is called, causing a NULL pointer dereference:
> >
> > Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
> > pc : adis_init+0xc0/0x118
> > Call trace:
> > adis_init+0xc0/0x118
> > adis16480_probe+0xe0/0x670
> >
> > Fix this by checking if adis->ops is NULL before dereferencing it,
> > falling through to assign the default ops in that case.
>
> Don't throw versions too quickly. You missed a tag from colleague of yours.
>
> > Fixes: 3b29bcee8f6f ("iio: imu: adis: Add custom ops struct")
>
> ...
>
> > - if (!adis->ops->write && !adis->ops->read && !adis->ops->reset)
> > + if (!adis->ops)
>
> I hope you have checked that this is indeed the case and we don't need this
> check anymore. (I would be glad to see it being replaced as in this patch!)
>
> Assuming this is confirmed,
> Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
>
> Collect the tags and issue a new version only on demand, and not earlier
> than 24h from previous one.
>
I picked up the tag from Antonio and applied this as well as adding a stable
marking so it'll get backported.
Note I'll be rebasing on rc1 once available, so the fixes-togreg branch
currently has a random mid merge window base.
Thanks,
Jonathan
> > adis->ops = &adis_default_ops;
> > else if (!adis->ops->write || !adis->ops->read || !adis->ops->reset)
> > return -EINVAL;
>
© 2016 - 2026 Red Hat, Inc.