[PATCH 1/4] Input: psmouse - fix use-after-free during protocol disconnect

Dmitry Torokhov <[email protected]>
Newsgroups org.kernel.vger.linux-input
Message-ID <[email protected]>
When a PS/2 mouse is disconnected or unbound, psmouse_disconnect() calls
the protocol disconnect handler (psmouse->disconnect()). During this time,
stray bytes arriving from the physical controller can still be passed to
psmouse_handle_byte(), which will invoke psmouse->protocol_handler().

This creates an asynchronous race condition with vendor disconnect handlers
(such as synaptics_disconnect()), which free vendor-specific private
structures (psmouse->private). If a byte arrives while the structures
are being freed, it leads to a use-after-free or NULL pointer
dereference in the protocol handler.

Fix this by explicitly setting psmouse->protocol_handler to NULL
safely wrapped in scoped_guard(serio_pause_rx, serio) immediately before
calling the vendor disconnect handler. We also add an unlikely check
in psmouse_handle_byte() to safely drop incoming bytes if the protocol
handler is NULL.

Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Dmitry Torokhov <[email protected]>
---
 drivers/input/mouse/psmouse-base.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 6ab5f1d96eae..916a14b9b6a7 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -267,7 +267,13 @@ void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
  */
 static int psmouse_handle_byte(struct psmouse *psmouse)
 {
-	psmouse_ret_t rc = psmouse->protocol_handler(psmouse);
+	psmouse_ret_t rc;
+
+	/* protocol_handler is NULL when device is being disconnected */
+	if (unlikely(!psmouse->protocol_handler))
+		return 0;
+
+	rc = psmouse->protocol_handler(psmouse);
 
 	switch (rc) {
 	case PSMOUSE_BAD_DATA:
@@ -1466,6 +1472,9 @@ static void psmouse_disconnect(struct serio *serio)
 		psmouse_deactivate(parent);
 	}
 
+	scoped_guard(serio_pause_rx, serio)
+		psmouse->protocol_handler = NULL;
+
 	if (psmouse->disconnect)
 		psmouse->disconnect(psmouse);
 
-- 
2.55.0.229.g6434b31f56-goog
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.