Original report of the bug: https://syzkaller.appspot.com/bug?id=a8d38d1b68ffc744c53bd9b9fc1dbd6c86b1afe2
Our system SyzScope detected 1 control flow hijacking about this bug.
Fuzzer tested kernel version: 2c1cfa49
Upstream patch: sctp: return error if the asoc has been peeled off in sctp_wait_for_sndbuf
[ 104.310963] =========================
[ 104.311969] WARNING: held lock freed!
[ 104.312445] 4.15.0-rc7+ #1 Not tainted
[ 104.312889] -------------------------
[ 104.313376] syz-executor/4441 is freeing memory 00000000ed825540-00000000459054b4, with a lock still held there!
[ 104.314618] (sk_lock-AF_INET6){+.+.}, at: [<0000000012233120>] sctp_wait_for_sndbuf+0x36d/0x590
[ 104.317175] 1 lock held by syz-executor/4441:
[ 104.317711] #0: (sk_lock-AF_INET6){+.+.}, at: [<0000000012233120>] sctp_wait_for_sndbuf+0x36d/0x590
[ 104.327802]
[ 104.327802] stack backtrace:
[ 104.328403] CPU: 0 PID: 4441 Comm: syz-executor Not tainted 4.15.0-rc7+ #1
[ 104.329261] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014
[ 104.330381] Call Trace:
[ 104.331295] dump_stack+0x155/0x1f2
[ 104.331766] ? arch_local_irq_restore+0x3c/0x3c
[ 104.332388] debug_check_no_locks_freed+0x217/0x220
[ 104.333061] kmem_cache_free+0x68/0x2a0
[ 104.333581] __sk_destruct+0x4eb/0x640
[ 104.334090] ? sock_rfree+0xc0/0xc0
[ 104.334562] ? inet_sendmsg+0xd5/0x380
[ 104.335666] ? SYSC_sendto+0x31e/0x3c0
[ 104.336174] ? SyS_sendto+0x40/0x50
[ 104.336650] ? entry_SYSCALL_64_fastpath+0x23/0x9a
[ 104.337295] ? debug_check_no_obj_freed+0x543/0x5e2
[ 104.337957] ? mark_lock+0x17b/0x9f0
[ 104.338455] ? mark_held_locks+0x79/0xa0
[ 104.355089] ? print_irqtrace_events+0x110/0x110
[ 104.355695] ? free_obj_work+0x390/0x390
[ 104.356215] ? sctp_put_port+0x2d4/0x320
[ 104.356714] ? sctp_poll+0x700/0x700
[ 104.357192] ? refcount_sub_and_test+0xd8/0x150
[ 104.357776] ? refcount_inc+0x50/0x50
[ 104.358250] ? refcount_inc+0x50/0x50
[ 104.359325] sk_destruct+0x38/0x60
[ 104.359748] __sk_free+0x107/0x140
[ 104.360181] sk_free+0x2a/0x40
[ 104.360564] sctp_association_put+0x106/0x1e0
[ 104.361096] ? sctp_association_hold+0x20/0x20
[ 104.361645] ? trace_hardirqs_on+0xd/0x10
[ 104.362146] ? __local_bh_enable_ip+0xcf/0x160
[ 104.363254] sctp_wait_for_sndbuf+0x481/0x590
[ 104.363857] ? sctp_init_sock+0x850/0x850
[ 104.364392] ? rcu_is_watching+0x8f/0xd0
[ 104.364904] ? rcutorture_record_progress+0x10/0x10
[ 104.365531] ? prepare_to_wait+0x260/0x260
[ 104.366091] ? trace_hardirqs_on+0xd/0x10
[ 104.374817] sctp_sendmsg+0x19ec/0x1cc0
[ 104.375328] ? sctp_id2assoc+0x210/0x210
[ 104.375838] ? check_noncircular+0x20/0x20
[ 104.376362] ? __fget+0x31c/0x480
[ 104.376802] ? lock_downgrade+0x370/0x370
[ 104.377341] ? lock_downgrade+0x370/0x370
[ 104.377886] ? find_held_lock+0x7e/0xe0
[ 104.378426] ? __asan_storeN+0x12/0x20
[ 104.387028] ? selinux_secmark_relabel_packet+0x70/0x70
[ 104.387640] ? lock_release+0x570/0x570
[ 104.388115] ? trace_event_raw_event_sched_switch+0x380/0x380
[ 104.388818] ? __check_object_size+0x23e/0x400
[ 104.389373] inet_sendmsg+0xd5/0x380
[ 104.389803] ? inet_sendmsg+0xd5/0x380
[ 104.390272] ? __might_sleep+0x6c/0xd0
[ 104.398841] ? inet_recvmsg+0x410/0x410
[ 104.399334] ? selinux_socket_sendmsg+0x24/0x30
[ 104.399919] ? security_socket_sendmsg+0x6e/0x90
[ 104.400503] ? inet_recvmsg+0x410/0x410
[ 104.400973] sock_sendmsg+0x84/0xa0
[ 104.401399] SYSC_sendto+0x31e/0x3c0
[ 104.401840] ? SYSC_connect+0x2e0/0x2e0
[ 104.402334] ? __asan_storeN+0x12/0x20
[ 104.410892] ? sock_has_perm+0x17c/0x1d0
[ 104.411421] ? selinux_secmark_relabel_packet+0x70/0x70
[ 104.412090] ? selinux_netlbl_socket_setsockopt+0xce/0x2b0
[ 104.412711] ? selinux_netlbl_sock_rcv_skb+0x440/0x440
[ 104.413289] ? selinux_socket_setsockopt+0x52/0x60
[ 104.413817] ? SyS_futex+0x22b/0x2f0
[ 104.414223] ? mark_held_locks+0x23/0xa0
[ 104.415208] ? entry_SYSCALL_64_fastpath+0x5/0x9a
[ 104.415774] SyS_sendto+0x40/0x50
[ 104.416222] entry_SYSCALL_64_fastpath+0x23/0x9a
[ 104.416859] RIP: 0033:0x45dd39
[ 104.417270] RSP: 002b:00007f903d63fc38 EFLAGS: 00000216 ORIG_RAX: 000000000000002c
[ 104.418252] RAX: ffffffffffffffda RBX: 00007f903d640700 RCX: 000000000045dd39
[ 104.435301] RDX: 0000000000000001 RSI: 000000002010bf14 RDI: 0000000000000012
[ 104.436191] RBP: 00007ffd62149050 R08: 00000000204d9000 R09: 000000000000001c
[ 104.437085] R10: 0000000000000000 R11: 0000000000000216 R12: 00007f903d63fdc0
[ 104.437995] R13: 0000000000000000 R14: 000000000071c010 R15: 00007ffd62149060
[ 104.501101] ==================================================================
[ 104.522531] BUG: KASAN: use-after-free in do_raw_spin_lock+0x1b/0x140
[ 104.523318] Read of size 4 at addr ffff88002e1f888c by task syz-executor/4441
[ 104.545831]
[ 104.546127] CPU: 0 PID: 4441 Comm: syz-executor Not tainted 4.15.0-rc7+ #1
[ 104.554701] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014
[ 104.567421] Call Trace:
[ 104.568725] dump_stack+0x155/0x1f2
[ 104.569799] ? arch_local_irq_restore+0x3c/0x3c
[ 104.570497] ? show_regs_print_info+0x18/0x18
[ 104.571063] ? do_raw_spin_lock+0x1b/0x140
[ 104.571589] print_address_description+0x73/0x250
[ 104.572175] ? do_raw_spin_lock+0x1b/0x140
[ 104.572685] kasan_report+0x25b/0x340
[ 104.573203] __asan_load4+0x78/0x80
[ 104.573654] do_raw_spin_lock+0x1b/0x140
[ 104.574175] _raw_spin_lock_bh+0x39/0x40
[ 104.574679] ? release_sock+0x73/0x1d0
[ 104.575169] release_sock+0x73/0x1d0
[ 104.594591] ? __release_sock+0x200/0x200
[ 104.598224] ? trace_hardirqs_on+0xd/0x10
[ 104.600755] sctp_sendmsg+0x1c71/0x1cc0
[ 104.614314] ? sctp_id2assoc+0x210/0x210
[ 104.616058] ? check_noncircular+0x20/0x20
[ 104.617149] ? __fget+0x31c/0x480
[ 104.618839] ? lock_downgrade+0x370/0x370
[ 104.645819] ? lock_downgrade+0x370/0x370
[ 104.650090] ? find_held_lock+0x7e/0xe0
[ 104.654376] ? __asan_storeN+0x12/0x20
[ 104.657545] ? selinux_secmark_relabel_packet+0x70/0x70
[ 104.660669] ? lock_release+0x570/0x570
[ 104.663071] ? trace_event_raw_event_sched_switch+0x380/0x380
[ 104.666470] ? __check_object_size+0x23e/0x400
[ 104.669535] inet_sendmsg+0xd5/0x380
[ 104.671914] ? inet_sendmsg+0xd5/0x380
[ 104.674215] ? __might_sleep+0x6c/0xd0
[ 104.675969] ? inet_recvmsg+0x410/0x410
[ 104.678541] ? selinux_socket_sendmsg+0x24/0x30
[ 104.680172] ? security_socket_sendmsg+0x6e/0x90
[ 104.682703] ? inet_recvmsg+0x410/0x410
[ 104.684530] sock_sendmsg+0x84/0xa0
[ 104.686589] SYSC_sendto+0x31e/0x3c0
[ 104.688328] ? SYSC_connect+0x2e0/0x2e0
[ 104.688845] ? __asan_storeN+0x12/0x20
[ 104.689627] ? sock_has_perm+0x17c/0x1d0
[ 104.690238] ? selinux_secmark_relabel_packet+0x70/0x70
[ 104.690859] ? selinux_netlbl_socket_setsockopt+0xce/0x2b0
[ 104.691509] ? selinux_netlbl_sock_rcv_skb+0x440/0x440
[ 104.692152] ? selinux_socket_setsockopt+0x52/0x60
[ 104.692730] ? SyS_futex+0x22b/0x2f0
[ 104.693161] ? mark_held_locks+0x23/0xa0
[ 104.693646] ? entry_SYSCALL_64_fastpath+0x5/0x9a
[ 104.694209] SyS_sendto+0x40/0x50
[ 104.694616] entry_SYSCALL_64_fastpath+0x23/0x9a
[ 104.695171] RIP: 0033:0x45dd39
[ 104.695541] RSP: 002b:00007f903d63fc38 EFLAGS: 00000216 ORIG_RAX: 000000000000002c
[ 104.696401] RAX: ffffffffffffffda RBX: 00007f903d640700 RCX: 000000000045dd39
[ 104.699097] RDX: 0000000000000001 RSI: 000000002010bf14 RDI: 0000000000000012
[ 104.699934] RBP: 00007ffd62149050 R08: 00000000204d9000 R09: 000000000000001c
[ 104.701433] R10: 0000000000000000 R11: 0000000000000216 R12: 00007f903d63fdc0
[ 104.704839] R13: 0000000000000000 R14: 000000000071c010 R15: 00007ffd62149060
[ 104.707242]
[ 104.708283] Allocated by task 4442:
[ 104.710050] save_stack+0x43/0xd0
[ 104.711602] kasan_kmalloc+0xad/0xe0
[ 104.713210] kasan_slab_alloc+0x12/0x20
[ 104.714073] kmem_cache_alloc+0x12e/0x760
[ 104.716090] sk_prot_alloc+0x4f/0x1d0
[ 104.717208] sk_alloc+0x105/0xcc0
[ 104.717618] sctp_v6_create_accept_sk+0x101/0x5a0
[ 104.718390] sctp_accept+0x4c4/0x680
[ 104.718837] inet_accept+0xe0/0x560
[ 104.719255] SYSC_accept4+0x2b9/0x530
[ 104.720389] SyS_accept+0x26/0x30
[ 104.748570] entry_SYSCALL_64_fastpath+0x23/0x9a
[ 104.758770]
[ 104.759301] Freed by task 4441:
[ 104.760259] save_stack+0x43/0xd0
[ 104.761347] kasan_slab_free+0x71/0xc0
[ 104.762930] kmem_cache_free+0x83/0x2a0
[ 104.764922] __sk_destruct+0x4eb/0x640
[ 104.767458] sk_destruct+0x38/0x60
[ 104.768650] __sk_free+0x107/0x140
[ 104.769541] sk_free+0x2a/0x40
[ 104.770255] sctp_association_put+0x106/0x1e0
[ 104.771117] sctp_wait_for_sndbuf+0x481/0x590
[ 104.771516] sctp_sendmsg+0x19ec/0x1cc0
[ 104.771874] inet_sendmsg+0xd5/0x380
[ 104.772190] sock_sendmsg+0x84/0xa0
[ 104.772520] SYSC_sendto+0x31e/0x3c0
[ 104.772847] SyS_sendto+0x40/0x50
[ 104.773367] entry_SYSCALL_64_fastpath+0x23/0x9a
[ 104.773935]
[ 104.774428] The buggy address belongs to the object at ffff88002e1f8800
[ 104.774428] which belongs to the cache SCTPv6 of size 1888
[ 104.782784] The buggy address is located 140 bytes inside of
[ 104.782784] 1888-byte region [ffff88002e1f8800, ffff88002e1f8f60)
[ 104.786468] The buggy address belongs to the page:
[ 104.788465] page:ffffea0000b87e00 count:1 mapcount:0 mapping:ffff88002e1f8000 index:0x0
[ 104.790484] flags: 0x1fffc0000000100(slab)
[ 104.796323] raw: 01fffc0000000100 ffff88002e1f8000 0000000000000000 0000000100000002
[ 104.798088] raw: ffffea0000b8dfe0 ffff880035286748 ffff880035287680 0000000000000000
[ 104.798856] page dumped because: kasan: bad access detected
[ 104.799352]
[ 104.799525] Memory state around the buggy address:
[ 104.799960] ffff88002e1f8780: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 104.800792] ffff88002e1f8800: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 104.801700] >ffff88002e1f8880: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 104.802412] ^
[ 104.802747] ffff88002e1f8900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 104.803396] ffff88002e1f8980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 104.804367] ==================================================================
The object sk was accidentally freed in sk_prot_free, It triggered a WARNING in kmem_cache_free, therefore this bug was labelled as "WARNING: held lock freed!"
static void sk_prot_free(struct proto *prot, struct sock *sk)
{
...
if (slab != NULL)
kmem_cache_free(slab, sk); // The object "sk" was going to be freed
...
}
void kmem_cache_free(struct kmem_cache *cachep, void *objp)
{
unsigned long flags;
cachep = cache_from_obj(cachep, objp);
if (!cachep)
return;
local_irq_save(flags);
debug_check_no_locks_freed(objp, cachep->object_size); // It triggered the WARNING in debug_check_no_locks_freed because it was trying to free a memory with a lock still held there.
if (!(cachep->flags & SLAB_DEBUG_OBJECTS))
debug_check_no_obj_freed(objp, cachep->object_size);
__cache_free(cachep, objp, _RET_IP_); // Then the object was freed
local_irq_restore(flags);
trace_kmem_cache_free(_RET_IP_, objp);
}
Even though sk was accidentally freed, the kernel was still using it in release_sock. It first triggered a UAF read when accessing a lock from sk, this action gave us a UAF read context.
And finally, sk invoke a function by sk->sk_prot->release_cb(sk). Now we hijack the control flow.
void release_sock(struct sock *sk)
{
spin_lock_bh(&sk->sk_lock.slock); // Futhermore, sk triggered a UAF read since sk was freed
if (sk->sk_backlog.tail)
__release_sock(sk);
if (sk->sk_prot->release_cb)
sk->sk_prot->release_cb(sk); // 0ops, sk dereference a function pointer. This gives us a control flow hijacking.
|do_raw_spin_lock kernel/locking/spinlock_debug.c:83(Triggered the original UAF read)
|_raw_spin_lock_bh kernel/locking/spinlock.c:169
|release_sock net/core/sock.c:2778
|release_sock net/core/sock.c:2785(Triggered a new impact: Control flow hijacking)
0xffffffff8135a5ab
do_raw_spin_lock kernel/locking/spinlock_debug.c:83(Triggered the original UAF read)
--------------------------------------
0xffffffff8135a63c
do_raw_spin_lock kernel/locking/spinlock_debug.c:72
--------------------------------------
0xffffffff81cb02f0
debug_locks_off lib/debug_locks.c:39
--------------------------------------
0xffffffff81cb02fa
debug_locks_off ./include/linux/debug_locks.h:17
--------------------------------------
0xffffffff81cb034e
debug_locks_off lib/debug_locks.c:46
--------------------------------------
0xffffffff81cb0355
debug_locks_off lib/debug_locks.c:47
--------------------------------------
0xffffffff8135a641
do_raw_spin_lock kernel/locking/spinlock_debug.c:72
--------------------------------------
0xffffffff8135a5b8
do_raw_spin_lock kernel/locking/spinlock_debug.c:84
--------------------------------------
0xffffffff8135a5c4
do_raw_spin_lock ./arch/x86/include/asm/current.h:15
--------------------------------------
0xffffffff8135a5d7
do_raw_spin_lock kernel/locking/spinlock_debug.c:85
--------------------------------------
0xffffffff8135a5e3
do_raw_spin_lock kernel/locking/spinlock_debug.c:85
--------------------------------------
0xffffffff8135a5f3
do_raw_spin_lock ./arch/x86/include/asm/atomic.h:187
--------------------------------------
0xffffffff8135a606
do_raw_spin_lock kernel/locking/spinlock_debug.c:91
--------------------------------------
0xffffffff8135a616
do_raw_spin_lock kernel/locking/spinlock_debug.c:91
--------------------------------------
0xffffffff8135a622
do_raw_spin_lock ./arch/x86/include/asm/current.h:15
--------------------------------------
0xffffffff837f9ec9
_raw_spin_lock_bh kernel/locking/spinlock.c:169
--------------------------------------
0xffffffff82cb44d3
release_sock net/core/sock.c:2778
--------------------------------------
0xffffffff82cb44df
release_sock net/core/sock.c:2778
--------------------------------------
0xffffffff82cb44f6
release_sock net/core/sock.c:2784
--------------------------------------
0xffffffff82cb44fb
release_sock net/core/sock.c:2784
--------------------------------------
0xffffffff82cb4504
release_sock net/core/sock.c:2784
--------------------------------------
0xffffffff82cb4514
release_sock net/core/sock.c:2784
--------------------------------------
0xffffffff82cb4520
release_sock net/core/sock.c:2785
--------------------------------------
0xffffffff82cb4525
release_sock net/core/sock.c:2785(Triggered a new impact: Control flow hijacking)
--------------------------------------
Total 37 basic block