|
| 1 | +From 29e1dfcd5150097f32f34891c85a50d9ead19df3 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Lihong Kou < [email protected]> |
| 3 | +Date: Tue, 23 Jun 2020 20:28:41 +0800 |
| 4 | +Subject: Bluetooth: add a mutex lock to avoid UAF in do_enale_set |
| 5 | + |
| 6 | +[ Upstream commit f9c70bdc279b191da8d60777c627702c06e4a37d ] |
| 7 | + |
| 8 | +In the case we set or free the global value listen_chan in |
| 9 | +different threads, we can encounter the UAF problems because |
| 10 | +the method is not protected by any lock, add one to avoid |
| 11 | +this bug. |
| 12 | + |
| 13 | +BUG: KASAN: use-after-free in l2cap_chan_close+0x48/0x990 |
| 14 | +net/bluetooth/l2cap_core.c:730 |
| 15 | +Read of size 8 at addr ffff888096950000 by task kworker/1:102/2868 |
| 16 | + |
| 17 | +CPU: 1 PID: 2868 Comm: kworker/1:102 Not tainted 5.5.0-syzkaller #0 |
| 18 | +Hardware name: Google Google Compute Engine/Google Compute Engine, |
| 19 | +BIOS Google 01/01/2011 |
| 20 | +Workqueue: events do_enable_set |
| 21 | +Call Trace: |
| 22 | + __dump_stack lib/dump_stack.c:77 [inline] |
| 23 | + dump_stack+0x1fb/0x318 lib/dump_stack.c:118 |
| 24 | + print_address_description+0x74/0x5c0 mm/kasan/report.c:374 |
| 25 | + __kasan_report+0x149/0x1c0 mm/kasan/report.c:506 |
| 26 | + kasan_report+0x26/0x50 mm/kasan/common.c:641 |
| 27 | + __asan_report_load8_noabort+0x14/0x20 mm/kasan/generic_report.c:135 |
| 28 | + l2cap_chan_close+0x48/0x990 net/bluetooth/l2cap_core.c:730 |
| 29 | + do_enable_set+0x660/0x900 net/bluetooth/6lowpan.c:1074 |
| 30 | + process_one_work+0x7f5/0x10f0 kernel/workqueue.c:2264 |
| 31 | + worker_thread+0xbbc/0x1630 kernel/workqueue.c:2410 |
| 32 | + kthread+0x332/0x350 kernel/kthread.c:255 |
| 33 | + ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:352 |
| 34 | + |
| 35 | +Allocated by task 2870: |
| 36 | + save_stack mm/kasan/common.c:72 [inline] |
| 37 | + set_track mm/kasan/common.c:80 [inline] |
| 38 | + __kasan_kmalloc+0x118/0x1c0 mm/kasan/common.c:515 |
| 39 | + kasan_kmalloc+0x9/0x10 mm/kasan/common.c:529 |
| 40 | + kmem_cache_alloc_trace+0x221/0x2f0 mm/slab.c:3551 |
| 41 | + kmalloc include/linux/slab.h:555 [inline] |
| 42 | + kzalloc include/linux/slab.h:669 [inline] |
| 43 | + l2cap_chan_create+0x50/0x320 net/bluetooth/l2cap_core.c:446 |
| 44 | + chan_create net/bluetooth/6lowpan.c:640 [inline] |
| 45 | + bt_6lowpan_listen net/bluetooth/6lowpan.c:959 [inline] |
| 46 | + do_enable_set+0x6a4/0x900 net/bluetooth/6lowpan.c:1078 |
| 47 | + process_one_work+0x7f5/0x10f0 kernel/workqueue.c:2264 |
| 48 | + worker_thread+0xbbc/0x1630 kernel/workqueue.c:2410 |
| 49 | + kthread+0x332/0x350 kernel/kthread.c:255 |
| 50 | + ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:352 |
| 51 | + |
| 52 | +Freed by task 2870: |
| 53 | + save_stack mm/kasan/common.c:72 [inline] |
| 54 | + set_track mm/kasan/common.c:80 [inline] |
| 55 | + kasan_set_free_info mm/kasan/common.c:337 [inline] |
| 56 | + __kasan_slab_free+0x12e/0x1e0 mm/kasan/common.c:476 |
| 57 | + kasan_slab_free+0xe/0x10 mm/kasan/common.c:485 |
| 58 | + __cache_free mm/slab.c:3426 [inline] |
| 59 | + kfree+0x10d/0x220 mm/slab.c:3757 |
| 60 | + l2cap_chan_destroy net/bluetooth/l2cap_core.c:484 [inline] |
| 61 | + kref_put include/linux/kref.h:65 [inline] |
| 62 | + l2cap_chan_put+0x170/0x190 net/bluetooth/l2cap_core.c:498 |
| 63 | + do_enable_set+0x66c/0x900 net/bluetooth/6lowpan.c:1075 |
| 64 | + process_one_work+0x7f5/0x10f0 kernel/workqueue.c:2264 |
| 65 | + worker_thread+0xbbc/0x1630 kernel/workqueue.c:2410 |
| 66 | + kthread+0x332/0x350 kernel/kthread.c:255 |
| 67 | + ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:352 |
| 68 | + |
| 69 | +The buggy address belongs to the object at ffff888096950000 |
| 70 | + which belongs to the cache kmalloc-2k of size 2048 |
| 71 | +The buggy address is located 0 bytes inside of |
| 72 | + 2048-byte region [ffff888096950000, ffff888096950800) |
| 73 | +The buggy address belongs to the page: |
| 74 | +page:ffffea00025a5400 refcount:1 mapcount:0 mapping:ffff8880aa400e00 index:0x0 |
| 75 | +flags: 0xfffe0000000200(slab) |
| 76 | +raw: 00fffe0000000200 ffffea00027d1548 ffffea0002397808 ffff8880aa400e00 |
| 77 | +raw: 0000000000000000 ffff888096950000 0000000100000001 0000000000000000 |
| 78 | +page dumped because: kasan: bad access detected |
| 79 | + |
| 80 | +Memory state around the buggy address: |
| 81 | + ffff88809694ff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
| 82 | + ffff88809694ff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
| 83 | +>ffff888096950000: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb |
| 84 | + ^ |
| 85 | + ffff888096950080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb |
| 86 | + ffff888096950100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb |
| 87 | +================================================================== |
| 88 | + |
| 89 | + |
| 90 | +Signed-off-by: Lihong Kou < [email protected]> |
| 91 | +Signed-off-by: Marcel Holtmann < [email protected]> |
| 92 | +Signed-off-by: Sasha Levin < [email protected]> |
| 93 | +--- |
| 94 | + net/bluetooth/6lowpan.c | 5 +++++ |
| 95 | + 1 file changed, 5 insertions(+) |
| 96 | + |
| 97 | +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c |
| 98 | +index 357475cceec61b..9a75f9b00b5129 100644 |
| 99 | +--- a/net/bluetooth/6lowpan.c |
| 100 | ++++ b/net/bluetooth/6lowpan.c |
| 101 | +@@ -57,6 +57,7 @@ static bool enable_6lowpan; |
| 102 | + /* We are listening incoming connections via this channel |
| 103 | + */ |
| 104 | + static struct l2cap_chan *listen_chan; |
| 105 | ++static DEFINE_MUTEX(set_lock); |
| 106 | + |
| 107 | + struct lowpan_peer { |
| 108 | + struct list_head list; |
| 109 | +@@ -1082,12 +1083,14 @@ static void do_enable_set(struct work_struct *work) |
| 110 | + |
| 111 | + enable_6lowpan = set_enable->flag; |
| 112 | + |
| 113 | ++ mutex_lock(&set_lock); |
| 114 | + if (listen_chan) { |
| 115 | + l2cap_chan_close(listen_chan, 0); |
| 116 | + l2cap_chan_put(listen_chan); |
| 117 | + } |
| 118 | + |
| 119 | + listen_chan = bt_6lowpan_listen(); |
| 120 | ++ mutex_unlock(&set_lock); |
| 121 | + |
| 122 | + kfree(set_enable); |
| 123 | + } |
| 124 | +@@ -1139,11 +1142,13 @@ static ssize_t lowpan_control_write(struct file *fp, |
| 125 | + if (ret == -EINVAL) |
| 126 | + return ret; |
| 127 | + |
| 128 | ++ mutex_lock(&set_lock); |
| 129 | + if (listen_chan) { |
| 130 | + l2cap_chan_close(listen_chan, 0); |
| 131 | + l2cap_chan_put(listen_chan); |
| 132 | + listen_chan = NULL; |
| 133 | + } |
| 134 | ++ mutex_unlock(&set_lock); |
| 135 | + |
| 136 | + if (conn) { |
| 137 | + struct lowpan_peer *peer; |
| 138 | +-- |
| 139 | +cgit 1.2.3-korg |
| 140 | + |
0 commit comments