Re: [PATCH 1/1] Bluetooth: fix race condition in hci_cmd_sync_clear

From: Luiz Augusto von Dentz
Date: Fri Mar 03 2023 - 13:09:55 EST


Hi Min,

On Wed, Mar 1, 2023 at 11:21 PM lm0963 <lm0963hack@xxxxxxxxx> wrote:
>
> There is a potential race condition in hci_cmd_sync_work and
> hci_cmd_sync_clear, and could lead to use-after-free. For instance,
> hci_cmd_sync_work is added to the 'req_workqueue' after cancel_work_sync
> The entry of 'cmd_sync_work_list' may be freed in hci_cmd_sync_clear, and
> causing kernel panic when it is used in hci_cmd_sync_work.
>
> Here's the call trace:
>
> dump_stack_lvl+0x49/0x63
> print_report.cold+0x5e/0x5d3
> ? hci_cmd_sync_work+0x282/0x320
> kasan_report+0xaa/0x120
> ? hci_cmd_sync_work+0x282/0x320
> __asan_report_load8_noabort+0x14/0x20
> hci_cmd_sync_work+0x282/0x320
> process_one_work+0x77b/0x11c0
> ? _raw_spin_lock_irq+0x8e/0xf0
> worker_thread+0x544/0x1180
> ? poll_idle+0x1e0/0x1e0
> kthread+0x285/0x320
> ? process_one_work+0x11c0/0x11c0
> ? kthread_complete_and_exit+0x30/0x30
> ret_from_fork+0x22/0x30
> </TASK>
>
> Allocated by task 266:
> kasan_save_stack+0x26/0x50
> __kasan_kmalloc+0xae/0xe0
> kmem_cache_alloc_trace+0x191/0x350
> hci_cmd_sync_queue+0x97/0x2b0
> hci_update_passive_scan+0x176/0x1d0
> le_conn_complete_evt+0x1b5/0x1a00
> hci_le_conn_complete_evt+0x234/0x340
> hci_le_meta_evt+0x231/0x4e0
> hci_event_packet+0x4c5/0xf00
> hci_rx_work+0x37d/0x880
> process_one_work+0x77b/0x11c0
> worker_thread+0x544/0x1180
> kthread+0x285/0x320
> ret_from_fork+0x22/0x30
>
> Freed by task 269:
> kasan_save_stack+0x26/0x50
> kasan_set_track+0x25/0x40
> kasan_set_free_info+0x24/0x40
> ____kasan_slab_free+0x176/0x1c0
> __kasan_slab_free+0x12/0x20
> slab_free_freelist_hook+0x95/0x1a0
> kfree+0xba/0x2f0
> hci_cmd_sync_clear+0x14c/0x210
> hci_unregister_dev+0xff/0x440
> vhci_release+0x7b/0xf0
> __fput+0x1f3/0x970
> ____fput+0xe/0x20
> task_work_run+0xd4/0x160
> do_exit+0x8b0/0x22a0
> do_group_exit+0xba/0x2a0
> get_signal+0x1e4a/0x25b0
> arch_do_signal_or_restart+0x93/0x1f80
> exit_to_user_mode_prepare+0xf5/0x1a0
> syscall_exit_to_user_mode+0x26/0x50
> ret_from_fork+0x15/0x30
>
> Signed-off-by: Min Li <lm0963hack@xxxxxxxxx>
> ---
> net/bluetooth/hci_sync.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
> index 117eedb6f709..3103daf49d63 100644
> --- a/net/bluetooth/hci_sync.c
> +++ b/net/bluetooth/hci_sync.c
> @@ -643,6 +643,7 @@ void hci_cmd_sync_clear(struct hci_dev *hdev)
> cancel_work_sync(&hdev->cmd_sync_work);
> cancel_work_sync(&hdev->reenable_adv_work);
>
> + mutex_lock(&hdev->cmd_sync_work_lock);
> list_for_each_entry_safe(entry, tmp, &hdev->cmd_sync_work_list, list) {
> if (entry->destroy)
> entry->destroy(hdev, entry->data, -ECANCELED);
> @@ -650,6 +651,7 @@ void hci_cmd_sync_clear(struct hci_dev *hdev)
> list_del(&entry->list);
> kfree(entry);
> }
> + mutex_unlock(&hdev->cmd_sync_work_lock);
> }

The code style of this one seems broken, did you generate it using git
format-patch?

> void __hci_cmd_sync_cancel(struct hci_dev *hdev, int err)
> --
> 2.25.1



--
Luiz Augusto von Dentz