Linux Input/HID development
 help / color / mirror / Atom feed
* [PATCH 0/9] HID: iio: Fix race condition between callback registration and device exposure
@ 2026-06-06 11:37 Sanjay Chitroda
  2026-06-06 11:37 ` [PATCH 1/9] iio: orientation: hid-sensor-rotation: Fix race " Sanjay Chitroda
                   ` (8 more replies)
  0 siblings, 9 replies; 19+ messages in thread
From: Sanjay Chitroda @ 2026-06-06 11:37 UTC (permalink / raw)
  To: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada, David Lechner,
	Nuno Sá, Andy Shevchenko, Archana Patni, Song Hongyan
  Cc: linux-input, linux-iio, linux-kernel, srinivas pandruvada,
	Sanjay Chitroda

Hi all,

This series fixes a race condition in HID IIO drivers related to the
ordering between callback registration and device exposure.

Currently, several HID IIO drivers register the IIO device (making it
visible to userspace and other kernel consumers) before all required
callbacks and resources are fully initialized, or rely on devm-based
cleanup in a way that does not guarantee correct teardown ordering.
This creates a window where the device can be accessed while it is
not fully initialized or is being torn down, potentially leading NULL
dereference or use-after-free.

To address this, the series ensures that:
  - All required callbacks and resources are set up before the device
    is registered with the IIO core
  - Resource cleanup is performed explicitly where ordering matters

PS: This is prepratory series to convert all HID IIO driver to devm.

Testing:
  - Compiled with W=1 for each patch in series
  - Build-tested on QEMU x86_64

---
Sanjay Chitroda (9):
      iio: orientation: hid-sensor-rotation: Fix race between callback registration and device exposure
      iio: orientation: hid-sensor-incl-3d: Fix race between callback registration and device exposure
      iio: gyro: hid-sensor-gyro-3d: Fix race between callback registration and device exposure
      iio: pressure: hid-sensor-press: Fix race between callback registration and device exposure
      iio: temperature: hid-sensor-temperature: switch to non-devm iio_device_register()
      iio: light: hid-sensor-prox: Fix race between callback registration and device exposure
      iio: light: hid-sensor-als: Fix race between callback registration and device exposure
      iio: magnetometer: hid-sensor-magn-3d: Fix race between callback registration and device exposure
      iio: accel: hid-sensor-accel-3d: Fix race between callback registration and device exposure

 drivers/iio/accel/hid-sensor-accel-3d.c          | 20 ++++++++++----------
 drivers/iio/gyro/hid-sensor-gyro-3d.c            | 20 ++++++++++----------
 drivers/iio/light/hid-sensor-als.c               | 20 ++++++++++----------
 drivers/iio/light/hid-sensor-prox.c              | 20 ++++++++++----------
 drivers/iio/magnetometer/hid-sensor-magn-3d.c    | 20 ++++++++++----------
 drivers/iio/orientation/hid-sensor-incl-3d.c     | 20 ++++++++++----------
 drivers/iio/orientation/hid-sensor-rotation.c    | 20 ++++++++++----------
 drivers/iio/pressure/hid-sensor-press.c          | 20 ++++++++++----------
 drivers/iio/temperature/hid-sensor-temperature.c |  3 ++-
 9 files changed, 82 insertions(+), 81 deletions(-)
---
base-commit: ae696dfa47c30016cd429b9db5e70b259b8f509e
change-id: 20260605-5-june-hid-iio-race-fixes-f8b981f82b80

Best regards,
--  
Sanjay Chitroda <sanjayembeddedse@gmail.com>


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

* [PATCH 1/9] iio: orientation: hid-sensor-rotation: Fix race between callback registration and device exposure
  2026-06-06 11:37 [PATCH 0/9] HID: iio: Fix race condition between callback registration and device exposure Sanjay Chitroda
@ 2026-06-06 11:37 ` Sanjay Chitroda
  2026-06-06 12:11   ` sashiko-bot
  2026-06-06 11:37 ` [PATCH 2/9] iio: orientation: hid-sensor-incl-3d: " Sanjay Chitroda
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Sanjay Chitroda @ 2026-06-06 11:37 UTC (permalink / raw)
  To: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada, David Lechner,
	Nuno Sá, Andy Shevchenko, Archana Patni, Song Hongyan
  Cc: linux-input, linux-iio, linux-kernel, srinivas pandruvada,
	Sanjay Chitroda

From: Sanjay Chitroda <sanjayembeddedse@gmail.com>

The driver registers the IIO device before completing sensor hub
callback registration and unregisters callbacks while the IIO device
is still exposed during teardown.

This creates race windows in both probe and remove paths, which can
lead to NULL pointer dereferences or use-after-free.

Fix this by correct ordering of callback registration and
IIO device registration in probe and remove paths.

Fixes: fc18dddc0625 ("iio: hid-sensors: Added device rotation support")
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
 drivers/iio/orientation/hid-sensor-rotation.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c
index 4a11e4555099..fd9beb93cefb 100644
--- a/drivers/iio/orientation/hid-sensor-rotation.c
+++ b/drivers/iio/orientation/hid-sensor-rotation.c
@@ -332,12 +332,6 @@ static int hid_dev_rot_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	ret = iio_device_register(indio_dev);
-	if (ret) {
-		dev_err(&pdev->dev, "device register failed\n");
-		goto error_remove_trigger;
-	}
-
 	rot_state->callbacks.send_event = dev_rot_proc_event;
 	rot_state->callbacks.capture_sample = dev_rot_capture_sample;
 	rot_state->callbacks.pdev = pdev;
@@ -345,13 +339,19 @@ static int hid_dev_rot_probe(struct platform_device *pdev)
 					&rot_state->callbacks);
 	if (ret) {
 		dev_err(&pdev->dev, "callback reg failed\n");
-		goto error_iio_unreg;
+		goto error_remove_trigger;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "device register failed\n");
+		goto error_remove_callback;
 	}
 
 	return 0;
 
-error_iio_unreg:
-	iio_device_unregister(indio_dev);
+error_remove_callback:
+	sensor_hub_remove_callback(hsdev, hsdev->usage);
 error_remove_trigger:
 	hid_sensor_remove_trigger(indio_dev, &rot_state->common_attributes);
 	return ret;
@@ -364,8 +364,8 @@ static void hid_dev_rot_remove(struct platform_device *pdev)
 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 	struct dev_rot_state *rot_state = iio_priv(indio_dev);
 
-	sensor_hub_remove_callback(hsdev, hsdev->usage);
 	iio_device_unregister(indio_dev);
+	sensor_hub_remove_callback(hsdev, hsdev->usage);
 	hid_sensor_remove_trigger(indio_dev, &rot_state->common_attributes);
 }
 

-- 
2.34.1


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

* [PATCH 2/9] iio: orientation: hid-sensor-incl-3d: Fix race between callback registration and device exposure
  2026-06-06 11:37 [PATCH 0/9] HID: iio: Fix race condition between callback registration and device exposure Sanjay Chitroda
  2026-06-06 11:37 ` [PATCH 1/9] iio: orientation: hid-sensor-rotation: Fix race " Sanjay Chitroda
@ 2026-06-06 11:37 ` Sanjay Chitroda
  2026-06-06 12:10   ` sashiko-bot
  2026-06-06 11:37 ` [PATCH 3/9] iio: gyro: hid-sensor-gyro-3d: " Sanjay Chitroda
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Sanjay Chitroda @ 2026-06-06 11:37 UTC (permalink / raw)
  To: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada, David Lechner,
	Nuno Sá, Andy Shevchenko, Archana Patni, Song Hongyan
  Cc: linux-input, linux-iio, linux-kernel, srinivas pandruvada,
	Sanjay Chitroda

From: Sanjay Chitroda <sanjayembeddedse@gmail.com>

The driver registers the IIO device before completing sensor hub
callback registration and unregisters callbacks while the IIO device
is still exposed during teardown.

This creates race windows in both probe and remove paths, which can
lead to NULL pointer dereferences or use-after-free.

Fix this by correct ordering of callback registration and
IIO device registration in probe and remove paths.

Fixes: 098d3beccfb6 ("iio: hid-sensors: Added Inclinometer 3D")
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
 drivers/iio/orientation/hid-sensor-incl-3d.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c
index 4e23a598a3fb..5e3d2bb9b5bf 100644
--- a/drivers/iio/orientation/hid-sensor-incl-3d.c
+++ b/drivers/iio/orientation/hid-sensor-incl-3d.c
@@ -356,12 +356,6 @@ static int hid_incl_3d_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	ret = iio_device_register(indio_dev);
-	if (ret) {
-		dev_err(&pdev->dev, "device register failed\n");
-		goto error_remove_trigger;
-	}
-
 	incl_state->callbacks.send_event = incl_3d_proc_event;
 	incl_state->callbacks.capture_sample = incl_3d_capture_sample;
 	incl_state->callbacks.pdev = pdev;
@@ -370,13 +364,19 @@ static int hid_incl_3d_probe(struct platform_device *pdev)
 					&incl_state->callbacks);
 	if (ret) {
 		dev_err(&pdev->dev, "callback reg failed\n");
-		goto error_iio_unreg;
+		goto error_remove_trigger;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "device register failed\n");
+		goto error_remove_callback;
 	}
 
 	return 0;
 
-error_iio_unreg:
-	iio_device_unregister(indio_dev);
+error_remove_callback:
+	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_INCLINOMETER_3D);
 error_remove_trigger:
 	hid_sensor_remove_trigger(indio_dev, &incl_state->common_attributes);
 	return ret;
@@ -389,8 +389,8 @@ static void hid_incl_3d_remove(struct platform_device *pdev)
 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 	struct incl_3d_state *incl_state = iio_priv(indio_dev);
 
-	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_INCLINOMETER_3D);
 	iio_device_unregister(indio_dev);
+	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_INCLINOMETER_3D);
 	hid_sensor_remove_trigger(indio_dev, &incl_state->common_attributes);
 }
 

-- 
2.34.1


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

* [PATCH 3/9] iio: gyro: hid-sensor-gyro-3d: Fix race between callback registration and device exposure
  2026-06-06 11:37 [PATCH 0/9] HID: iio: Fix race condition between callback registration and device exposure Sanjay Chitroda
  2026-06-06 11:37 ` [PATCH 1/9] iio: orientation: hid-sensor-rotation: Fix race " Sanjay Chitroda
  2026-06-06 11:37 ` [PATCH 2/9] iio: orientation: hid-sensor-incl-3d: " Sanjay Chitroda
@ 2026-06-06 11:37 ` Sanjay Chitroda
  2026-06-06 12:13   ` sashiko-bot
  2026-06-06 11:37 ` [PATCH 4/9] iio: pressure: hid-sensor-press: " Sanjay Chitroda
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Sanjay Chitroda @ 2026-06-06 11:37 UTC (permalink / raw)
  To: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada, David Lechner,
	Nuno Sá, Andy Shevchenko, Archana Patni, Song Hongyan
  Cc: linux-input, linux-iio, linux-kernel, srinivas pandruvada,
	Sanjay Chitroda

From: Sanjay Chitroda <sanjayembeddedse@gmail.com>

The driver registers the IIO device before completing sensor hub
callback registration and unregisters callbacks while the IIO device
is still exposed during teardown.

This creates race windows in both probe and remove paths, which can
lead to NULL pointer dereferences or use-after-free.

Fix this by correct ordering of callback registration and
IIO device registration in probe and remove paths.

Fixes: c5bdbef704ba ("iio: hid-sensors: Added Gyroscope 3D")
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
 drivers/iio/gyro/hid-sensor-gyro-3d.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
index e48c25c87b6d..dd871eacdaf4 100644
--- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
+++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
@@ -324,12 +324,6 @@ static int hid_gyro_3d_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	ret = iio_device_register(indio_dev);
-	if (ret) {
-		dev_err(&pdev->dev, "device register failed\n");
-		goto error_remove_trigger;
-	}
-
 	gyro_state->callbacks.send_event = gyro_3d_proc_event;
 	gyro_state->callbacks.capture_sample = gyro_3d_capture_sample;
 	gyro_state->callbacks.pdev = pdev;
@@ -337,13 +331,19 @@ static int hid_gyro_3d_probe(struct platform_device *pdev)
 					&gyro_state->callbacks);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "callback reg failed\n");
-		goto error_iio_unreg;
+		goto error_remove_trigger;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "device register failed\n");
+		goto error_remove_callback;
 	}
 
 	return ret;
 
-error_iio_unreg:
-	iio_device_unregister(indio_dev);
+error_remove_callback:
+	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_GYRO_3D);
 error_remove_trigger:
 	hid_sensor_remove_trigger(indio_dev, &gyro_state->common_attributes);
 	return ret;
@@ -356,8 +356,8 @@ static void hid_gyro_3d_remove(struct platform_device *pdev)
 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 	struct gyro_3d_state *gyro_state = iio_priv(indio_dev);
 
-	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_GYRO_3D);
 	iio_device_unregister(indio_dev);
+	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_GYRO_3D);
 	hid_sensor_remove_trigger(indio_dev, &gyro_state->common_attributes);
 }
 

-- 
2.34.1


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

* [PATCH 4/9] iio: pressure: hid-sensor-press: Fix race between callback registration and device exposure
  2026-06-06 11:37 [PATCH 0/9] HID: iio: Fix race condition between callback registration and device exposure Sanjay Chitroda
                   ` (2 preceding siblings ...)
  2026-06-06 11:37 ` [PATCH 3/9] iio: gyro: hid-sensor-gyro-3d: " Sanjay Chitroda
@ 2026-06-06 11:37 ` Sanjay Chitroda
  2026-06-06 11:50   ` sashiko-bot
  2026-06-06 11:37 ` [PATCH 5/9] iio: temperature: hid-sensor-temperature: switch to non-devm iio_device_register() Sanjay Chitroda
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Sanjay Chitroda @ 2026-06-06 11:37 UTC (permalink / raw)
  To: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada, David Lechner,
	Nuno Sá, Andy Shevchenko, Archana Patni, Song Hongyan
  Cc: linux-input, linux-iio, linux-kernel, srinivas pandruvada,
	Sanjay Chitroda

From: Sanjay Chitroda <sanjayembeddedse@gmail.com>

The driver registers the IIO device before completing sensor hub
callback registration and unregisters callbacks while the IIO device
is still exposed during teardown.

This creates race windows in both probe and remove paths, which can
lead to NULL pointer dereferences or use-after-free.

Fix this by correct ordering of callback registration and
IIO device registration in probe and remove paths.

Fixes: f64a799b8a49 ("iio: hid-sensors: Added Pressure Sensor driver")
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
 drivers/iio/pressure/hid-sensor-press.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c
index a039b99d9851..09795473948a 100644
--- a/drivers/iio/pressure/hid-sensor-press.c
+++ b/drivers/iio/pressure/hid-sensor-press.c
@@ -291,12 +291,6 @@ static int hid_press_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	ret = iio_device_register(indio_dev);
-	if (ret) {
-		dev_err(&pdev->dev, "device register failed\n");
-		goto error_remove_trigger;
-	}
-
 	press_state->callbacks.send_event = press_proc_event;
 	press_state->callbacks.capture_sample = press_capture_sample;
 	press_state->callbacks.pdev = pdev;
@@ -304,13 +298,19 @@ static int hid_press_probe(struct platform_device *pdev)
 					&press_state->callbacks);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "callback reg failed\n");
-		goto error_iio_unreg;
+		goto error_remove_trigger;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "device register failed\n");
+		goto error_remove_callback;
 	}
 
 	return ret;
 
-error_iio_unreg:
-	iio_device_unregister(indio_dev);
+error_remove_callback:
+	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_PRESSURE);
 error_remove_trigger:
 	hid_sensor_remove_trigger(indio_dev, &press_state->common_attributes);
 	return ret;
@@ -323,8 +323,8 @@ static void hid_press_remove(struct platform_device *pdev)
 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 	struct press_state *press_state = iio_priv(indio_dev);
 
-	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_PRESSURE);
 	iio_device_unregister(indio_dev);
+	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_PRESSURE);
 	hid_sensor_remove_trigger(indio_dev, &press_state->common_attributes);
 }
 

-- 
2.34.1


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

* [PATCH 5/9] iio: temperature: hid-sensor-temperature: switch to non-devm iio_device_register()
  2026-06-06 11:37 [PATCH 0/9] HID: iio: Fix race condition between callback registration and device exposure Sanjay Chitroda
                   ` (3 preceding siblings ...)
  2026-06-06 11:37 ` [PATCH 4/9] iio: pressure: hid-sensor-press: " Sanjay Chitroda
@ 2026-06-06 11:37 ` Sanjay Chitroda
  2026-06-06 12:09   ` sashiko-bot
  2026-06-06 11:37 ` [PATCH 6/9] iio: light: hid-sensor-prox: Fix race between callback registration and device exposure Sanjay Chitroda
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Sanjay Chitroda @ 2026-06-06 11:37 UTC (permalink / raw)
  To: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada, David Lechner,
	Nuno Sá, Andy Shevchenko, Archana Patni, Song Hongyan
  Cc: linux-input, linux-iio, linux-kernel, srinivas pandruvada,
	Sanjay Chitroda

From: Sanjay Chitroda <sanjayembeddedse@gmail.com>

Avoid using devm_iio_device_register() as this driver requires explicit
error handling paths. Mixing devm_* APIs with goto-based unwinding
breaks the expected LIFO resource release model and may introduce race
windows during teardown, potentially leading to use-after-free issues.

Add explicit iio_device_unregister() call in the teardown path to ensure
deterministic cleanup and follow kernel resource management conventions.

Fixes: 59d0f2da3569 ("iio: hid: Add temperature sensor support")
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
 drivers/iio/temperature/hid-sensor-temperature.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/temperature/hid-sensor-temperature.c b/drivers/iio/temperature/hid-sensor-temperature.c
index 9f628a8e5cfb..34bff7e9f3a3 100644
--- a/drivers/iio/temperature/hid-sensor-temperature.c
+++ b/drivers/iio/temperature/hid-sensor-temperature.c
@@ -244,7 +244,7 @@ static int hid_temperature_probe(struct platform_device *pdev)
 	if (ret)
 		goto error_remove_trigger;
 
-	ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret)
 		goto error_remove_callback;
 
@@ -264,6 +264,7 @@ static void hid_temperature_remove(struct platform_device *pdev)
 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 	struct temperature_state *temp_st = iio_priv(indio_dev);
 
+	iio_device_unregister(indio_dev);
 	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TEMPERATURE);
 	hid_sensor_remove_trigger(indio_dev, &temp_st->common_attributes);
 }

-- 
2.34.1


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

* [PATCH 6/9] iio: light: hid-sensor-prox: Fix race between callback registration and device exposure
  2026-06-06 11:37 [PATCH 0/9] HID: iio: Fix race condition between callback registration and device exposure Sanjay Chitroda
                   ` (4 preceding siblings ...)
  2026-06-06 11:37 ` [PATCH 5/9] iio: temperature: hid-sensor-temperature: switch to non-devm iio_device_register() Sanjay Chitroda
@ 2026-06-06 11:37 ` Sanjay Chitroda
  2026-06-06 12:13   ` sashiko-bot
  2026-06-06 11:37 ` [PATCH 7/9] iio: light: hid-sensor-als: " Sanjay Chitroda
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Sanjay Chitroda @ 2026-06-06 11:37 UTC (permalink / raw)
  To: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada, David Lechner,
	Nuno Sá, Andy Shevchenko, Archana Patni, Song Hongyan
  Cc: linux-input, linux-iio, linux-kernel, srinivas pandruvada,
	Sanjay Chitroda

From: Sanjay Chitroda <sanjayembeddedse@gmail.com>

The driver registers the IIO device before completing sensor hub
callback registration and unregisters callbacks while the IIO device
is still exposed during teardown.

This creates race windows in both probe and remove paths, which can
lead to NULL pointer dereferences or use-after-free.

Fix this by correct ordering of callback registration and
IIO device registration in probe and remove paths.

Fixes: 39a3a0138f61 ("iio: hid-sensors: Added Proximity Sensor Driver")
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
 drivers/iio/light/hid-sensor-prox.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c
index edc9274a2c07..3df7f28d3b44 100644
--- a/drivers/iio/light/hid-sensor-prox.c
+++ b/drivers/iio/light/hid-sensor-prox.c
@@ -312,12 +312,6 @@ static int hid_prox_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	ret = iio_device_register(indio_dev);
-	if (ret) {
-		dev_err(&pdev->dev, "device register failed\n");
-		goto error_remove_trigger;
-	}
-
 	prox_state->callbacks.send_event = prox_proc_event;
 	prox_state->callbacks.capture_sample = prox_capture_sample;
 	prox_state->callbacks.pdev = pdev;
@@ -325,13 +319,19 @@ static int hid_prox_probe(struct platform_device *pdev)
 					   &prox_state->callbacks);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "callback reg failed\n");
-		goto error_iio_unreg;
+		goto error_remove_trigger;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "device register failed\n");
+		goto error_remove_callback;
 	}
 
 	return ret;
 
-error_iio_unreg:
-	iio_device_unregister(indio_dev);
+error_remove_callback:
+	sensor_hub_remove_callback(hsdev, hsdev->usage);
 error_remove_trigger:
 	hid_sensor_remove_trigger(indio_dev, &prox_state->common_attributes);
 	return ret;
@@ -344,8 +344,8 @@ static void hid_prox_remove(struct platform_device *pdev)
 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 	struct prox_state *prox_state = iio_priv(indio_dev);
 
-	sensor_hub_remove_callback(hsdev, hsdev->usage);
 	iio_device_unregister(indio_dev);
+	sensor_hub_remove_callback(hsdev, hsdev->usage);
 	hid_sensor_remove_trigger(indio_dev, &prox_state->common_attributes);
 }
 

-- 
2.34.1


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

* [PATCH 7/9] iio: light: hid-sensor-als: Fix race between callback registration and device exposure
  2026-06-06 11:37 [PATCH 0/9] HID: iio: Fix race condition between callback registration and device exposure Sanjay Chitroda
                   ` (5 preceding siblings ...)
  2026-06-06 11:37 ` [PATCH 6/9] iio: light: hid-sensor-prox: Fix race between callback registration and device exposure Sanjay Chitroda
@ 2026-06-06 11:37 ` Sanjay Chitroda
  2026-06-06 12:11   ` sashiko-bot
  2026-06-06 11:37 ` [PATCH 8/9] iio: magnetometer: hid-sensor-magn-3d: " Sanjay Chitroda
  2026-06-06 11:37 ` [PATCH 9/9] iio: accel: hid-sensor-accel-3d: " Sanjay Chitroda
  8 siblings, 1 reply; 19+ messages in thread
From: Sanjay Chitroda @ 2026-06-06 11:37 UTC (permalink / raw)
  To: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada, David Lechner,
	Nuno Sá, Andy Shevchenko, Archana Patni, Song Hongyan
  Cc: linux-input, linux-iio, linux-kernel, srinivas pandruvada,
	Sanjay Chitroda

From: Sanjay Chitroda <sanjayembeddedse@gmail.com>

The driver registers the IIO device before completing sensor hub
callback registration and unregisters callbacks while the IIO device
is still exposed during teardown.

This creates race windows in both probe and remove paths, which can
lead to NULL pointer dereferences or use-after-free.

Fix this by correct ordering of callback registration and
IIO device registration in probe and remove paths.

Fixes: ed5514c925a0 ("iio: hid-sensors: Added ALS")
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
 drivers/iio/light/hid-sensor-als.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
index d72e260b8266..93d603848690 100644
--- a/drivers/iio/light/hid-sensor-als.c
+++ b/drivers/iio/light/hid-sensor-als.c
@@ -406,25 +406,25 @@ static int hid_als_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	ret = iio_device_register(indio_dev);
-	if (ret) {
-		dev_err(&pdev->dev, "device register failed\n");
-		goto error_remove_trigger;
-	}
-
 	als_state->callbacks.send_event = als_proc_event;
 	als_state->callbacks.capture_sample = als_capture_sample;
 	als_state->callbacks.pdev = pdev;
 	ret = sensor_hub_register_callback(hsdev, hsdev->usage, &als_state->callbacks);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "callback reg failed\n");
-		goto error_iio_unreg;
+		goto error_remove_trigger;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "device register failed\n");
+		goto error_remove_callback;
 	}
 
 	return ret;
 
-error_iio_unreg:
-	iio_device_unregister(indio_dev);
+error_remove_callback:
+	sensor_hub_remove_callback(hsdev, hsdev->usage);
 error_remove_trigger:
 	hid_sensor_remove_trigger(indio_dev, &als_state->common_attributes);
 	return ret;
@@ -437,8 +437,8 @@ static void hid_als_remove(struct platform_device *pdev)
 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 	struct als_state *als_state = iio_priv(indio_dev);
 
-	sensor_hub_remove_callback(hsdev, hsdev->usage);
 	iio_device_unregister(indio_dev);
+	sensor_hub_remove_callback(hsdev, hsdev->usage);
 	hid_sensor_remove_trigger(indio_dev, &als_state->common_attributes);
 }
 

-- 
2.34.1


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

* [PATCH 8/9] iio: magnetometer: hid-sensor-magn-3d: Fix race between callback registration and device exposure
  2026-06-06 11:37 [PATCH 0/9] HID: iio: Fix race condition between callback registration and device exposure Sanjay Chitroda
                   ` (6 preceding siblings ...)
  2026-06-06 11:37 ` [PATCH 7/9] iio: light: hid-sensor-als: " Sanjay Chitroda
@ 2026-06-06 11:37 ` Sanjay Chitroda
  2026-06-06 12:10   ` sashiko-bot
  2026-06-06 11:37 ` [PATCH 9/9] iio: accel: hid-sensor-accel-3d: " Sanjay Chitroda
  8 siblings, 1 reply; 19+ messages in thread
From: Sanjay Chitroda @ 2026-06-06 11:37 UTC (permalink / raw)
  To: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada, David Lechner,
	Nuno Sá, Andy Shevchenko, Archana Patni, Song Hongyan
  Cc: linux-input, linux-iio, linux-kernel, srinivas pandruvada,
	Sanjay Chitroda

From: Sanjay Chitroda <sanjayembeddedse@gmail.com>

The driver registers the IIO device before completing sensor hub
callback registration and unregisters callbacks while the IIO device
is still exposed during teardown.

This creates race windows in both probe and remove paths, which can
lead to NULL pointer dereferences or use-after-free.

Fix this by correct ordering of callback registration and
IIO device registration in probe and remove paths.

Fixes: bc1d57ba0669 ("iio: hid-sensors: Added Compass/Magnetometer 3D")
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
 drivers/iio/magnetometer/hid-sensor-magn-3d.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
index 23884825eb00..acae77273bd5 100644
--- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
+++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
@@ -513,12 +513,6 @@ static int hid_magn_3d_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	ret = iio_device_register(indio_dev);
-	if (ret) {
-		dev_err(&pdev->dev, "device register failed\n");
-		goto error_remove_trigger;
-	}
-
 	magn_state->callbacks.send_event = magn_3d_proc_event;
 	magn_state->callbacks.capture_sample = magn_3d_capture_sample;
 	magn_state->callbacks.pdev = pdev;
@@ -526,13 +520,19 @@ static int hid_magn_3d_probe(struct platform_device *pdev)
 					&magn_state->callbacks);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "callback reg failed\n");
-		goto error_iio_unreg;
+		goto error_remove_trigger;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "device register failed\n");
+		goto error_remove_callback;
 	}
 
 	return ret;
 
-error_iio_unreg:
-	iio_device_unregister(indio_dev);
+error_remove_callback:
+	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_COMPASS_3D);
 error_remove_trigger:
 	hid_sensor_remove_trigger(indio_dev, &magn_state->magn_flux_attributes);
 	return ret;
@@ -545,8 +545,8 @@ static void hid_magn_3d_remove(struct platform_device *pdev)
 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 	struct magn_3d_state *magn_state = iio_priv(indio_dev);
 
-	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_COMPASS_3D);
 	iio_device_unregister(indio_dev);
+	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_COMPASS_3D);
 	hid_sensor_remove_trigger(indio_dev, &magn_state->magn_flux_attributes);
 }
 

-- 
2.34.1


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

* [PATCH 9/9] iio: accel: hid-sensor-accel-3d: Fix race between callback registration and device exposure
  2026-06-06 11:37 [PATCH 0/9] HID: iio: Fix race condition between callback registration and device exposure Sanjay Chitroda
                   ` (7 preceding siblings ...)
  2026-06-06 11:37 ` [PATCH 8/9] iio: magnetometer: hid-sensor-magn-3d: " Sanjay Chitroda
@ 2026-06-06 11:37 ` Sanjay Chitroda
  2026-06-06 12:13   ` sashiko-bot
  8 siblings, 1 reply; 19+ messages in thread
From: Sanjay Chitroda @ 2026-06-06 11:37 UTC (permalink / raw)
  To: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada, David Lechner,
	Nuno Sá, Andy Shevchenko, Archana Patni, Song Hongyan
  Cc: linux-input, linux-iio, linux-kernel, srinivas pandruvada,
	Sanjay Chitroda

From: Sanjay Chitroda <sanjayembeddedse@gmail.com>

The driver registers the IIO device before completing sensor hub
callback registration and unregisters callbacks while the IIO device
is still exposed during teardown.

This creates race windows in both probe and remove paths, which can
lead to NULL pointer dereferences or use-after-free.

Fix this by correct ordering of callback registration and
IIO device registration in probe and remove paths.

Fixes: 45fe6f7d002c ("iio: hid-sensors: Added accelerometer 3D")
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
 drivers/iio/accel/hid-sensor-accel-3d.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
index 2bf05ab5235e..c000e001c001 100644
--- a/drivers/iio/accel/hid-sensor-accel-3d.c
+++ b/drivers/iio/accel/hid-sensor-accel-3d.c
@@ -386,12 +386,6 @@ static int hid_accel_3d_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	ret = iio_device_register(indio_dev);
-	if (ret) {
-		dev_err(&pdev->dev, "device register failed\n");
-		goto error_remove_trigger;
-	}
-
 	accel_state->callbacks.send_event = accel_3d_proc_event;
 	accel_state->callbacks.capture_sample = accel_3d_capture_sample;
 	accel_state->callbacks.pdev = pdev;
@@ -399,13 +393,19 @@ static int hid_accel_3d_probe(struct platform_device *pdev)
 					&accel_state->callbacks);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "callback reg failed\n");
-		goto error_iio_unreg;
+		goto error_remove_trigger;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "device register failed\n");
+		goto error_remove_callback;
 	}
 
 	return ret;
 
-error_iio_unreg:
-	iio_device_unregister(indio_dev);
+error_remove_callback:
+	sensor_hub_remove_callback(hsdev, hsdev->usage);
 error_remove_trigger:
 	hid_sensor_remove_trigger(indio_dev, &accel_state->common_attributes);
 	return ret;
@@ -418,8 +418,8 @@ static void hid_accel_3d_remove(struct platform_device *pdev)
 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 	struct accel_3d_state *accel_state = iio_priv(indio_dev);
 
-	sensor_hub_remove_callback(hsdev, hsdev->usage);
 	iio_device_unregister(indio_dev);
+	sensor_hub_remove_callback(hsdev, hsdev->usage);
 	hid_sensor_remove_trigger(indio_dev, &accel_state->common_attributes);
 }
 

-- 
2.34.1


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

* Re: [PATCH 4/9] iio: pressure: hid-sensor-press: Fix race between callback registration and device exposure
  2026-06-06 11:37 ` [PATCH 4/9] iio: pressure: hid-sensor-press: " Sanjay Chitroda
@ 2026-06-06 11:50   ` sashiko-bot
  0 siblings, 0 replies; 19+ messages in thread
From: sashiko-bot @ 2026-06-06 11:50 UTC (permalink / raw)
  To: Sanjay Chitroda; +Cc: dmitry.torokhov, linux-input

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

New issues:
- [Critical] Reordering teardown introduces list corruption and UAF via concurrent buffer access.

Pre-existing issues:
- [High] This problem wasn't introduced by this patch, but the lack of synchronization in sensor hub callback removal leads to Use-After-Free, and this patch exposes the race on the probe error path.
--

commit 82bc619c3ad12fb028f336e0c55f37d3a740bf6e
Author: Sanjay Chitroda <sanjayembeddedse@gmail.com>

iio: pressure: hid-sensor-press: Fix race between callback registration and device exposure

The driver registers the IIO device before completing sensor hub
callback registration and unregisters callbacks while the IIO device
is still exposed during teardown. This patch reorders callback
registration and IIO device registration in probe and remove paths.

> diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c
> index a039b99d9851d..09795473948a9 100644
> --- a/drivers/iio/pressure/hid-sensor-press.c
> +++ b/drivers/iio/pressure/hid-sensor-press.c
[ ... ]
> @@ -304,13 +298,19 @@ static int hid_press_probe(struct platform_device *pdev)
>  					&press_state->callbacks);
>  	if (ret < 0) {
>  		dev_err(&pdev->dev, "callback reg failed\n");
> -		goto error_iio_unreg;
> +		goto error_remove_trigger;
> +	}
> +
> +	ret = iio_device_register(indio_dev);
> +	if (ret) {
> +		dev_err(&pdev->dev, "device register failed\n");
> +		goto error_remove_callback;
>  	}
>  
>  	return ret;
>  
> -error_iio_unreg:
> -	iio_device_unregister(indio_dev);
> +error_remove_callback:
> +	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_PRESSURE);

[Severity: High]
This is a pre-existing issue, but the lack of synchronization in sensor
hub callback removal might lead to a use-after-free, and this patch
exposes it on the probe error path.

When sensor_hub_remove_callback() deletes the list entry:

drivers/hid/hid-sensor-hub.c:sensor_hub_remove_callback() {
    list_del(&callback->list);
    kfree(callback);
    ...
}

it doesn't appear to wait for active readers to finish processing. If
iio_device_register() fails, the driver calls sensor_hub_remove_callback()
and returns, allowing devres to free the press_state memory. 

Could a suspended or delayed sensor_hub_raw_event() thread resume and
dereference the freed memory?

>  error_remove_trigger:
>  	hid_sensor_remove_trigger(indio_dev, &press_state->common_attributes);
>  	return ret;
> @@ -323,8 +323,8 @@ static void hid_press_remove(struct platform_device *pdev)
>  	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
>  	struct press_state *press_state = iio_priv(indio_dev);
>  
> -	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_PRESSURE);
>  	iio_device_unregister(indio_dev);
> +	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_PRESSURE);

[Severity: Critical]
Does this reversed teardown order introduce list corruption or a
use-after-free through concurrent buffer access?

By calling iio_device_unregister() before removing the sensor hub
callback, incoming HID events can still trigger press_proc_event().
This locklessly pushes to buffers:

drivers/iio/pressure/hid-sensor-press.c:press_proc_event()
  iio_push_to_buffers_with_ts()
    iio_push_to_buffers()
      list_for_each_entry(buf, &iio_dev_opaque->buffer_list, buffer_list)

While this runs, iio_device_unregister() actively removes buffers
from the list:

iio_device_unregister()
  iio_disable_all_buffers()
    list_del_init()

Could iterating over the buffer list while it is being modified by
list_del_init() cause the lockless reader to follow the self-referential
next pointer, leading to an infinite loop or use-after-free?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260606-5-june-hid-iio-race-fixes-v1-0-27a848c5758f@gmail.com?part=4

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

* Re: [PATCH 5/9] iio: temperature: hid-sensor-temperature: switch to non-devm iio_device_register()
  2026-06-06 11:37 ` [PATCH 5/9] iio: temperature: hid-sensor-temperature: switch to non-devm iio_device_register() Sanjay Chitroda
@ 2026-06-06 12:09   ` sashiko-bot
  0 siblings, 0 replies; 19+ messages in thread
From: sashiko-bot @ 2026-06-06 12:09 UTC (permalink / raw)
  To: Sanjay Chitroda; +Cc: linux-input, dmitry.torokhov

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

New issues:
- [High] Explicitly calling `iio_device_unregister()` before stopping the hardware data source causes a hard lockup.

Pre-existing issues:
- [High] The driver uses a single global static `struct hid_sensor_hub_callbacks temperature_callbacks` which is modified during `probe()`. If multiple temperature sensors are probed, the `pdev` pointer within this global struct is overwritten by the most recently probed device. This causes events from all sensors to be routed to the last probed sensor's IIO device, leading to data corruption. Furthermore, if a sensor is removed, the remaining sensors will dereference a dangling `pdev` pointer when handling events, causing a Use-After-Free.
- [High] The sensor hub remove callback lacks synchronization with active event processing, leading to use-after-free on module unload or device unbind.
--

commit 40b43e4e8d671ec0d491c5e0ebefd5ffcf97e7ad
Author: Sanjay Chitroda <sanjayembeddedse@gmail.com>

iio: temperature: hid-sensor-temperature: switch to non-devm iio_device_register()

This commit switches from devm_iio_device_register() to the non-devm
iio_device_register() to avoid mixing devm APIs with goto-based unwinding.
It adds an explicit iio_device_unregister() call in the teardown path to
ensure deterministic cleanup.

> diff --git a/drivers/iio/temperature/hid-sensor-temperature.c b/drivers/iio/temperature/hid-sensor-temperature.c
> index 9f628a8e5cfbe..34bff7e9f3a33 100644
> --- a/drivers/iio/temperature/hid-sensor-temperature.c
> +++ b/drivers/iio/temperature/hid-sensor-temperature.c
> @@ -244,7 +244,7 @@ static int hid_temperature_probe(struct platform_device *pdev)
>  	if (ret)
>  		goto error_remove_trigger;
>  
> -	ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev);
> +	ret = iio_device_register(indio_dev);

[Severity: High]
This isn't a bug introduced by this patch, but does the driver use a
single global static struct hid_sensor_hub_callbacks temperature_callbacks
which is modified during probe()?

If multiple temperature sensors are probed, the pdev pointer within this
global struct is overwritten by the most recently probed device:

drivers/iio/temperature/hid-sensor-temperature.c:hid_temperature_probe() {
        ...
        temperature_callbacks.pdev = pdev;
        ret = sensor_hub_register_callback(hsdev,
                                        HID_USAGE_SENSOR_TEMPERATURE,
                                        &temperature_callbacks);
        ...
}

This causes events from all sensors to be routed to the last probed sensor's
IIO device, leading to data corruption.

Furthermore, if a sensor is removed, the remaining sensors will dereference
a dangling pdev pointer when handling events, causing a use-after-free.

>  	if (ret)
>  		goto error_remove_callback;
>  

[ ... ]

> @@ -264,6 +264,7 @@ static void hid_temperature_remove(struct platform_device *pdev)
>  	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
>  	struct temperature_state *temp_st = iio_priv(indio_dev);
>  
> +	iio_device_unregister(indio_dev);

[Severity: High]
Does explicitly calling iio_device_unregister() before stopping the
hardware data source cause a hard lockup?

The modified teardown order unregisters the IIO device before the sensor
hub callback is removed. This function deletes the buffer from the IIO core
buffer list.

Concurrently, incoming hardware interrupts can invoke
temperature_proc_event() which locklessly iterates over the same buffer
list using list_for_each_entry().

If list_del_init() executes concurrently during the iteration, the lockless
traversal can enter an infinite loop. Because the event handler executes
with IRQs disabled, this could cause a hard lockup.

>  	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TEMPERATURE);

[Severity: High]
This is a pre-existing issue, but does sensor_hub_remove_callback() lack
synchronization with active event processing?

When sensor_hub_remove_callback() unlinks the callback from
dyn_callback_list, it returns immediately without waiting for concurrent
executions of sensor_hub_raw_event() to finish.

Since the raw event handler drops dyn_callback_lock before executing the
callbacks, remove() can complete and trigger devres cleanup while the raw
event handler is still actively dereferencing the IIO device on another
CPU, potentially leading to a use-after-free.

>  	hid_sensor_remove_trigger(indio_dev, &temp_st->common_attributes);
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260606-5-june-hid-iio-race-fixes-v1-0-27a848c5758f@gmail.com?part=5

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

* Re: [PATCH 2/9] iio: orientation: hid-sensor-incl-3d: Fix race between callback registration and device exposure
  2026-06-06 11:37 ` [PATCH 2/9] iio: orientation: hid-sensor-incl-3d: " Sanjay Chitroda
@ 2026-06-06 12:10   ` sashiko-bot
  0 siblings, 0 replies; 19+ messages in thread
From: sashiko-bot @ 2026-06-06 12:10 UTC (permalink / raw)
  To: Sanjay Chitroda; +Cc: linux-input, dmitry.torokhov

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

New issues:
- [High] The patch introduces a Use-After-Free (UAF) vulnerability in the probe error path by registering the sensor hub callback before completing IIO device registration.
- [High] The patch inverts the teardown order in the remove path, leaving the HID callback active during IIO buffer teardown, which leads to lockless list corruption or Use-After-Free.

Pre-existing issues:
- [High] The driver suffers from a pre-existing Use-After-Free vulnerability during device removal because `sensor_hub_remove_callback()` does not synchronize with currently executing HID callbacks.
--

commit 7127797d9af9cf3f6a23d56c71b46a308c88b097
Author: Sanjay Chitroda <sanjayembeddedse@gmail.com>

iio: orientation: hid-sensor-incl-3d: Fix race between callback registration and device exposure

This commit modifies the probe and remove paths in the HID 3D inclinometer
driver to adjust the registration order between the IIO device and the sensor
hub callbacks. It attempts to fix a race condition by registering callbacks
before the IIO device in the probe function, and unregistering the IIO device
before removing callbacks in the remove function.

> diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c
> --- a/drivers/iio/orientation/hid-sensor-incl-3d.c
> +++ b/drivers/iio/orientation/hid-sensor-incl-3d.c
[ ... ]
> @@ -370,13 +364,19 @@ static int hid_incl_3d_probe(struct platform_device *pdev)
>  					&incl_state->callbacks);
>  	if (ret) {
>  		dev_err(&pdev->dev, "callback reg failed\n");
> -		goto error_iio_unreg;
> +		goto error_remove_trigger;
> +	}
> +
> +	ret = iio_device_register(indio_dev);
> +	if (ret) {
> +		dev_err(&pdev->dev, "device register failed\n");
> +		goto error_remove_callback;
>  	}
>  
>  	return 0;
>  
> -error_iio_unreg:
> -	iio_device_unregister(indio_dev);
> +error_remove_callback:
> +	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_INCLINOMETER_3D);

[Severity: High]
Does this error path introduce a use-after-free regression?

By registering the callback before IIO device registration completes, the HID
event callback is added to the active list and can dispatch events
asynchronously immediately.

If iio_device_register() fails, the error path calls
sensor_hub_remove_callback(). However, this function only deletes the
callback from a lock-protected list and does not synchronize with
concurrently executing callbacks:

drivers/hid/hid-sensor-hub.c:sensor_hub_raw_event() {
    ...
    if (callback && collection && callback->send_event)
        callback->send_event(hsdev, collection->usage, callback->pdev);
    ...
}

When the probe function returns, the devres subsystem will free the indio_dev
memory which contains the callbacks structure.

If a concurrent HID event was dispatched just before the callback was
removed, could it locklessly dereference the freed callback->send_event
function pointer?

>  error_remove_trigger:
>  	hid_sensor_remove_trigger(indio_dev, &incl_state->common_attributes);
>  	return ret;
[ ... ]
> @@ -389,8 +389,8 @@ static void hid_incl_3d_remove(struct platform_device *pdev)
>  	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
>  	struct incl_3d_state *incl_state = iio_priv(indio_dev);
>  
> -	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_INCLINOMETER_3D);
>  	iio_device_unregister(indio_dev);
> +	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_INCLINOMETER_3D);

[Severity: High]
Might this inverted teardown order cause list corruption or a use-after-free?

By leaving the HID callback active during IIO device unregistration, the
hardware event source remains active while dismantling structures.

When iio_device_unregister() disables buffers, it removes them from
indio_dev->buffer_list using list_del_init() without holding locks that
protect the push path.

If other sensors keep the shared HID hub active, events for this sensor can
arrive concurrently. The event handler calls iio_push_to_buffers(), which
iterates locklessly:

drivers/iio/industrialio-buffer.c:iio_push_to_buffers() {
    ...
    list_for_each_entry(buf, &iio_dev_opaque->buffer_list, buffer_list) {
        ret = iio_push_to_buffer(buf, data);
    ...
}

If these race, could the concurrent modification result in list corruption or
dereferencing freed buffers?

[Severity: High]
This is a pre-existing issue, but does sensor_hub_remove_callback() properly
synchronize with executing HID callbacks before device removal completes?

Looking at the implementation, sensor_hub_remove_callback() removes the
callback from a lock-protected list and returns immediately:

drivers/hid/hid-sensor-hub.c:sensor_hub_remove_callback() {
    ...
    list_del(&callback->list);
    kfree(callback);
    break;
    ...
}

It does not wait for any actively running callbacks in sensor_hub_raw_event()
to finish. Once hid_incl_3d_remove() completes, devres frees the indio_dev
memory containing the incl_state and its callbacks.

If the HID event thread is still executing the callback locklessly, might it
dereference a freed function pointer and access freed memory?

>  	hid_sensor_remove_trigger(indio_dev, &incl_state->common_attributes);
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260606-5-june-hid-iio-race-fixes-v1-0-27a848c5758f@gmail.com?part=2

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

* Re: [PATCH 8/9] iio: magnetometer: hid-sensor-magn-3d: Fix race between callback registration and device exposure
  2026-06-06 11:37 ` [PATCH 8/9] iio: magnetometer: hid-sensor-magn-3d: " Sanjay Chitroda
@ 2026-06-06 12:10   ` sashiko-bot
  0 siblings, 0 replies; 19+ messages in thread
From: sashiko-bot @ 2026-06-06 12:10 UTC (permalink / raw)
  To: Sanjay Chitroda; +Cc: dmitry.torokhov, linux-input

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

New issues:
- [Critical] Reordering `iio_device_unregister()` before `sensor_hub_remove_callback()` in the remove path introduces a critical list corruption race.
- [High] Reordering callback registration before IIO device registration introduces a Use-After-Free (UAF) window on the probe error path.

Pre-existing issues:
- [High] Pre-existing Use-After-Free vulnerability because `sensor_hub_remove_callback()` unlinks the callback without synchronizing with currently executing asynchronous HID events.
--

commit b4969e9293deed992cb095faf4c58a2ab65c8d1e
Author: Sanjay Chitroda <sanjayembeddedse@gmail.com>

iio: magnetometer: hid-sensor-magn-3d: Fix race between callback registration and device exposure

This patch attempts to fix a race condition by reordering the callback
registration and IIO device registration in the probe and remove paths.
It registers the sensor hub callback before exposing the IIO device, and
unregisters the IIO device before removing the callbacks.

> diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
> index 23884825eb00f..acae77273bd5e 100644
> --- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
> +++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
[ ... ]
> @@ -526,13 +520,19 @@ static int hid_magn_3d_probe(struct platform_device *pdev)
>  					&magn_state->callbacks);
>  	if (ret < 0) {
>  		dev_err(&pdev->dev, "callback reg failed\n");
> -		goto error_iio_unreg;
> +		goto error_remove_trigger;
> +	}
> +
> +	ret = iio_device_register(indio_dev);
> +	if (ret) {
> +		dev_err(&pdev->dev, "device register failed\n");
> +		goto error_remove_callback;
>  	}
>  
>  	return ret;
>  
> -error_iio_unreg:
> -	iio_device_unregister(indio_dev);
> +error_remove_callback:
> +	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_COMPASS_3D);

[Severity: High]
Can this sequence cause a use-after-free if a callback is currently
executing?

Since sensor_hub_remove_callback() only unlinks the callback without
synchronizing or waiting for currently executing ones to finish, could
magn_3d_proc_event() still be running?

When hid_magn_3d_probe() returns an error, the devres subsystem will
immediately free indio_dev and magn_state. If a concurrent callback was
triggered right before iio_device_register() failed, it would then
access the newly freed memory.

>  error_remove_trigger:
>  	hid_sensor_remove_trigger(indio_dev, &magn_state->magn_flux_attributes);
>  	return ret;
> @@ -545,8 +545,8 @@ static void hid_magn_3d_remove(struct platform_device *pdev)
>  	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
>  	struct magn_3d_state *magn_state = iio_priv(indio_dev);
>  
> -	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_COMPASS_3D);
>  	iio_device_unregister(indio_dev);

[Severity: Critical]
Does reordering iio_device_unregister() before removing the callback
expose a list corruption race?

iio_device_unregister() calls iio_disable_all_buffers(), which modifies
the buffer_list using list_del_init() without lock or RCU protection.

Since the sensor callback is still active, incoming hardware events can
continue to fire. If magn_3d_proc_event() calls 
iio_push_to_buffers_with_timestamp() and iterates over buffer_list
locklessly at the same time list_del_init() is executing, could this
cause the next pointer to loop on itself and result in a hard lockup?

> +	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_COMPASS_3D);

[Severity: High]
This isn't a bug introduced by this patch, but does the lack of
synchronization in sensor_hub_remove_callback() leave a lingering
use-after-free window here?

sensor_hub_remove_callback() removes the callback from the list but
returns without waiting for any currently executing sensor_hub_raw_event()
to finish.

After sensor_hub_remove_callback() completes, hid_magn_3d_remove()
returns and devres will free indio_dev and magn_state. If a callback is
still executing on another CPU, it might access this freed memory.

>  	hid_sensor_remove_trigger(indio_dev, &magn_state->magn_flux_attributes);
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260606-5-june-hid-iio-race-fixes-v1-0-27a848c5758f@gmail.com?part=8

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

* Re: [PATCH 7/9] iio: light: hid-sensor-als: Fix race between callback registration and device exposure
  2026-06-06 11:37 ` [PATCH 7/9] iio: light: hid-sensor-als: " Sanjay Chitroda
@ 2026-06-06 12:11   ` sashiko-bot
  0 siblings, 0 replies; 19+ messages in thread
From: sashiko-bot @ 2026-06-06 12:11 UTC (permalink / raw)
  To: Sanjay Chitroda; +Cc: dmitry.torokhov, linux-input

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

New issues:
- [Critical] Reversing the teardown order in `hid_als_remove()` leaves the data producer active during IIO device unregistration, leading to buffer list corruption and a kernel panic.
- [High] Registering the HID sensor hub callback before `iio_device_register()` introduces a Use-After-Free vulnerability on the probe error path.

Pre-existing issues:
- [High] `sensor_hub_remove_callback()` does not wait for executing callbacks to finish, causing a Use-After-Free when the driver unbinds.
--

commit 7a8f6d5a76d506427e21235e877b3b2cd1616826
Author: Sanjay Chitroda <sanjayembeddedse@gmail.com>

iio: light: hid-sensor-als: Fix race between callback registration and device exposure

This commit modifies the initialization and teardown sequences in the
hid-sensor-als driver. It registers the sensor hub callback before exposing
the IIO device in the probe path, and reverses the order in the remove
path.

> diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
> index d72e260b82668..93d6038486908 100644
> --- a/drivers/iio/light/hid-sensor-als.c
> +++ b/drivers/iio/light/hid-sensor-als.c
> @@ -406,25 +406,25 @@ static int hid_als_probe(struct platform_device *pdev)
>  		return ret;
>  	}
>  
> -	ret = iio_device_register(indio_dev);
> -	if (ret) {
> -		dev_err(&pdev->dev, "device register failed\n");
> -		goto error_remove_trigger;
> -	}
> -
>  	als_state->callbacks.send_event = als_proc_event;
>  	als_state->callbacks.capture_sample = als_capture_sample;
>  	als_state->callbacks.pdev = pdev;
>  	ret = sensor_hub_register_callback(hsdev, hsdev->usage, &als_state->callbacks);
>  	if (ret < 0) {
>  		dev_err(&pdev->dev, "callback reg failed\n");
> -		goto error_iio_unreg;
> +		goto error_remove_trigger;
> +	}
> +
> +	ret = iio_device_register(indio_dev);
> +	if (ret) {
> +		dev_err(&pdev->dev, "device register failed\n");
> +		goto error_remove_callback;

[Severity: High]
Does registering the HID sensor hub callback before iio_device_register()
introduce a use-after-free vulnerability on the probe error path?

If iio_device_register() fails, the error path calls
sensor_hub_remove_callback() and the probe function returns, triggering
devres to free the allocated indio_dev and als_state memory.

However, sensor_hub_remove_callback() only unlinks the callback from the
list; it does not synchronize or wait for concurrently executing events.
If an event arrived from the hardware between registration and failure,
als_capture_sample() could be executing on another CPU.

That function will continue to run and write to the devres-managed memory
after it has been freed:

drivers/iio/light/hid-sensor-als.c:als_capture_sample() {
    ...
	struct iio_dev *indio_dev = platform_get_drvdata(priv);
	struct als_state *als_state = iio_priv(indio_dev);

	switch (usage_id) {
	case HID_USAGE_SENSOR_LIGHT_ILLUM:
		als_state->scan.illum[CHANNEL_SCAN_INDEX_ILLUM] = sample_data;
    ...
}

>  	}
>  
>  	return ret;
>  
> -error_iio_unreg:
> -	iio_device_unregister(indio_dev);
> +error_remove_callback:
> +	sensor_hub_remove_callback(hsdev, hsdev->usage);
>  error_remove_trigger:
>  	hid_sensor_remove_trigger(indio_dev, &als_state->common_attributes);
>  	return ret;
> @@ -437,8 +437,8 @@ static void hid_als_remove(struct platform_device *pdev)
>  	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
>  	struct als_state *als_state = iio_priv(indio_dev);
>  
> -	sensor_hub_remove_callback(hsdev, hsdev->usage);
>  	iio_device_unregister(indio_dev);
> +	sensor_hub_remove_callback(hsdev, hsdev->usage);

[Severity: Critical]
Does reversing the teardown order here leave the data producer active
during IIO device unregistration?

iio_device_unregister() cleans up buffers by calling
iio_disable_all_buffers(), which unlinks buffers from
indio_dev->buffer_list using list_del_init():

drivers/iio/industrialio-buffer.c:iio_buffer_deactivate() {
    ...
	list_del_init(&buffer->buffer_list);
    ...
}

Because the HID event callback remains registered and active, incoming
sensor events can concurrently trigger iio_push_to_buffers_with_ts(). This
function locklessly iterates over buffer_list:

drivers/iio/industrialio-buffer.c:iio_push_to_buffers() {
    ...
	list_for_each_entry(buf, &iio_dev_opaque->buffer_list, buffer_list) {
		ret = iio_push_to_buffer(buf, data);
    ...
}

Concurrently traversing a linked list while it is being actively dismantled
via list_del_init() without synchronization causes the reader to follow
self-referential pointers, which can result in an infinite loop, soft
lockup, or kernel panic.

[Severity: High]
This is a pre-existing issue, but does sensor_hub_remove_callback() wait
for executing callbacks to finish?

When the driver is removed, it removes the callback using
sensor_hub_remove_callback(). This function removes the callback from the
list under dyn_callback_lock but fails to synchronize with or wait for
currently running callbacks:

drivers/hid/hid-sensor-hub.c:sensor_hub_remove_callback() {
    ...
	list_for_each_entry(callback, &pdata->dyn_callback_list, list)
		if (callback->usage_id == usage_id &&
						callback->hsdev == hsdev) {
			list_del(&callback->list);
			kfree(callback);
			break;
		}
	spin_unlock_irqrestore(&pdata->dyn_callback_lock, flags);
    ...
}

If an event is already in-flight, als_capture_sample() can continue
executing after hid_als_remove() completes and devres frees the indio_dev.
The concurrent execution will then dereference the freed als_state
structure, causing a use-after-free.

>  	hid_sensor_remove_trigger(indio_dev, &als_state->common_attributes);
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260606-5-june-hid-iio-race-fixes-v1-0-27a848c5758f@gmail.com?part=7

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

* Re: [PATCH 1/9] iio: orientation: hid-sensor-rotation: Fix race between callback registration and device exposure
  2026-06-06 11:37 ` [PATCH 1/9] iio: orientation: hid-sensor-rotation: Fix race " Sanjay Chitroda
@ 2026-06-06 12:11   ` sashiko-bot
  0 siblings, 0 replies; 19+ messages in thread
From: sashiko-bot @ 2026-06-06 12:11 UTC (permalink / raw)
  To: Sanjay Chitroda; +Cc: linux-input, dmitry.torokhov

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:

New issues:
- [High] Newly introduced Use-After-Free in the probe error path caused by registering the callback before IIO device registration.
- [High] Newly introduced data race leading to list corruption in the remove path by unregistering the IIO device while the sensor hub callback is still active.

Pre-existing issues:
- [High] Pre-existing Use-After-Free due to a lack of synchronization in sensor hub callback removal.
- [High] Pre-existing Out-of-Bounds Read in dev_rot_capture_sample when reading malicious HID reports.
--

commit 53e3688342562957aa2297744b7cc0b03bf921af
Author: Sanjay Chitroda <sanjayembeddedse@gmail.com>
Subject: iio: orientation: hid-sensor-rotation: Fix race between callback registration and device exposure

The driver registers the IIO device before completing sensor hub callback
registration and unregisters callbacks while the IIO device is still exposed
during teardown. This creates race windows in both probe and remove paths.
This patch attempts to fix this by correct ordering of callback registration.

Fixes: fc18dddc0625 ("iio: hid-sensors: Added device rotation support")

> diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c
> index 4a11e45550991..fd9beb93cefb1 100644
> --- a/drivers/iio/orientation/hid-sensor-rotation.c
> +++ b/drivers/iio/orientation/hid-sensor-rotation.c
> @@ -332,12 +332,6 @@ static int hid_dev_rot_probe(struct platform_device *pdev)
>  		return ret;
>  	}
>  
> -	ret = iio_device_register(indio_dev);
> -	if (ret) {
> -		dev_err(&pdev->dev, "device register failed\n");
> -		goto error_remove_trigger;
> -	}
> -
>  	rot_state->callbacks.send_event = dev_rot_proc_event;
>  	rot_state->callbacks.capture_sample = dev_rot_capture_sample;

[Severity: High]
This is a pre-existing issue, but can dev_rot_capture_sample() read
out-of-bounds when handling malicious HID reports?

If raw_len does not correspond to an array of four 16-bit integers, the
function unconditionally copies 16 bytes:

drivers/iio/orientation/hid-sensor-rotation.c:dev_rot_capture_sample() {
    ...
    } else {
        memcpy(&rot_state->scan.sampled_vals, raw_data,
               sizeof(rot_state->scan.sampled_vals));
    }
    ...
}

If a malicious USB device provides a report descriptor with a field size
smaller than 16 bytes, will this memcpy() read out-of-bounds without verifying
that raw_len is at least 16?

>  	rot_state->callbacks.pdev = pdev;
> @@ -345,13 +339,19 @@ static int hid_dev_rot_probe(struct platform_device *pdev)
>  					&rot_state->callbacks);
>  	if (ret) {
>  		dev_err(&pdev->dev, "callback reg failed\n");
> -		goto error_iio_unreg;
> +		goto error_remove_trigger;
> +	}
> +
> +	ret = iio_device_register(indio_dev);
> +	if (ret) {
> +		dev_err(&pdev->dev, "device register failed\n");
> +		goto error_remove_callback;
>  	}

[Severity: High]
Is there a use-after-free introduced in this new error path?

By registering the callback before the IIO device, if iio_device_register()
fails, the error path removes the callback and returns, triggering devres
cleanup.

Because sensor_hub_remove_callback() lacks execution synchronization, an event
dispatched immediately after callback registration can run concurrently. When
hid_dev_rot_probe() returns, the rot_state memory is freed while the event
handler is still executing.

[ ... ]

> @@ -364,8 +364,8 @@ static void hid_dev_rot_remove(struct platform_device *pdev)
>  	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
>  	struct dev_rot_state *rot_state = iio_priv(indio_dev);

[Severity: High]
This isn't a bug introduced by this patch, but does hid_dev_rot_remove()
complete teardown without synchronization, allowing devres to free memory
while callbacks are still executing?

When sensor_hub_remove_callback() removes the callback entry from the list:

drivers/hid/hid-sensor-hub.c:sensor_hub_remove_callback() {
    ...
    list_del(&callback->list);
    kfree(callback);
    ...
}

It does not wait for any currently executing callback, such as
dev_rot_proc_event(), to finish. When hid_dev_rot_remove() returns, devres
automatically frees indio_dev and rot_state.

If dev_rot_proc_event() is running concurrently on another CPU:

drivers/iio/orientation/hid-sensor-rotation.c:dev_rot_proc_event() {
    ...
    struct iio_dev *indio_dev = platform_get_drvdata(priv);
    struct dev_rot_state *rot_state = iio_priv(indio_dev);
    ...
}

Could it dereference the freed indio_dev pointer?

>  
> -	sensor_hub_remove_callback(hsdev, hsdev->usage);
>  	iio_device_unregister(indio_dev);
> +	sensor_hub_remove_callback(hsdev, hsdev->usage);

[Severity: High]
Will moving sensor_hub_remove_callback() after iio_device_unregister()
dismantle the buffer list concurrently with active events?

Leaving the callback active during teardown means an incoming sensor event can
trigger dev_rot_proc_event(), which calls iio_push_to_buffers() while
iio_device_unregister() is disabling buffers.

If iio_push_to_buffers() locklessly iterates over the buffer list:

drivers/iio/industrialio-buffer.c:iio_push_to_buffers() {
    ...
    list_for_each_entry(buf, &iio_dev_opaque->buffer_list, buffer_list) {
    ...
}

And iio_device_unregister() concurrently uses list_del_init() to remove
buffers from the list, might this cause list corruption?

>  	hid_sensor_remove_trigger(indio_dev, &rot_state->common_attributes);
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260606-5-june-hid-iio-race-fixes-v1-0-27a848c5758f@gmail.com?part=1

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

* Re: [PATCH 6/9] iio: light: hid-sensor-prox: Fix race between callback registration and device exposure
  2026-06-06 11:37 ` [PATCH 6/9] iio: light: hid-sensor-prox: Fix race between callback registration and device exposure Sanjay Chitroda
@ 2026-06-06 12:13   ` sashiko-bot
  0 siblings, 0 replies; 19+ messages in thread
From: sashiko-bot @ 2026-06-06 12:13 UTC (permalink / raw)
  To: Sanjay Chitroda; +Cc: dmitry.torokhov, linux-input

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

New issues:
- [Critical] Reordering `iio_device_unregister()` before `sensor_hub_remove_callback()` introduces a critical data race that can lead to an infinite loop, list corruption, or Use-After-Free during device teardown.

Pre-existing issues:
- [High] Lack of synchronization in `sensor_hub_remove_callback()` fails to flush in-flight events, causing a Use-After-Free of devres-managed memory during probe failure.
- [High] Incorrect parsing of little-endian HID report data using host-endian pointer casts.
--

commit 60bbe69d1f4ccbb5130ebd8324841d9eca79e70a
Author: Sanjay Chitroda <sanjayembeddedse@gmail.com>

iio: light: hid-sensor-prox: Fix race between callback registration and device exposure

The driver registers the IIO device before completing sensor hub
callback registration and unregisters callbacks while the IIO device
is still exposed during teardown.

This creates race windows in both probe and remove paths, which can
lead to NULL pointer dereferences or use-after-free.

Fix this by correct ordering of callback registration and
IIO device registration in probe and remove paths.

> diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c
> index edc9274a2c076..3df7f28d3b445 100644
> --- a/drivers/iio/light/hid-sensor-prox.c
> +++ b/drivers/iio/light/hid-sensor-prox.c

[ ... ]

> @@ -325,13 +319,19 @@ static int hid_prox_probe(struct platform_device *pdev)
>  					   &prox_state->callbacks);
>  	if (ret < 0) {
>  		dev_err(&pdev->dev, "callback reg failed\n");
> -		goto error_iio_unreg;
> +		goto error_remove_trigger;
> +	}
> +
> +	ret = iio_device_register(indio_dev);
> +	if (ret) {
> +		dev_err(&pdev->dev, "device register failed\n");
> +		goto error_remove_callback;
>  	}

[Severity: High]
This is a pre-existing issue, but this patch newly exposes it in the probe
error path by moving callback registration before iio_device_register().

When hid_prox_probe() fails here and completes, devres automatically frees the
indio_dev and prox_state structures.

sensor_hub_remove_callback() acquires pdata->dyn_callback_lock to remove the
callback from the list, but it does not wait for currently executing callbacks
in sensor_hub_raw_event() (which run under pdata->lock) to complete.

Could a still-executing event handler on another CPU dereference the freed
memory, leading to a Use-After-Free?

>  
>  	return ret;
>  
> -error_iio_unreg:
> -	iio_device_unregister(indio_dev);
> +error_remove_callback:
> +	sensor_hub_remove_callback(hsdev, hsdev->usage);
>  error_remove_trigger:

[ ... ]

> @@ -344,8 +344,8 @@ static void hid_prox_remove(struct platform_device *pdev)
>  	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
>  	struct prox_state *prox_state = iio_priv(indio_dev);
>  
> -	sensor_hub_remove_callback(hsdev, hsdev->usage);
>  	iio_device_unregister(indio_dev);
> +	sensor_hub_remove_callback(hsdev, hsdev->usage);

[Severity: Critical]
Does reordering the teardown sequence so that sensor_hub_remove_callback()
runs after iio_device_unregister() leave the sensor hub callback fully
active while the IIO device is being dismantled?

iio_device_unregister() calls iio_disable_all_buffers(), which iterates over
the buffer_list using list_del_init() and frees internal state. Concurrently,
incoming hardware events trigger prox_proc_event(). While
iio_disable_all_buffers() eventually decrements data_ready to 0,
prox_proc_event() checks data_ready without any locking.

If prox_proc_event() observes data_ready > 0 and calls iio_push_to_buffers()
concurrently with buffer teardown, will it perform a lockless list traversal
over the actively modifying buffer_list?

drivers/iio/industrialio-buffer.c:iio_push_to_buffers() {
	...
	list_for_each_entry(buf, &iio_dev_opaque->buffer_list, buffer_list) {
	...
}

Could this concurrent modification cause the iterator's next pointer to become
self-referential, resulting in an infinite loop, or access freed memory
causing a Use-After-Free?

>  	hid_sensor_remove_trigger(indio_dev, &prox_state->common_attributes);
>  }

[Severity: High]
This isn't a bug introduced by this patch, but looking at how raw data
is handled in prox_capture_sample() from drivers/iio/light/hid-sensor-prox.c:

	switch (raw_len) {
	case 1:
		prox_state->human_presence[chan] = *(u8 *)raw_data * multiplier;
		return 0;
	case 2:
		prox_state->human_presence[chan] = *(u16 *)raw_data * multiplier;
		return 0;
	case 4:
		prox_state->human_presence[chan] = *(u32 *)raw_data * multiplier;
		return 0;
	}

The raw data received from the HID sensor hub is in little-endian format as
per the HID specification.

When raw_data is directly cast to u16 * or u32 * and dereferenced on a Big
Endian architecture, will this host-endian read result in incorrectly swapped
bytes, producing corrupted sensor readings?

Furthermore, since raw_data points directly into the unaligned HID report byte
array, can this cast trigger an unaligned memory access exception (kernel oops)
on strict architectures? Should this use get_unaligned_le16() or
get_unaligned_le32() instead to correctly parse the little-endian data stream?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260606-5-june-hid-iio-race-fixes-v1-0-27a848c5758f@gmail.com?part=6

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

* Re: [PATCH 9/9] iio: accel: hid-sensor-accel-3d: Fix race between callback registration and device exposure
  2026-06-06 11:37 ` [PATCH 9/9] iio: accel: hid-sensor-accel-3d: " Sanjay Chitroda
@ 2026-06-06 12:13   ` sashiko-bot
  0 siblings, 0 replies; 19+ messages in thread
From: sashiko-bot @ 2026-06-06 12:13 UTC (permalink / raw)
  To: Sanjay Chitroda; +Cc: dmitry.torokhov, linux-input

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

New issues:
- [High] The patch introduces a Use-After-Free / NULL Pointer Dereference in the `probe` error path by registering the sensor hub callback before IIO device registration.

Pre-existing issues:
- [High] Reordering IIO device unregistration before callback removal exacerbates a Use-After-Free vulnerability during driver teardown.
- [High] Reordering IIO device unregistration before callback removal widens a severe data race leading to linked list corruption.
--

commit 538b7bb72b2f4da6c8de1d51d2852e714b2a2bcc
Author: Sanjay Chitroda <sanjayembeddedse@gmail.com>

iio: accel: hid-sensor-accel-3d: Fix race between callback registration and device exposure

The driver registers the IIO device before completing sensor hub
callback registration and unregisters callbacks while the IIO device
is still exposed during teardown.

> diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
> index 2bf05ab5235ef..c000e001c0015 100644
> --- a/drivers/iio/accel/hid-sensor-accel-3d.c
> +++ b/drivers/iio/accel/hid-sensor-accel-3d.c
[ ... ]
> @@ -399,13 +393,19 @@ static int hid_accel_3d_probe(struct platform_device *pdev)
>  					&accel_state->callbacks);
>  	if (ret < 0) {
>  		dev_err(&pdev->dev, "callback reg failed\n");
> -		goto error_iio_unreg;
> +		goto error_remove_trigger;
> +	}
> +
> +	ret = iio_device_register(indio_dev);
> +	if (ret) {
> +		dev_err(&pdev->dev, "device register failed\n");
> +		goto error_remove_callback;

[Severity: High]
Does this new error path expose asynchronous event handlers to a
use-after-free or NULL pointer dereference?

When sensor_hub_register_callback() succeeds, it allows the hardware to
immediately dispatch events to accel_3d_proc_event(). If iio_device_register()
then fails, the code jumps to error_remove_callback.

While sensor_hub_remove_callback() removes the callback from the list, it
does not appear to synchronize with or wait for concurrently running handlers.
When probe() returns, devres frees the indio_dev structure and the driver
core clears drvdata.

Any concurrently executing accel_3d_proc_event() might then fetch the cleared
drvdata (causing a NULL pointer dereference) or access the freed indio_dev
(causing a use-after-free).

>  	}
>  
>  	return ret;
>  
> -error_iio_unreg:
> -	iio_device_unregister(indio_dev);
> +error_remove_callback:
> +	sensor_hub_remove_callback(hsdev, hsdev->usage);
>  error_remove_trigger:
>  	hid_sensor_remove_trigger(indio_dev, &accel_state->common_attributes);
>  	return ret;
> @@ -418,8 +418,8 @@ static void hid_accel_3d_remove(struct platform_device *pdev)
>  	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
>  	struct accel_3d_state *accel_state = iio_priv(indio_dev);
>  
> -	sensor_hub_remove_callback(hsdev, hsdev->usage);
>  	iio_device_unregister(indio_dev);

[Severity: High]
This is a pre-existing issue, but does moving iio_device_unregister() before
sensor_hub_remove_callback() widen a data race leading to linked list
corruption?

By calling iio_device_unregister() first, the sensor callback remains fully
active and eligible to receive new events during IIO teardown.

Hardware events trigger accel_3d_proc_event(), which calls
iio_push_to_buffers(). This traverses the buffer_list without holding locks
using list_for_each_entry(). Concurrently, iio_device_unregister() calls
iio_disable_all_buffers(), which modifies the same buffer_list.

Can this concurrent list modification corrupt the traversal pointer,
potentially causing an infinite loop or a panic?

> +	sensor_hub_remove_callback(hsdev, hsdev->usage);

[Severity: High]
This is a pre-existing issue, but does this reordering exacerbate a
use-after-free vulnerability during driver teardown?

sensor_hub_remove_callback() unlinks the callback from the internal list
without synchronizing with currently executing event handlers. When the
remove function returns, devres will immediately free indio_dev.

Previously, the slow iio_device_unregister() call was executed after callback
removal, providing an implicit grace period for in-flight events to finish.
By moving it before callback removal, this delay is eliminated, which might
cause any concurrent event handler to dereference the freed indio_dev
structure more reliably.

>  	hid_sensor_remove_trigger(indio_dev, &accel_state->common_attributes);
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260606-5-june-hid-iio-race-fixes-v1-0-27a848c5758f@gmail.com?part=9

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

* Re: [PATCH 3/9] iio: gyro: hid-sensor-gyro-3d: Fix race between callback registration and device exposure
  2026-06-06 11:37 ` [PATCH 3/9] iio: gyro: hid-sensor-gyro-3d: " Sanjay Chitroda
@ 2026-06-06 12:13   ` sashiko-bot
  0 siblings, 0 replies; 19+ messages in thread
From: sashiko-bot @ 2026-06-06 12:13 UTC (permalink / raw)
  To: Sanjay Chitroda; +Cc: dmitry.torokhov, linux-input

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Lack of synchronization in sensor_hub_remove_callback() leads to Use-After-Free (UAF) of function pointers and device state.
--

commit aa52ffd9a4b9c66e6a2d69f6946e1ab533f472af
Author: Sanjay Chitroda <sanjayembeddedse@gmail.com>

iio: gyro: hid-sensor-gyro-3d: Fix race between callback registration and device exposure

This commit reorders callback registration and IIO device registration
in the probe and remove paths to prevent race conditions during
initialization and teardown.

> diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
> --- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
> +++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
[ ... ]
> @@ -337,13 +331,19 @@ static int hid_gyro_3d_probe(struct platform_device *pdev)
>  					&gyro_state->callbacks);
>  	if (ret < 0) {
>  		dev_err(&pdev->dev, "callback reg failed\n");
> -		goto error_iio_unreg;
> +		goto error_remove_trigger;
> +	}
> +
> +	ret = iio_device_register(indio_dev);
> +	if (ret) {
> +		dev_err(&pdev->dev, "device register failed\n");
> +		goto error_remove_callback;
>  	}
>  
>  	return ret;
>  
> -error_iio_unreg:
> -	iio_device_unregister(indio_dev);
> +error_remove_callback:
> +	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_GYRO_3D);

[Severity: High]
Does this new error path introduce a use-after-free window if an event
arrives concurrently?

Looking at sensor_hub_remove_callback(), it removes the callback from the
active list but does not appear to synchronize with or wait for concurrently
executing event handlers.

If iio_device_register() fails, probe() calls sensor_hub_remove_callback()
and returns immediately. The devres subsystem will then free the indio_dev
and gyro_state memory.

Could this sequence occur:

CPU1
hid_gyro_3d_probe()
    error_remove_callback:
    sensor_hub_remove_callback()
    return ret;

CPU2 sees this in sensor_hub_raw_event():
    if (callback->capture_sample) {
        callback->capture_sample(...);

Since callback points to the devm-allocated gyro_state->callbacks, would
this lead to dereferencing freed function pointers and state data?

>  error_remove_trigger:
>  	hid_sensor_remove_trigger(indio_dev, &gyro_state->common_attributes);
>  	return ret;
[ ... ]
> @@ -356,8 +356,8 @@ static void hid_gyro_3d_remove(struct platform_device *pdev)
>  	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
>  	struct gyro_3d_state *gyro_state = iio_priv(indio_dev);
>  
> -	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_GYRO_3D);
>  	iio_device_unregister(indio_dev);
> +	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_GYRO_3D);

[Severity: High]
Does this teardown sequence suffer from the same lack of synchronization?

If sensor_hub_remove_callback() does not wait for ongoing events to complete,
could a concurrent sensor_hub_raw_event() still be executing and access
gyro_state->callbacks after hid_gyro_3d_remove() finishes and devres cleans
up the memory?

>  	hid_sensor_remove_trigger(indio_dev, &gyro_state->common_attributes);
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260606-5-june-hid-iio-race-fixes-v1-0-27a848c5758f@gmail.com?part=3

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

end of thread, other threads:[~2026-06-06 12:13 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-06 11:37 [PATCH 0/9] HID: iio: Fix race condition between callback registration and device exposure Sanjay Chitroda
2026-06-06 11:37 ` [PATCH 1/9] iio: orientation: hid-sensor-rotation: Fix race " Sanjay Chitroda
2026-06-06 12:11   ` sashiko-bot
2026-06-06 11:37 ` [PATCH 2/9] iio: orientation: hid-sensor-incl-3d: " Sanjay Chitroda
2026-06-06 12:10   ` sashiko-bot
2026-06-06 11:37 ` [PATCH 3/9] iio: gyro: hid-sensor-gyro-3d: " Sanjay Chitroda
2026-06-06 12:13   ` sashiko-bot
2026-06-06 11:37 ` [PATCH 4/9] iio: pressure: hid-sensor-press: " Sanjay Chitroda
2026-06-06 11:50   ` sashiko-bot
2026-06-06 11:37 ` [PATCH 5/9] iio: temperature: hid-sensor-temperature: switch to non-devm iio_device_register() Sanjay Chitroda
2026-06-06 12:09   ` sashiko-bot
2026-06-06 11:37 ` [PATCH 6/9] iio: light: hid-sensor-prox: Fix race between callback registration and device exposure Sanjay Chitroda
2026-06-06 12:13   ` sashiko-bot
2026-06-06 11:37 ` [PATCH 7/9] iio: light: hid-sensor-als: " Sanjay Chitroda
2026-06-06 12:11   ` sashiko-bot
2026-06-06 11:37 ` [PATCH 8/9] iio: magnetometer: hid-sensor-magn-3d: " Sanjay Chitroda
2026-06-06 12:10   ` sashiko-bot
2026-06-06 11:37 ` [PATCH 9/9] iio: accel: hid-sensor-accel-3d: " Sanjay Chitroda
2026-06-06 12:13   ` sashiko-bot

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