[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