D Desmond Cheong Zhi Xi #
Message details and related content
Syzbot reported a use-after-free Write in sco_sock_timeout [1]: ================================================================== BUG: KASAN: use-after-free in instrument_atomic_read_write include/linux/instrumented.h:101 [inline] BUG: KASAN: use-after-free in atomic_fetch_add_relaxed include/asm-generic/atomic-instrumented.h:111 [inline] BUG: KASAN: use-after-free in __refcount_add include/linux/refcount.h:193 [inline] BUG: KASAN: use-after-free in __refcount_inc include/linux/refcount.h:250 [inline] BUG: KASAN: use-after-free in refcount_inc include/linux/refcount.h:267 [inline] BUG: KASAN: use-after-free in sock_hold include/net/sock.h:702 [inline] BUG: KASAN: use-after-free in sco_sock_timeout+0x64/0x290 net/bluetooth/sco.c:88 Write of size 4 at addr ffff888034b46080 by task kworker/1:0/20 CPU: 1 PID: 20 Comm: kworker/1:0 Not tainted 5.14.0-rc6-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Workqueue: events sco_sock_timeout Call Trace: __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0xcd/0x134 lib/dump_stack.c:105 print_address_description.constprop.0.cold+0x6c/0x309 mm/kasan/report.c:233 __kasan_report mm/kasan/report.c:419 [inline] kasan_report.cold+0x83/0xdf mm/kasan/report.c:436 check_region_inline mm/kasan/generic.c:183 [inline] kasan_check_range+0x13d/0x180 mm/kasan/generic.c:189 instrument_atomic_read_write include/linux/instrumented.h:101 [inline] atomic_fetch_add_relaxed include/asm-generic/atomic-instrumented.h:111 [inline] __refcount_add include/linux/refcount.h:193 [inline] __refcount_inc include/linux/refcount.h:250 [inline] refcount_inc include/linux/refcount.h:267 [inline] sock_hold include/net/sock.h:702 [inline] sco_sock_timeout+0x64/0x290 net/bluetooth/sco.c:88 process_one_work+0x98d/0x1630 kernel/workqueue.c:2276 worker_thread+0x658/0x11f0 kernel/workqueue.c:2422 kthread+0x3e5/0x4d0 kernel/kthread.c:319 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:295 Allocated by task 4872: kasan_save_stack+0x1b/0x40 mm/kasan/common.c:38 kasan_set_track mm/kasan/common.c:46 [inline] set_alloc_info mm/kasan/common.c:434 [inline] ____kasan_kmalloc mm/kasan/common.c:513 [inline]
ffff888034b46080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^ ffff888034b46100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff888034b46180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ================================================================== sco_sock_connect checks the socket's state before allocating a new SCO connection and creating a channel for it with the given socket. However, because this check occurs outside the socket lock, multiple concurrent calls to sco_sock_connect are able to pass the check before serially entering the critical section and making multiple recursive calls to sco_connect. The result is that multiple SCO connections are allocated, but each connection overrides the socket's channel with the previous connection. This may cause a UAF because the overwritten connections can't have their channels deleted when the socket is released, so sco_sock_timeout is able to access the freed socket. Fix this by checking the socket's state after the socket is locked in sco_sock_connect. Link: https://syzkaller.appspot.com/bug?extid=2bef95d3ab4daa10155b [1] Reported-by: <redacted> Tested-by: <redacted> Signed-off-by: Desmond Cheong Zhi Xi <redacted> Cc: Hillf Danton <redacted> --- net/bluetooth/sco.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 98a881586512..fa25b07120c9 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c@@ -578,9 +578,6 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen addr->sa_family != AF_BLUETOOTH) return -EINVAL; - if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) - return -EBADFD; - if (sk->sk_type != SOCK_SEQPACKET) return -EINVAL;
@@ -591,6 +588,13 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen lock_sock(sk); + if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) { + hci_dev_unlock(hdev); + hci_dev_put(hdev); + err = -EBADFD; + goto done; + } + /* Set destination address and psm */ bacpy(&sco_pi(sk)->dst, &sa->sco_bdaddr);
--
2.25.1