Takashi Iwai daddd4
From 5c4c8c9544099bb9043a10a5318130a943e32fc3 Mon Sep 17 00:00:00 2001
Takashi Iwai daddd4
From: Archie Pusaka <apusaka@chromium.org>
Takashi Iwai daddd4
Date: Mon, 22 Mar 2021 14:03:11 +0800
Takashi Iwai daddd4
Subject: [PATCH] Bluetooth: verify AMP hci_chan before amp_destroy
Takashi Iwai daddd4
Git-commit: 5c4c8c9544099bb9043a10a5318130a943e32fc3
Takashi Iwai daddd4
Patch-mainline: v5.13-rc1
Takashi Iwai daddd4
References: CVE-2021-33034 bsc#1186111
Takashi Iwai daddd4
Takashi Iwai daddd4
hci_chan can be created in 2 places: hci_loglink_complete_evt() if
Takashi Iwai daddd4
it is an AMP hci_chan, or l2cap_conn_add() otherwise. In theory,
Takashi Iwai daddd4
Only AMP hci_chan should be removed by a call to
Takashi Iwai daddd4
hci_disconn_loglink_complete_evt(). However, the controller might mess
Takashi Iwai daddd4
up, call that function, and destroy an hci_chan which is not initiated
Takashi Iwai daddd4
by hci_loglink_complete_evt().
Takashi Iwai daddd4
Takashi Iwai daddd4
This patch adds a verification that the destroyed hci_chan must have
Takashi Iwai daddd4
been init'd by hci_loglink_complete_evt().
Takashi Iwai daddd4
Takashi Iwai daddd4
Example crash call trace:
Takashi Iwai daddd4
Call Trace:
Takashi Iwai daddd4
 __dump_stack lib/dump_stack.c:77 [inline]
Takashi Iwai daddd4
 dump_stack+0xe3/0x144 lib/dump_stack.c:118
Takashi Iwai daddd4
 print_address_description+0x67/0x22a mm/kasan/report.c:256
Takashi Iwai daddd4
 kasan_report_error mm/kasan/report.c:354 [inline]
Takashi Iwai daddd4
 kasan_report mm/kasan/report.c:412 [inline]
Takashi Iwai daddd4
 kasan_report+0x251/0x28f mm/kasan/report.c:396
Takashi Iwai daddd4
 hci_send_acl+0x3b/0x56e net/bluetooth/hci_core.c:4072
Takashi Iwai daddd4
 l2cap_send_cmd+0x5af/0x5c2 net/bluetooth/l2cap_core.c:877
Takashi Iwai daddd4
 l2cap_send_move_chan_cfm_icid+0x8e/0xb1 net/bluetooth/l2cap_core.c:4661
Takashi Iwai daddd4
 l2cap_move_fail net/bluetooth/l2cap_core.c:5146 [inline]
Takashi Iwai daddd4
 l2cap_move_channel_rsp net/bluetooth/l2cap_core.c:5185 [inline]
Takashi Iwai daddd4
 l2cap_bredr_sig_cmd net/bluetooth/l2cap_core.c:5464 [inline]
Takashi Iwai daddd4
 l2cap_sig_channel net/bluetooth/l2cap_core.c:5799 [inline]
Takashi Iwai daddd4
 l2cap_recv_frame+0x1d12/0x51aa net/bluetooth/l2cap_core.c:7023
Takashi Iwai daddd4
 l2cap_recv_acldata+0x2ea/0x693 net/bluetooth/l2cap_core.c:7596
Takashi Iwai daddd4
 hci_acldata_packet net/bluetooth/hci_core.c:4606 [inline]
Takashi Iwai daddd4
 hci_rx_work+0x2bd/0x45e net/bluetooth/hci_core.c:4796
Takashi Iwai daddd4
 process_one_work+0x6f8/0xb50 kernel/workqueue.c:2175
Takashi Iwai daddd4
 worker_thread+0x4fc/0x670 kernel/workqueue.c:2321
Takashi Iwai daddd4
 kthread+0x2f0/0x304 kernel/kthread.c:253
Takashi Iwai daddd4
 ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:415
Takashi Iwai daddd4
Takashi Iwai daddd4
Allocated by task 38:
Takashi Iwai daddd4
 set_track mm/kasan/kasan.c:460 [inline]
Takashi Iwai daddd4
 kasan_kmalloc+0x8d/0x9a mm/kasan/kasan.c:553
Takashi Iwai daddd4
 kmem_cache_alloc_trace+0x102/0x129 mm/slub.c:2787
Takashi Iwai daddd4
 kmalloc include/linux/slab.h:515 [inline]
Takashi Iwai daddd4
 kzalloc include/linux/slab.h:709 [inline]
Takashi Iwai daddd4
 hci_chan_create+0x86/0x26d net/bluetooth/hci_conn.c:1674
Takashi Iwai daddd4
 l2cap_conn_add.part.0+0x1c/0x814 net/bluetooth/l2cap_core.c:7062
Takashi Iwai daddd4
 l2cap_conn_add net/bluetooth/l2cap_core.c:7059 [inline]
Takashi Iwai daddd4
 l2cap_connect_cfm+0x134/0x852 net/bluetooth/l2cap_core.c:7381
Takashi Iwai daddd4
 hci_connect_cfm+0x9d/0x122 include/net/bluetooth/hci_core.h:1404
Takashi Iwai daddd4
 hci_remote_ext_features_evt net/bluetooth/hci_event.c:4161 [inline]
Takashi Iwai daddd4
 hci_event_packet+0x463f/0x72fa net/bluetooth/hci_event.c:5981
Takashi Iwai daddd4
 hci_rx_work+0x197/0x45e net/bluetooth/hci_core.c:4791
Takashi Iwai daddd4
 process_one_work+0x6f8/0xb50 kernel/workqueue.c:2175
Takashi Iwai daddd4
 worker_thread+0x4fc/0x670 kernel/workqueue.c:2321
Takashi Iwai daddd4
 kthread+0x2f0/0x304 kernel/kthread.c:253
Takashi Iwai daddd4
 ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:415
Takashi Iwai daddd4
Takashi Iwai daddd4
Freed by task 1732:
Takashi Iwai daddd4
 set_track mm/kasan/kasan.c:460 [inline]
Takashi Iwai daddd4
 __kasan_slab_free mm/kasan/kasan.c:521 [inline]
Takashi Iwai daddd4
 __kasan_slab_free+0x106/0x128 mm/kasan/kasan.c:493
Takashi Iwai daddd4
 slab_free_hook mm/slub.c:1409 [inline]
Takashi Iwai daddd4
 slab_free_freelist_hook+0xaa/0xf6 mm/slub.c:1436
Takashi Iwai daddd4
 slab_free mm/slub.c:3009 [inline]
Takashi Iwai daddd4
 kfree+0x182/0x21e mm/slub.c:3972
Takashi Iwai daddd4
 hci_disconn_loglink_complete_evt net/bluetooth/hci_event.c:4891 [inline]
Takashi Iwai daddd4
 hci_event_packet+0x6a1c/0x72fa net/bluetooth/hci_event.c:6050
Takashi Iwai daddd4
 hci_rx_work+0x197/0x45e net/bluetooth/hci_core.c:4791
Takashi Iwai daddd4
 process_one_work+0x6f8/0xb50 kernel/workqueue.c:2175
Takashi Iwai daddd4
 worker_thread+0x4fc/0x670 kernel/workqueue.c:2321
Takashi Iwai daddd4
 kthread+0x2f0/0x304 kernel/kthread.c:253
Takashi Iwai daddd4
 ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:415
Takashi Iwai daddd4
Takashi Iwai daddd4
The buggy address belongs to the object at ffff8881d7af9180
Takashi Iwai daddd4
 which belongs to the cache kmalloc-128 of size 128
Takashi Iwai daddd4
The buggy address is located 24 bytes inside of
Takashi Iwai daddd4
 128-byte region [ffff8881d7af9180, ffff8881d7af9200)
Takashi Iwai daddd4
The buggy address belongs to the page:
Takashi Iwai daddd4
page:ffffea00075ebe40 count:1 mapcount:0 mapping:ffff8881da403200 index:0x0
Takashi Iwai daddd4
Flags: 0x8000000000000200(slab)
Takashi Iwai daddd4
Raw: 8000000000000200 dead000000000100 dead000000000200 ffff8881da403200
Takashi Iwai daddd4
Raw: 0000000000000000 0000000080150015 00000001ffffffff 0000000000000000
Takashi Iwai daddd4
page dumped because: kasan: bad access detected
Takashi Iwai daddd4
Takashi Iwai daddd4
Memory state around the buggy address:
Takashi Iwai daddd4
 ffff8881d7af9080: fc fc fc fc fc fc fc fc fb fb fb fb fb fb fb fb
Takashi Iwai daddd4
 ffff8881d7af9100: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
Takashi Iwai daddd4
>ffff8881d7af9180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb                            ^ ffff8881d7af9200: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc ffff8881d7af9280: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
Takashi Iwai daddd4
Takashi Iwai daddd4
Signed-off-by: Archie Pusaka <apusaka@chromium.org>
Takashi Iwai daddd4
Reported-by: syzbot+98228e7407314d2d4ba2@syzkaller.appspotmail.com
Takashi Iwai daddd4
Reviewed-by: Alain Michaud <alainm@chromium.org>
Takashi Iwai daddd4
Reviewed-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
Takashi Iwai daddd4
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Takashi Iwai daddd4
Acked-by: Takashi Iwai <tiwai@suse.de>
Takashi Iwai daddd4
Takashi Iwai daddd4
---
Takashi Iwai daddd4
 include/net/bluetooth/hci_core.h | 1 +
Takashi Iwai daddd4
 net/bluetooth/hci_event.c        | 3 ++-
Takashi Iwai daddd4
 2 files changed, 3 insertions(+), 1 deletion(-)
Takashi Iwai daddd4
Takashi Iwai daddd4
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
Takashi Iwai daddd4
index ebdd4afe30d2..ca4ac6603b9a 100644
Takashi Iwai daddd4
--- a/include/net/bluetooth/hci_core.h
Takashi Iwai daddd4
+++ b/include/net/bluetooth/hci_core.h
Takashi Iwai daddd4
@@ -704,6 +704,7 @@ struct hci_chan {
Takashi Iwai daddd4
 	struct sk_buff_head data_q;
Takashi Iwai daddd4
 	unsigned int	sent;
Takashi Iwai daddd4
 	__u8		state;
Takashi Iwai daddd4
+	bool		amp;
Takashi Iwai daddd4
 };
Takashi Iwai daddd4
 
Takashi Iwai daddd4
 struct hci_conn_params {
Takashi Iwai daddd4
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
Takashi Iwai daddd4
index cf2f4a0abdbd..341c8ce93648 100644
Takashi Iwai daddd4
--- a/net/bluetooth/hci_event.c
Takashi Iwai daddd4
+++ b/net/bluetooth/hci_event.c
Takashi Iwai daddd4
@@ -5032,6 +5032,7 @@ static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
Takashi Iwai daddd4
 		return;
Takashi Iwai daddd4
 
Takashi Iwai daddd4
 	hchan->handle = le16_to_cpu(ev->handle);
Takashi Iwai daddd4
+	hchan->amp = true;
Takashi Iwai daddd4
 
Takashi Iwai daddd4
 	BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
Takashi Iwai daddd4
 
Takashi Iwai daddd4
@@ -5064,7 +5065,7 @@ static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
Takashi Iwai daddd4
 	hci_dev_lock(hdev);
Takashi Iwai daddd4
 
Takashi Iwai daddd4
 	hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
Takashi Iwai daddd4
-	if (!hchan)
Takashi Iwai daddd4
+	if (!hchan || !hchan->amp)
Takashi Iwai daddd4
 		goto unlock;
Takashi Iwai daddd4
 
Takashi Iwai daddd4
 	amp_destroy_logical_link(hchan, ev->reason);
Takashi Iwai daddd4
-- 
Takashi Iwai daddd4
2.26.2
Takashi Iwai daddd4