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.

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