[PATCH RFC v2] Input: serio, gameport - clean up properly if device_add() fails

"syzbot" <[email protected]>
Newsgroups dev.linux.lists.syzbot
Message-ID <[email protected]>
A general protection fault can occur in __device_attach() when device_add()
fails during port registration.

If device_add() fails (e.g. due to memory allocation failure), dev->p is
freed and set to NULL. However, events queued during device registration
may remain on the workqueue. When the workqueue processes these stale
events, it attempts to attach a driver, leading to a NULL pointer
dereference when accessing dev->p in __device_attach().

Oops: general protection fault, probably for non-canonical address
0xdffffc0000000021: 0000 [#1] SMP KASAN NOPTI
KASAN: null-ptr-deref in range [0x0000000000000108-0x000000000000010f]
CPU: 0 UID: 0 PID: 987 Comm: kworker/0:2 Not tainted PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS
1.16.3-debian-1.16.3-2 04/01/2014
Workqueue: events_long serio_handle_event
RIP: 0010:__device_attach+0xb3/0x450 drivers/base/dd.c:1074
Call Trace:
 <TASK>
 serio_find_driver drivers/input/serio/serio.c:112 [inline]
 serio_handle_event+0x581/0x860 drivers/input/serio/serio.c:206
 process_one_work kernel/workqueue.c:3322 [inline]
 process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3405
 worker_thread+0x92d/0xe10 kernel/workqueue.c:3486
 kthread+0x388/0x470 kernel/kthread.c:436
 ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
 </TASK>

Fix this by properly cleaning up port state, unlinking parent references,
and removing pending events when device_add() fails in serio_add_port() and
gameport_add_port().

Fixes: ddf1ffbd40c9 ("Input: serio - let device core tell us if device was registered")
Assisted-by: Gemini:gemini-3.6-flash Gemini:gemini-3.1-pro-preview syzbot
Reported-by: [email protected]
Closes: https://syzkaller.appspot.com/bug?extid=de42beb9ccc760a210ab
Link: https://syzkaller.appspot.com/ai_job?id=abe77c96-ec34-4c72-9a4e-12da9bb8ce68
To: "Dmitry Torokhov" <[email protected]>
To: <[email protected]>
Cc: "Kees Cook" <[email protected]>
Cc: <[email protected]>

---
v2:
- Remove pending events and clean up port structures directly when device_add() fails in serio_add_port(), rather than checking device_is_registered() in serio_find_driver().
- Extend device_add() error handling and pending event cleanup to gameport_add_port().

v1:
https://lore.kernel.org/all/[email protected]/T/
---
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index 9707b155b..7c90bbd74 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -598,10 +598,17 @@ static void gameport_add_port(struct gameport *gameport)
 			gameport->name, gameport->phys, gameport->speed);
 
 	error = device_add(&gameport->dev);
-	if (error)
+	if (error) {
 		dev_err(&gameport->dev,
 			"device_add() failed for %s (%s), error: %d\n",
 			gameport->phys, gameport->name, error);
+		if (gameport->parent) {
+			gameport->parent->child = NULL;
+			gameport->parent = NULL;
+		}
+		list_del_init(&gameport->node);
+		gameport_remove_pending_events(gameport);
+	}
 }
 
 /*
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 54dd26249..1ce427069 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -510,10 +510,20 @@ static void serio_add_port(struct serio *serio)
 		serio->start(serio);
 
 	error = device_add(&serio->dev);
-	if (error)
+	if (error) {
 		dev_err(&serio->dev,
 			"device_add() failed for %s (%s), error: %d\n",
 			serio->phys, serio->name, error);
+		if (serio->stop)
+			serio->stop(serio);
+		if (parent) {
+			guard(serio_pause_rx)(parent);
+			list_del_init(&serio->child_node);
+			serio->parent = NULL;
+		}
+		list_del_init(&serio->node);
+		serio_remove_pending_events(serio);
+	}
 }
 
 /*


base-commit: db2ddb87143519e20a95aa36c60b36107b736a58
-- 
This is an AI-generated patch subject to moderation.
Reply with '#syz upstream' to Sign-off the patch as a human author
and send it to the upstream kernel mailing lists.
Reply with '#syz reject' to reject it ('#syz unreject' to undo).

See https://goo.gle/syzbot-ai-patches for information about AI-generated patches.
You can comment on the patch as usual, syzbot will try to address
the comments and send a new version of the patch if necessary.
syzbot engineers can be reached at [email protected].
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.