KASAN: use-after-free Read in io_async_task_func
Original report of the bug: https://syzkaller.appspot.com/bug?id=ce5f07d6ec3b5050b8f0728a3b389aa510f2591b
Our system SyzScope detected a control flow hijacking from this bug.
Fuzzer tested kernel version: fc80c51f
Upstream patch: io_uring: hold 'ctx' reference around task_work queue + execute
Primitive 1: Control flow hijacking in try_to_wake_up
Bug impact analysis:
The vulnerable object was accidentally freed when one thread is executing function __io_req_task_submit. The UAF read happens when it enters mutex_unlock, the entire ctx object was freed.
static void __io_req_task_submit(struct io_kiocb *req)
{
struct io_ring_ctx *ctx = req->ctx;
if (!__io_sq_thread_acquire_mm(ctx)) {
mutex_lock(&ctx->uring_lock);
__io_queue_sqe(req, NULL, NULL); // For some reason the ctx was freed by another thread
mutex_unlock(&ctx->uring_lock); // The UAF read happens in this mutex_unlock
} else {
__io_req_task_cancel(req, -EFAULT);
}
}
The waiter->task was added to a list wake_q
static noinline void __sched __mutex_unlock_slowpath(struct mutex *lock, unsigned long ip)
{
owner = atomic_long_read(&lock->owner); // The original UAF read in Kasan report
...
if (!list_empty(&lock->wait_list)) {
struct mutex_waiter *waiter = // "waiter" comes from the freed object
list_first_entry(&lock->wait_list,
struct mutex_waiter, list);
next = waiter->task; // "next" eventually comes from the freed object
debug_mutex_wake_waiter(lock, waiter);
wake_q_add(&wake_q, next); // Then, "next" was added to wake_q, it's the head of this list
}
if (owner & MUTEX_FLAG_HANDOFF)
__mutex_handoff(lock, next);
spin_unlock(&lock->wait_lock);
wake_up_q(&wake_q); // The "wake_q" entered wake_up_q
}
The waiter->task get out of the list and pass to wake_up_process, it finally reach to try_to_wake_up
void wake_up_q(struct wake_q_head *head)
{
struct wake_q_node *node = head->first;
while (node != WAKE_Q_TAIL) {
struct task_struct *task;
task = container_of(node, struct task_struct, wake_q); // retrieve the task from the list, now we get the one comes from freed object
BUG_ON(!task);
node = node->next;
task->wake_q.next = NULL;
wake_up_process(task); // pass the task to wake_up_process
put_task_struct(task);
}
}
int wake_up_process(struct task_struct *p)
{
return try_to_wake_up(p, TASK_NORMAL, 0);
}
The entire task_struct comes from the freed object, therefore the attacker can control the entire object.
try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
{
...
cpu = select_task_rq(p, p->wake_cpu, SD_BALANCE_WAKE, wake_flags); // p comes from the freed object
...
}
Here is the control flow hijacking
int select_task_rq(struct task_struct *p, int cpu, int sd_flags, int wake_flags)
{
lockdep_assert_held(&p->pi_lock);
if (p->nr_cpus_allowed > 1)
cpu = p->sched_class->select_task_rq(p, cpu, sd_flags, wake_flags); // Control flow hijacking happens here since p comes from the freed object.
else
...
...
}
Trace in high level:
|__mutex_unlock_slowpath kernel/locking/mutex.c:1242(Triggered the UAF read)
|wake_up_q None:None
|try_to_wake_up kernel/sched/core.c:590
|None kernel/sched/core.c:2360(Triggered a new impact which we identify: Control flow hijacking)
Trace in detail(we confirm this trace can occur in practice):
0xffffffff855adddf
__mutex_unlock_slowpath kernel/locking/mutex.c:1242(Triggered the UAF read)
--------------------------------------
0xffffffff855adde8
__mutex_unlock_slowpath kernel/locking/mutex.c:80
--------------------------------------
0xffffffff855addfd
__mutex_unlock_slowpath kernel/locking/mutex.c:1243
--------------------------------------
0xffffffff855ade09
__mutex_unlock_slowpath kernel/locking/mutex.c:1243
--------------------------------------
0xffffffff855ade18
__mutex_unlock_slowpath kernel/locking/mutex.c:1246
--------------------------------------
0xffffffff855ade22
__mutex_unlock_slowpath kernel/locking/mutex.c:101
--------------------------------------
0xffffffff855ade42
__mutex_unlock_slowpath kernel/locking/mutex.c:1251
--------------------------------------
0xffffffff855adebd
__mutex_unlock_slowpath kernel/locking/mutex.c:1252
--------------------------------------
0xffffffff855b3c70
_raw_spin_lock kernel/locking/spinlock.c:150
--------------------------------------
0xffffffff8137b110
preempt_count_add kernel/sched/core.c:4174
--------------------------------------
0xffffffff8137b12c
preempt_count_add kernel/sched/core.c:4187
--------------------------------------
0xffffffff813dd110
in_lock_functions kernel/locking/spinlock.c:392
--------------------------------------
0xffffffff813dd110
in_lock_functions kernel/locking/spinlock.c:392
--------------------------------------
0xffffffff8137b19a
preempt_count_add kernel/sched/core.c:4167
--------------------------------------
0xffffffff813cd4d0
lock_acquire kernel/locking/lockdep.c:4977
--------------------------------------
0xffffffff813e0fe0
do_raw_spin_lock kernel/locking/spinlock_debug.c:111
--------------------------------------
0xffffffff813e100d
do_raw_spin_lock kernel/locking/spinlock_debug.c:83
--------------------------------------
0xffffffff813e101c
do_raw_spin_lock kernel/locking/spinlock_debug.c:84
--------------------------------------
0xffffffff813e1028
do_raw_spin_lock kernel/locking/spinlock_debug.c:84
--------------------------------------
0xffffffff813e1042
do_raw_spin_lock kernel/locking/spinlock_debug.c:85
--------------------------------------
0xffffffff813e104e
do_raw_spin_lock kernel/locking/spinlock_debug.c:85
--------------------------------------
0xffffffff813e1061
do_raw_spin_lock kernel/locking/spinlock_debug.c:85
--------------------------------------
0xffffffff813e10aa
do_raw_spin_lock kernel/locking/spinlock_debug.c:91
--------------------------------------
0xffffffff813e10b9
do_raw_spin_lock kernel/locking/spinlock_debug.c:91
--------------------------------------
0xffffffff813e10c5
do_raw_spin_lock kernel/locking/spinlock_debug.c:92
--------------------------------------
0xffffffff813e10df
do_raw_spin_lock kernel/locking/spinlock_debug.c:116
--------------------------------------
0xffffffff855b3ca9
_raw_spin_lock kernel/locking/spinlock.c:152
--------------------------------------
0xffffffff855aded3
__mutex_unlock_slowpath kernel/locking/mutex.c:1262
--------------------------------------
0xffffffff813c9a80
debug_mutex_unlock kernel/locking/mutex-debug.c:73
--------------------------------------
0xffffffff813c9a94
debug_mutex_unlock kernel/locking/mutex-debug.c:74
--------------------------------------
0xffffffff813c9af6
debug_mutex_unlock kernel/locking/mutex-debug.c:78
--------------------------------------
0xffffffff855adedb
__mutex_unlock_slowpath kernel/locking/mutex.c:1263
--------------------------------------
0xffffffff855adef0
__mutex_unlock_slowpath kernel/locking/mutex.c:1266
--------------------------------------
0xffffffff855adef8
__mutex_unlock_slowpath kernel/locking/mutex.c:1266
--------------------------------------
0xffffffff855adf08
__mutex_unlock_slowpath kernel/locking/mutex.c:1269
--------------------------------------
0xffffffff813c9640
debug_mutex_wake_waiter kernel/locking/mutex-debug.c:38
--------------------------------------
0xffffffff813c965b
debug_mutex_wake_waiter kernel/locking/mutex-debug.c:39
--------------------------------------
0xffffffff813c9676
debug_mutex_wake_waiter kernel/locking/mutex-debug.c:40
--------------------------------------
0xffffffff813c9682
debug_mutex_wake_waiter kernel/locking/mutex-debug.c:40
--------------------------------------
0xffffffff813c968b
debug_mutex_wake_waiter kernel/locking/mutex-debug.c:40
--------------------------------------
0xffffffff813c96a0
debug_mutex_wake_waiter kernel/locking/mutex-debug.c:41
--------------------------------------
0xffffffff813c96ac
debug_mutex_wake_waiter kernel/locking/mutex-debug.c:41
--------------------------------------
0xffffffff813c96b5
debug_mutex_wake_waiter kernel/locking/mutex-debug.c:41
--------------------------------------
0xffffffff813c96be
debug_mutex_wake_waiter kernel/locking/mutex-debug.c:41
--------------------------------------
0xffffffff813c96c4
debug_mutex_wake_waiter kernel/locking/mutex-debug.c:42
--------------------------------------
0xffffffff813c96d0
debug_mutex_wake_waiter kernel/locking/mutex-debug.c:42
--------------------------------------
0xffffffff813c96ed
debug_mutex_wake_waiter kernel/locking/mutex-debug.c:43
--------------------------------------
0xffffffff855adf1a
__mutex_unlock_slowpath kernel/locking/mutex.c:1271
--------------------------------------
0xffffffff81378f10
wake_q_add kernel/sched/core.c:551
--------------------------------------
0xffffffff81378f4b
wake_q_add kernel/sched/core.c:533
--------------------------------------
0xffffffff81378f54
wake_q_add kernel/sched/core.c:533
--------------------------------------
0xffffffff81378f60
wake_q_add kernel/sched/core.c:533
--------------------------------------
0xffffffff81378f90
wake_q_add kernel/sched/core.c:554
--------------------------------------
0xffffffff855adf26
__mutex_unlock_slowpath kernel/locking/mutex.c:1246
--------------------------------------
0xffffffff855b3df0
_raw_spin_unlock kernel/locking/spinlock.c:182
--------------------------------------
0xffffffff813cf060
lock_release kernel/locking/lockdep.c:5013
--------------------------------------
0xffffffff813e14c0
do_raw_spin_unlock kernel/locking/spinlock_debug.c:136
--------------------------------------
0xffffffff813e14e0
do_raw_spin_unlock kernel/locking/spinlock_debug.c:97
--------------------------------------
0xffffffff813e1504
do_raw_spin_unlock kernel/locking/spinlock_debug.c:98
--------------------------------------
0xffffffff813e150f
do_raw_spin_unlock kernel/locking/spinlock_debug.c:99
--------------------------------------
0xffffffff813e1530
do_raw_spin_unlock kernel/locking/spinlock_debug.c:100
--------------------------------------
0xffffffff813e153d
do_raw_spin_unlock kernel/locking/spinlock_debug.c:100
--------------------------------------
0xffffffff813e1551
do_raw_spin_unlock kernel/locking/spinlock_debug.c:102
--------------------------------------
0xffffffff813e1559
do_raw_spin_unlock kernel/locking/spinlock_debug.c:102
--------------------------------------
0xffffffff813e1568
do_raw_spin_unlock kernel/locking/spinlock_debug.c:103
--------------------------------------
0xffffffff813e1592
do_raw_spin_unlock kernel/locking/spinlock_debug.c:140
--------------------------------------
0xffffffff8137b1e0
preempt_count_sub kernel/sched/core.c:4206
--------------------------------------
0xffffffff8137b1f3
preempt_count_sub kernel/sched/core.c:4211
--------------------------------------
0xffffffff8137b20f
preempt_count_sub kernel/sched/core.c:4216
--------------------------------------
0xffffffff8137b217
preempt_count_sub kernel/sched/core.c:4216
--------------------------------------
0xffffffff855b3e22
_raw_spin_unlock kernel/locking/spinlock.c:184
--------------------------------------
0xffffffff81379060
wake_up_q kernel/sched/core.c:580
--------------------------------------
0xffffffff81379073
wake_up_q kernel/sched/core.c:581
--------------------------------------
0xffffffff81379088
wake_up_q kernel/sched/core.c:583
--------------------------------------
0xffffffff8137908e
wake_up_q kernel/sched/core.c:587
--------------------------------------
0xffffffff8137909a
wake_up_q kernel/sched/core.c:587
--------------------------------------
0xffffffff813790a5
wake_up_q kernel/sched/core.c:589
--------------------------------------
0xffffffff813790b1
wake_up_q kernel/sched/core.c:590
--------------------------------------
0xffffffff8137bb80
try_to_wake_up kernel/sched/core.c:2826
--------------------------------------
0xffffffff8137b110
preempt_count_add kernel/sched/core.c:4174
--------------------------------------
0xffffffff8137b12c
preempt_count_add kernel/sched/core.c:4187
--------------------------------------
0xffffffff813dd110
in_lock_functions kernel/locking/spinlock.c:392
--------------------------------------
0xffffffff8137b19a
preempt_count_add kernel/sched/core.c:4167
--------------------------------------
0xffffffff8137bbc2
try_to_wake_up kernel/sched/core.c:2859
--------------------------------------
0xffffffff855b3cb0
_raw_spin_lock_irqsave kernel/locking/spinlock.c:158
--------------------------------------
0xffffffff811a38a0
native_save_fl arch/x86/kernel/irqflags.S:11
--------------------------------------
0xffffffff8152afd0
trace_hardirqs_off kernel/trace/trace_preemptirq.c:75
--------------------------------------
0xffffffff8152afdc
trace_hardirqs_off kernel/trace/trace_preemptirq.c:76
--------------------------------------
0xffffffff85596ac0
lockdep_hardirqs_off kernel/locking/lockdep.c:3770
--------------------------------------
0xffffffff85596b43
lockdep_hardirqs_off kernel/locking/lockdep.c:3805
--------------------------------------
0xffffffff8152afe8
trace_hardirqs_off kernel/trace/trace_preemptirq.c:78
--------------------------------------
0xffffffff8152aff8
trace_hardirqs_off kernel/trace/trace_preemptirq.c:78
--------------------------------------
0xffffffff8152b003
trace_hardirqs_off kernel/trace/trace_preemptirq.c:79
--------------------------------------
0xffffffff8152b024
trace_hardirqs_off kernel/trace/trace_preemptirq.c:81
--------------------------------------
0xffffffff8152b033
trace_hardirqs_off kernel/trace/trace_preemptirq.c:80
--------------------------------------
0xffffffff8152b038
trace_hardirqs_off kernel/trace/trace_preemptirq.c:80
--------------------------------------
0xffffffff8152b048
trace_hardirqs_off kernel/trace/trace_preemptirq.c:84
--------------------------------------
0xffffffff8137b110
preempt_count_add kernel/sched/core.c:4174
--------------------------------------
0xffffffff8137b12c
preempt_count_add kernel/sched/core.c:4187
--------------------------------------
0xffffffff8137b1a1
preempt_count_add kernel/sched/core.c:4191
--------------------------------------
0xffffffff813cd4d0
lock_acquire kernel/locking/lockdep.c:4977
--------------------------------------
0xffffffff813e0fe0
do_raw_spin_lock kernel/locking/spinlock_debug.c:111
--------------------------------------
0xffffffff813e100d
do_raw_spin_lock kernel/locking/spinlock_debug.c:83
--------------------------------------
0xffffffff813e101c
do_raw_spin_lock kernel/locking/spinlock_debug.c:84
--------------------------------------
0xffffffff813e1028
do_raw_spin_lock kernel/locking/spinlock_debug.c:84
--------------------------------------
0xffffffff813e1042
do_raw_spin_lock kernel/locking/spinlock_debug.c:85
--------------------------------------
0xffffffff813e104e
do_raw_spin_lock kernel/locking/spinlock_debug.c:85
--------------------------------------
0xffffffff813e1061
do_raw_spin_lock kernel/locking/spinlock_debug.c:85
--------------------------------------
0xffffffff813e10aa
do_raw_spin_lock kernel/locking/spinlock_debug.c:91
--------------------------------------
0xffffffff813e10b9
do_raw_spin_lock kernel/locking/spinlock_debug.c:91
--------------------------------------
0xffffffff813e10c5
do_raw_spin_lock kernel/locking/spinlock_debug.c:92
--------------------------------------
0xffffffff813e10df
do_raw_spin_lock kernel/locking/spinlock_debug.c:116
--------------------------------------
0xffffffff855b3d2d
_raw_spin_lock_irqsave kernel/locking/spinlock.c:159
--------------------------------------
0xffffffff8137bbd1
try_to_wake_up kernel/sched/core.c:2859
--------------------------------------
0xffffffff8137bbe1
try_to_wake_up kernel/sched/core.c:2861
--------------------------------------
0xffffffff8137bbed
try_to_wake_up kernel/sched/core.c:2861
--------------------------------------
0xffffffff85596e30
debug_lockdep_rcu_enabled kernel/rcu/update.c:290
--------------------------------------
0xffffffff8137bbf9
try_to_wake_up kernel/sched/core.c:2892
--------------------------------------
0xffffffff8137bc05
try_to_wake_up kernel/sched/core.c:2892
--------------------------------------
0xffffffff8137bcfa
try_to_wake_up kernel/sched/core.c:2895
--------------------------------------
0xffffffff8137bd09
try_to_wake_up kernel/sched/core.c:2895
--------------------------------------
0xffffffff8137bd97
try_to_wake_up kernel/sched/core.c:2924
--------------------------------------
0xffffffff8137bda0
try_to_wake_up kernel/sched/core.c:2932
--------------------------------------
0xffffffff8137bdb4
try_to_wake_up kernel/sched/core.c:2953
--------------------------------------
0xffffffff8137bde8
try_to_wake_up kernel/sched/core.c:2953
--------------------------------------
0xffffffff8137bdf8
try_to_wake_up kernel/sched/core.c:2966
--------------------------------------
0xffffffff8137be01
try_to_wake_up kernel/sched/core.c:2968
--------------------------------------
0xffffffff8137be0a
try_to_wake_up kernel/sched/core.c:2968
--------------------------------------
0xffffffff8137be1a
try_to_wake_up kernel/sched/core.c:2357
--------------------------------------
0xffffffff8137be3c
try_to_wake_up kernel/sched/core.c:2359
--------------------------------------
0xffffffff8137be4b
try_to_wake_up kernel/sched/core.c:2359
--------------------------------------
0xffffffff8137be59
try_to_wake_up kernel/sched/core.c:2360
--------------------------------------
0xffffffff8137be62
try_to_wake_up kernel/sched/core.c:2360
--------------------------------------
0xffffffff8137be6f
try_to_wake_up kernel/sched/core.c:2360(Triggered a new impact which we identify: Control flow hijacking)
--------------------------------------
Total 281 basic block