Thread (2 messages) flat view 2 messages, 2 authors, 1d ago
WARM1d

[PATCH] Input: synaptics-rmi4 - reject concurrent firmware updates

From: Shuangpeng Bai <hidden>
Date: 2026-08-17 18:22:25
Also in: stable
Subsystem: input (keyboard, mouse, joystick, touchscreen) drivers, the rest · Maintainers: Dmitry Torokhov, Linus Torvalds

The update_fw sysfs store callback can execute concurrently. Each
invocation runs rmi_firmware_update(), which tears down and rebuilds the
RMI function list.

If two writes overlap, both rmi_free_function_list() calls can walk the
same list and select the same rmi_function entry. One invocation can delete
and unregister the entry while the other still uses its iterator's fn
pointer, resulting in use-after-free or list corruption. This was
reproduced as list_del corruption in rmi_free_function_list().

Firmware flashing is an exclusive operation, and running a second update
concurrently has no useful semantics. Add a per-device update_mutex and
try to acquire it immediately before starting the update. Return -EBUSY if
another update is already active, and hold the mutex until the update has
completed so their function-list teardown cannot overlap.

The status attribute does not acquire update_mutex, so update_fw_status can
still be polled while an update is running.

Fixes: 29fd0ec2bdbe ("Input: synaptics-rmi4 - add support for F34 device reflash")
Cc: stable@vger.kernel.org
Signed-off-by: Shuangpeng Bai <redacted>
---
 drivers/input/rmi4/rmi_driver.c | 1 +
 drivers/input/rmi4/rmi_f34.c    | 8 +++++---
 include/linux/rmi.h             | 1 +
 3 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index 5d49a9021c7d..3a5cb17e938f 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -1218,6 +1218,7 @@ static int rmi_driver_probe(struct device *dev)
 
 	mutex_init(&data->irq_mutex);
 	mutex_init(&data->enabled_mutex);
+	mutex_init(&data->update_mutex);
 
 	retval = rmi_probe_interrupts(data);
 	if (retval)
diff --git a/drivers/input/rmi4/rmi_f34.c b/drivers/input/rmi4/rmi_f34.c
index f1947f03b06a..04f12165cab0 100644
--- a/drivers/input/rmi4/rmi_f34.c
+++ b/drivers/input/rmi4/rmi_f34.c
@@ -468,13 +468,15 @@ static ssize_t rmi_driver_update_fw_store(struct device *dev,
 	if (error)
 		return error;
 
+	if (!mutex_trylock(&data->update_mutex))
+		return -EBUSY;
+
 	dev_info(dev, "Flashing %s\n", fw_name);
 
 	error = rmi_firmware_update(data, fw);
-	if (error)
-		return error;
 
-	return count;
+	mutex_unlock(&data->update_mutex);
+	return error ?: count;
 }
 
 static DEVICE_ATTR(update_fw, 0200, NULL, rmi_driver_update_fw_store);
diff --git a/include/linux/rmi.h b/include/linux/rmi.h
index ab7eea01ab42..d56c23240868 100644
--- a/include/linux/rmi.h
+++ b/include/linux/rmi.h
@@ -340,6 +340,7 @@ struct rmi_driver_data {
 
 	struct rmi_function *f01_container;
 	struct rmi_function *f34_container;
+	struct mutex update_mutex;
 	bool bootloader_mode;
 
 	int num_of_irq_regs;
-- 
2.43.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help