[PATCH RFC] usb: atm: cxacru: fix use-after-free in cxacru_poll_status()
"syzbot" <[email protected]> Sun, 2 Aug 2026 20:29:40 +0000 (UTC)
| Newsgroups | dev.linux.lists.syzbot |
|---|---|
| Message-ID | <[email protected]> |
A KASAN use-after-free was detected in __mutex_lock_common triggered by the
cxacru_poll_status work item attempting to lock
instance->poll_state_serialize after the instance (struct cxacru_data) has
been freed by cxacru_unbind.
The root cause is a race condition in cxacru_unbind where it conditionally
skips canceling the delayed work instance->poll_work if
instance->poll_state == CXPOLL_STOPPED. However, the state CXPOLL_STOPPED
only means that the work should not reschedule itself; it does not mean
that the work is not currently executing.
If the work is executing while cxacru_unbind skips the cancellation and
frees the instance memory, the work item will eventually attempt to access
the freed memory, leading to the use-after-free.
To fix this, remove the is_polling variable and the conditional check in
cxacru_unbind. The driver now unconditionally calls
cancel_delayed_work_sync(&instance->poll_work). This safely guarantees that
the work item has completely finished executing before the instance memory
is freed.
Additionally, update cxacru_poll_status to check if instance->poll_state ==
CXPOLL_SHUTDOWN before deciding to reschedule itself. This ensures that if
the work item is currently executing while cxacru_unbind sets the state to
CXPOLL_SHUTDOWN, it will cleanly exit and not attempt to reschedule itself.
BUG: KASAN: slab-use-after-free in __mutex_lock_common
kernel/locking/mutex.c:625 [inline]
BUG: KASAN: slab-use-after-free in __mutex_lock+0x154/0x1550
kernel/locking/mutex.c:821
Read of size 8 at addr ffff8881fbf3e218 by task kworker/1:1/32
Workqueue: events cxacru_poll_status
Call Trace:
<TASK>
dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
print_address_description+0x55/0x1e0 mm/kasan/report.c:378
print_report+0x58/0x70 mm/kasan/report.c:482
kasan_report+0x117/0x150 mm/kasan/report.c:595
__mutex_lock_common kernel/locking/mutex.c:625 [inline]
__mutex_lock+0x154/0x1550 kernel/locking/mutex.c:821
cxacru_poll_status+0x73a/0x1110 drivers/usb/atm/cxacru.c:920
process_one_work kernel/workqueue.c:3322 [inline]
process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3405
worker_thread+0xa47/0xfb0 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>
Freed by task 5720:
kasan_save_stack mm/kasan/common.c:57 [inline]
kasan_save_track+0x3e/0x80 mm/kasan/common.c:78
kasan_save_free_info+0x40/0x50 mm/kasan/generic.c:584
poison_slab_object mm/kasan/common.c:253 [inline]
__kasan_slab_free+0x5c/0x80 mm/kasan/common.c:285
kasan_slab_free include/linux/kasan.h:235 [inline]
slab_free_hook mm/slub.c:2677 [inline]
slab_free mm/slub.c:6377 [inline]
kfree+0x1c5/0x640 mm/slub.c:6692
cxacru_unbind+0x1c8/0x340 drivers/usb/atm/cxacru.c:1266
usbatm_usb_disconnect+0x42b/0x620 drivers/usb/atm/usbatm.c:1255
usb_unbind_interface+0x295/0x9f0 drivers/usb/core/driver.c:458
device_remove drivers/base/dd.c:618 [inline]
__device_release_driver drivers/base/dd.c:1349 [inline]
device_release_driver_internal+0x4f5/0x880 drivers/base/dd.c:1372
bus_remove_device+0x444/0x560 drivers/base/bus.c:664
device_del+0x524/0x8f0 drivers/base/core.c:3961
usb_disable_device+0x3d4/0x8d0 drivers/usb/core/message.c:1478
usb_disconnect+0x346/0x9a0 drivers/usb/core/hub.c:2345
Fixes: 6a02c996bce2 ("USB: cxacru: ADSL state management")
Assisted-by: Gemini:gemini-3.5-flash Gemini:gemini-3.1-pro-preview syzbot
Reported-by: [email protected]
Closes: https://syzkaller.appspot.com/bug?extid=24eb38c789655fc43663
Link: https://syzkaller.appspot.com/ai_job?id=79150e78-3441-40ad-8389-e897b217e2a0
To: "Chas Williams" <[email protected]>
To: <[email protected]>
To: "Greg Kroah-Hartman" <[email protected]>
To: <[email protected]>
To: <[email protected]>
To: <[email protected]>
To: "Simon Arlott" <[email protected]>
Cc: <[email protected]>
---
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index f1900c567..4a2206d3b 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -923,7 +923,8 @@ static void cxacru_poll_status(struct work_struct *work)
instance->line_status == 0) /* down */
instance->poll_state = CXPOLL_STOPPED;
- if (instance->poll_state == CXPOLL_STOPPED)
+ if (instance->poll_state == CXPOLL_STOPPED ||
+ instance->poll_state == CXPOLL_SHUTDOWN)
keep_polling = 0;
mutex_unlock(&instance->poll_state_serialize);
@@ -1231,7 +1232,6 @@ static void cxacru_unbind(struct usbatm_data *usbatm_instance,
struct usb_interface *intf)
{
struct cxacru_data *instance = usbatm_instance->driver_data;
- int is_polling = 1;
usb_dbg(usbatm_instance, "cxacru_unbind entered\n");
@@ -1243,17 +1243,11 @@ static void cxacru_unbind(struct usbatm_data *usbatm_instance,
mutex_lock(&instance->poll_state_serialize);
BUG_ON(instance->poll_state == CXPOLL_SHUTDOWN);
- /* ensure that status polling continues unless
- * it has already stopped */
- if (instance->poll_state == CXPOLL_STOPPED)
- is_polling = 0;
-
/* stop polling from being stopped or started */
instance->poll_state = CXPOLL_SHUTDOWN;
mutex_unlock(&instance->poll_state_serialize);
- if (is_polling)
- cancel_delayed_work_sync(&instance->poll_work);
+ cancel_delayed_work_sync(&instance->poll_work);
usb_kill_urb(instance->snd_urb);
usb_kill_urb(instance->rcv_urb);
base-commit: f5098b6bae761e346ebcd9da7f95622c04733cff
--
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].