| From b22154c5d02bc5c2ca7204861af9ffa99e48ef35 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 23 Jun 2020 20:28:41 +0800 |
| Subject: Bluetooth: add a mutex lock to avoid UAF in do_enale_set |
| |
| From: Lihong Kou <koulihong@huawei.com> |
| |
| [ Upstream commit f9c70bdc279b191da8d60777c627702c06e4a37d ] |
| |
| In the case we set or free the global value listen_chan in |
| different threads, we can encounter the UAF problems because |
| the method is not protected by any lock, add one to avoid |
| this bug. |
| |
| BUG: KASAN: use-after-free in l2cap_chan_close+0x48/0x990 |
| net/bluetooth/l2cap_core.c:730 |
| Read of size 8 at addr ffff888096950000 by task kworker/1:102/2868 |
| |
| CPU: 1 PID: 2868 Comm: kworker/1:102 Not tainted 5.5.0-syzkaller #0 |
| Hardware name: Google Google Compute Engine/Google Compute Engine, |
| BIOS Google 01/01/2011 |
| Workqueue: events do_enable_set |
| Call Trace: |
| __dump_stack lib/dump_stack.c:77 [inline] |
| dump_stack+0x1fb/0x318 lib/dump_stack.c:118 |
| print_address_description+0x74/0x5c0 mm/kasan/report.c:374 |
| __kasan_report+0x149/0x1c0 mm/kasan/report.c:506 |
| kasan_report+0x26/0x50 mm/kasan/common.c:641 |
| __asan_report_load8_noabort+0x14/0x20 mm/kasan/generic_report.c:135 |
| l2cap_chan_close+0x48/0x990 net/bluetooth/l2cap_core.c:730 |
| do_enable_set+0x660/0x900 net/bluetooth/6lowpan.c:1074 |
| process_one_work+0x7f5/0x10f0 kernel/workqueue.c:2264 |
| worker_thread+0xbbc/0x1630 kernel/workqueue.c:2410 |
| kthread+0x332/0x350 kernel/kthread.c:255 |
| ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:352 |
| |
| Allocated by task 2870: |
| save_stack mm/kasan/common.c:72 [inline] |
| set_track mm/kasan/common.c:80 [inline] |
| __kasan_kmalloc+0x118/0x1c0 mm/kasan/common.c:515 |
| kasan_kmalloc+0x9/0x10 mm/kasan/common.c:529 |
| kmem_cache_alloc_trace+0x221/0x2f0 mm/slab.c:3551 |
| kmalloc include/linux/slab.h:555 [inline] |
| kzalloc include/linux/slab.h:669 [inline] |
| l2cap_chan_create+0x50/0x320 net/bluetooth/l2cap_core.c:446 |
| chan_create net/bluetooth/6lowpan.c:640 [inline] |
| bt_6lowpan_listen net/bluetooth/6lowpan.c:959 [inline] |
| do_enable_set+0x6a4/0x900 net/bluetooth/6lowpan.c:1078 |
| process_one_work+0x7f5/0x10f0 kernel/workqueue.c:2264 |
| worker_thread+0xbbc/0x1630 kernel/workqueue.c:2410 |
| kthread+0x332/0x350 kernel/kthread.c:255 |
| ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:352 |
| |
| Freed by task 2870: |
| save_stack mm/kasan/common.c:72 [inline] |
| set_track mm/kasan/common.c:80 [inline] |
| kasan_set_free_info mm/kasan/common.c:337 [inline] |
| __kasan_slab_free+0x12e/0x1e0 mm/kasan/common.c:476 |
| kasan_slab_free+0xe/0x10 mm/kasan/common.c:485 |
| __cache_free mm/slab.c:3426 [inline] |
| kfree+0x10d/0x220 mm/slab.c:3757 |
| l2cap_chan_destroy net/bluetooth/l2cap_core.c:484 [inline] |
| kref_put include/linux/kref.h:65 [inline] |
| l2cap_chan_put+0x170/0x190 net/bluetooth/l2cap_core.c:498 |
| do_enable_set+0x66c/0x900 net/bluetooth/6lowpan.c:1075 |
| process_one_work+0x7f5/0x10f0 kernel/workqueue.c:2264 |
| worker_thread+0xbbc/0x1630 kernel/workqueue.c:2410 |
| kthread+0x332/0x350 kernel/kthread.c:255 |
| ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:352 |
| |
| The buggy address belongs to the object at ffff888096950000 |
| which belongs to the cache kmalloc-2k of size 2048 |
| The buggy address is located 0 bytes inside of |
| 2048-byte region [ffff888096950000, ffff888096950800) |
| The buggy address belongs to the page: |
| page:ffffea00025a5400 refcount:1 mapcount:0 mapping:ffff8880aa400e00 index:0x0 |
| flags: 0xfffe0000000200(slab) |
| raw: 00fffe0000000200 ffffea00027d1548 ffffea0002397808 ffff8880aa400e00 |
| raw: 0000000000000000 ffff888096950000 0000000100000001 0000000000000000 |
| page dumped because: kasan: bad access detected |
| |
| Memory state around the buggy address: |
| ffff88809694ff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
| ffff88809694ff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
| >ffff888096950000: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb |
| ^ |
| ffff888096950080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb |
| ffff888096950100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb |
| ================================================================== |
| |
| Reported-by: syzbot+96414aa0033c363d8458@syzkaller.appspotmail.com |
| Signed-off-by: Lihong Kou <koulihong@huawei.com> |
| Signed-off-by: Marcel Holtmann <marcel@holtmann.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| net/bluetooth/6lowpan.c | 5 +++++ |
| 1 file changed, 5 insertions(+) |
| |
| diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c |
| index 4cd6b8d811ffa..11602902884ba 100644 |
| --- a/net/bluetooth/6lowpan.c |
| +++ b/net/bluetooth/6lowpan.c |
| @@ -57,6 +57,7 @@ static bool enable_6lowpan; |
| /* We are listening incoming connections via this channel |
| */ |
| static struct l2cap_chan *listen_chan; |
| +static DEFINE_MUTEX(set_lock); |
| |
| struct lowpan_peer { |
| struct list_head list; |
| @@ -1195,12 +1196,14 @@ static void do_enable_set(struct work_struct *work) |
| |
| enable_6lowpan = set_enable->flag; |
| |
| + mutex_lock(&set_lock); |
| if (listen_chan) { |
| l2cap_chan_close(listen_chan, 0); |
| l2cap_chan_put(listen_chan); |
| } |
| |
| listen_chan = bt_6lowpan_listen(); |
| + mutex_unlock(&set_lock); |
| |
| kfree(set_enable); |
| } |
| @@ -1252,11 +1255,13 @@ static ssize_t lowpan_control_write(struct file *fp, |
| if (ret == -EINVAL) |
| return ret; |
| |
| + mutex_lock(&set_lock); |
| if (listen_chan) { |
| l2cap_chan_close(listen_chan, 0); |
| l2cap_chan_put(listen_chan); |
| listen_chan = NULL; |
| } |
| + mutex_unlock(&set_lock); |
| |
| if (conn) { |
| struct lowpan_peer *peer; |
| -- |
| 2.25.1 |
| |