[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