[PATCH] wifi: libertas: check workqueue creation in lbs_add_card()
YuanZhe Liu
25031212351 at stu.xidian.edu.cn
Sat Oct 17 00:03:35 PDT 2026
lbs_add_card() does not check whether create_singlethread_workqueue()
returned a valid workqueue. That helper always creates the workqueue
with WQ_MEM_RECLAIM, so alloc_workqueue() also creates a rescuer kthread
and returns NULL if that kthread cannot be created, for example when the
task which starts the driver is killed while kthread_create() waits for
the new thread:
workqueue: Failed to create a rescuer kthread for wq "lbs_worker": -4
-4 is -EINTR, which is exactly what the killable wait in
kthread_create_on_node() returns when it is interrupted.
The card is published anyway, with priv->work_thread left NULL, and the
removal path destroys the workqueue unconditionally. destroy_workqueue()
dereferences the NULL pointer while unregistering the workqueue from
sysfs, which faults at offset 0xb0, the ->wq_dev member of struct
workqueue_struct:
KASAN: null-ptr-deref in range [0x00000000000000b0-0x00000000000000b7]
RIP: 0010:destroy_workqueue+0x2e/0xc00 kernel/workqueue.c:6147
Call Trace:
lbs_remove_card+0xc9/0x3a0 main.c:919
if_usb_disconnect+0xc1/0x270 if_usb.c:317
Fail the probe instead of publishing a card whose workqueue could not be
created. The other two libertas bus backends already check the result
of their alloc_workqueue() call, and all three callers of lbs_add_card()
already handle an ERR_PTR() return, so no caller needs to change.
Fixes: 2afc0c5d71a3 ("[PATCH] libertas: push WEXT scan requests to a work queue")
Cc: stable at vger.kernel.org
Co-developed-by: Bin Yu <byu at xidian.edu.cn>
Signed-off-by: Bin Yu <byu at xidian.edu.cn>
Co-developed-by: Cheng Wen <wencheng at xidian.edu.cn>
Signed-off-by: Cheng Wen <wencheng at xidian.edu.cn>
Signed-off-by: YuanZhe Liu <25031212351 at stu.xidian.edu.cn>
---
drivers/net/wireless/marvell/libertas/main.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/net/wireless/marvell/libertas/main.c b/drivers/net/wireless/marvell/libertas/main.c
index dd97f1b61f4d..522736ca6cfd 100644
--- a/drivers/net/wireless/marvell/libertas/main.c
+++ b/drivers/net/wireless/marvell/libertas/main.c
@@ -877,6 +877,12 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
}
priv->work_thread = create_singlethread_workqueue("lbs_worker");
+ if (!priv->work_thread) {
+ err = -ENOMEM;
+ lbs_deb_thread("Error creating worker thread.\n");
+ goto err_thread;
+ }
+
INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker);
priv->wol_criteria = EHS_REMOVE_WAKEUP;
@@ -886,6 +892,9 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
return priv;
+ err_thread:
+ kthread_stop(priv->main_thread);
+
err_ndev:
free_netdev(dev);
--
2.34.1
More information about the libertas-dev
mailing list