Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Bluetooth: hci_qca: Fix the teardown problem for real

While discussing solutions for the teardown problem which results from
circular dependencies between timers and workqueues, where timers schedule
work from their timer callback and workqueues arm the timers from work
items, it was discovered that the recent fix to the QCA code is incorrect.

That commit fixes the obvious problem of using del_timer() instead of
del_timer_sync() and reorders the teardown calls to

destroy_workqueue(wq);
del_timer_sync(t);

This makes it less likely to explode, but it's still broken:

destroy_workqueue(wq);
/* After this point @wq cannot be touched anymore */

---> timer expires
queue_work(wq) <---- Results in a NULL pointer dereference
deep in the work queue core code.
del_timer_sync(t);

Use the new timer_shutdown_sync() function to ensure that the timers are
disarmed, no timer callbacks are running and the timers cannot be armed
again. This restores the original teardown sequence:

timer_shutdown_sync(t);
destroy_workqueue(wq);

which is now correct because the timer core silently ignores potential
rearming attempts which can happen when destroy_workqueue() drains pending
work before mopping up the workqueue.

Fixes: 72ef98445aca ("Bluetooth: hci_qca: Use del_timer_sync() before freeing")
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Guenter Roeck <linux@roeck-us.net>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Reviewed-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Acked-by: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Link: https://lore.kernel.org/all/87iljhsftt.ffs@tglx
Link: https://lore.kernel.org/r/20221123201625.435907114@linutronix.de

+8 -2
+8 -2
drivers/bluetooth/hci_qca.c
··· 696 696 skb_queue_purge(&qca->tx_wait_q); 697 697 skb_queue_purge(&qca->txq); 698 698 skb_queue_purge(&qca->rx_memdump_q); 699 + /* 700 + * Shut the timers down so they can't be rearmed when 701 + * destroy_workqueue() drains pending work which in turn might try 702 + * to arm a timer. After shutdown rearm attempts are silently 703 + * ignored by the timer core code. 704 + */ 705 + timer_shutdown_sync(&qca->tx_idle_timer); 706 + timer_shutdown_sync(&qca->wake_retrans_timer); 699 707 destroy_workqueue(qca->workqueue); 700 - del_timer_sync(&qca->tx_idle_timer); 701 - del_timer_sync(&qca->wake_retrans_timer); 702 708 qca->hu = NULL; 703 709 704 710 kfree_skb(qca->rx_skb);