[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].