[lvc-project] [PATCH] Bluetooth: fix use-after-free in device_for_each_child()
Luiz Augusto von Dentz
luiz.dentz at gmail.com
Wed Oct 30 17:59:42 MSK 2024
Hi Dmitry,
On Fri, Oct 25, 2024 at 7:40 AM Dmitry Antipov <dmantipov at yandex.ru> wrote:
>
> Syzbot has reported the following KASAN splat:
>
> BUG: KASAN: slab-use-after-free in device_for_each_child+0x18f/0x1a0
> Read of size 8 at addr ffff88801f605308 by task kbnepd bnep0/4980
>
> CPU: 0 UID: 0 PID: 4980 Comm: kbnepd bnep0 Not tainted 6.12.0-rc4-00161-gae90f6a6170d #1
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-2.fc40 04/01/2014
> Call Trace:
> <TASK>
> dump_stack_lvl+0x100/0x190
> ? device_for_each_child+0x18f/0x1a0
> print_report+0x13a/0x4cb
> ? __virt_addr_valid+0x5e/0x590
> ? __phys_addr+0xc6/0x150
> ? device_for_each_child+0x18f/0x1a0
> kasan_report+0xda/0x110
> ? device_for_each_child+0x18f/0x1a0
> ? __pfx_dev_memalloc_noio+0x10/0x10
> device_for_each_child+0x18f/0x1a0
> ? __pfx_device_for_each_child+0x10/0x10
> pm_runtime_set_memalloc_noio+0xf2/0x180
> netdev_unregister_kobject+0x1ed/0x270
> unregister_netdevice_many_notify+0x123c/0x1d80
> ? __mutex_trylock_common+0xde/0x250
> ? __pfx_unregister_netdevice_many_notify+0x10/0x10
> ? trace_contention_end+0xe6/0x140
> ? __mutex_lock+0x4e7/0x8f0
> ? __pfx_lock_acquire.part.0+0x10/0x10
> ? rcu_is_watching+0x12/0xc0
> ? unregister_netdev+0x12/0x30
> unregister_netdevice_queue+0x30d/0x3f0
> ? __pfx_unregister_netdevice_queue+0x10/0x10
> ? __pfx_down_write+0x10/0x10
> unregister_netdev+0x1c/0x30
> bnep_session+0x1fb3/0x2ab0
> ? __pfx_bnep_session+0x10/0x10
> ? __pfx_lock_release+0x10/0x10
> ? __pfx_woken_wake_function+0x10/0x10
> ? __kthread_parkme+0x132/0x200
> ? __pfx_bnep_session+0x10/0x10
> ? kthread+0x13a/0x370
> ? __pfx_bnep_session+0x10/0x10
> kthread+0x2b7/0x370
> ? __pfx_kthread+0x10/0x10
> ret_from_fork+0x48/0x80
> ? __pfx_kthread+0x10/0x10
> ret_from_fork_asm+0x1a/0x30
> </TASK>
>
> Allocated by task 4974:
> kasan_save_stack+0x30/0x50
> kasan_save_track+0x14/0x30
> __kasan_kmalloc+0xaa/0xb0
> __kmalloc_noprof+0x1d1/0x440
> hci_alloc_dev_priv+0x1d/0x2820
> __vhci_create_device+0xef/0x7d0
> vhci_write+0x2c7/0x480
> vfs_write+0x6a0/0xfc0
> ksys_write+0x12f/0x260
> do_syscall_64+0xc7/0x250
> entry_SYSCALL_64_after_hwframe+0x77/0x7f
>
> Freed by task 4979:
> kasan_save_stack+0x30/0x50
> kasan_save_track+0x14/0x30
> kasan_save_free_info+0x3b/0x60
> __kasan_slab_free+0x4f/0x70
> kfree+0x141/0x490
> hci_release_dev+0x4d9/0x600
> bt_host_release+0x6a/0xb0
> device_release+0xa4/0x240
> kobject_put+0x1ec/0x5a0
> put_device+0x1f/0x30
> vhci_release+0x81/0xf0
> __fput+0x3f6/0xb30
> task_work_run+0x151/0x250
> do_exit+0xa79/0x2c30
> do_group_exit+0xd5/0x2a0
> get_signal+0x1fcd/0x2210
> arch_do_signal_or_restart+0x93/0x780
> syscall_exit_to_user_mode+0x140/0x290
> do_syscall_64+0xd4/0x250
> entry_SYSCALL_64_after_hwframe+0x77/0x7f
>
> Fix this by doing 'device_del()' later and immediately before
> freeing its 'struct hci_dev' container. Otherwise the former
> might race against 'unregister_netdev()' innards called when
> 'bnep_session()' is going to terminate.
>
> Reported-by: syzbot+6cf5652d3df49fae2e3f at syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=6cf5652d3df49fae2e3f
> Fixes: bdc3e0f1d201 ("Bluetooth: Move device_add handling into hci_register_dev")
> Signed-off-by: Dmitry Antipov <dmantipov at yandex.ru>
> ---
> net/bluetooth/hci_core.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index 96d097b21d13..f1195b110495 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -2716,7 +2716,6 @@ void hci_unregister_dev(struct hci_dev *hdev)
> rfkill_destroy(hdev->rfkill);
> }
>
> - device_del(&hdev->dev);
> /* Actual cleanup is deferred until hci_release_dev(). */
> hci_dev_put(hdev);
> }
> @@ -2756,6 +2755,8 @@ void hci_release_dev(struct hci_dev *hdev)
> kfree_skb(hdev->sent_cmd);
> kfree_skb(hdev->req_skb);
> kfree_skb(hdev->recv_event);
> +
> + device_del(&hdev->dev);
This actually doesn't work, we depend on device_del for
hci_release_dev to be called, so as the result hdev are never freed
with this change.
> kfree(hdev);
> }
> EXPORT_SYMBOL(hci_release_dev);
> --
> 2.47.0
>
--
Luiz Augusto von Dentz
More information about the lvc-project
mailing list