Skip to content

Commit 3743c17

Browse files
Zqiang1211axboe
authored andcommitted
io-wq: Fix UAF when wakeup wqe in hash waitqueue
BUG: KASAN: use-after-free in __wake_up_common+0x637/0x650 Read of size 8 at addr ffff8880304250d8 by task iou-wrk-28796/28802 Call Trace: __dump_stack [inline] dump_stack+0x141/0x1d7 print_address_description.constprop.0.cold+0x5b/0x2c6 __kasan_report [inline] kasan_report.cold+0x7c/0xd8 __wake_up_common+0x637/0x650 __wake_up_common_lock+0xd0/0x130 io_worker_handle_work+0x9dd/0x1790 io_wqe_worker+0xb2a/0xd40 ret_from_fork+0x1f/0x30 Allocated by task 28798: kzalloc_node [inline] io_wq_create+0x3c4/0xdd0 io_init_wq_offload [inline] io_uring_alloc_task_context+0x1bf/0x6b0 __io_uring_add_task_file+0x29a/0x3c0 io_uring_add_task_file [inline] io_uring_install_fd [inline] io_uring_create [inline] io_uring_setup+0x209a/0x2bd0 do_syscall_64+0x3a/0xb0 entry_SYSCALL_64_after_hwframe+0x44/0xae Freed by task 28798: kfree+0x106/0x2c0 io_wq_destroy+0x182/0x380 io_wq_put [inline] io_wq_put_and_exit+0x7a/0xa0 io_uring_clean_tctx [inline] __io_uring_cancel+0x428/0x530 io_uring_files_cancel do_exit+0x299/0x2a60 do_group_exit+0x125/0x310 get_signal+0x47f/0x2150 arch_do_signal_or_restart+0x2a8/0x1eb0 handle_signal_work[inline] exit_to_user_mode_loop [inline] exit_to_user_mode_prepare+0x171/0x280 __syscall_exit_to_user_mode_work [inline] syscall_exit_to_user_mode+0x19/0x60 do_syscall_64+0x47/0xb0 entry_SYSCALL_64_after_hwframe There are the following scenarios, hash waitqueue is shared by io-wq1 and io-wq2. (note: wqe is worker) io-wq1:worker2 | locks bit1 io-wq2:worker1 | waits bit1 io-wq1:worker3 | waits bit1 io-wq1:worker2 | completes all wqe bit1 work items io-wq1:worker2 | drop bit1, exit io-wq2:worker1 | locks bit1 io-wq1:worker3 | can not locks bit1, waits bit1 and exit io-wq1 | exit and free io-wq1 io-wq2:worker1 | drops bit1 io-wq1:worker3 | be waked up, even though wqe is freed After all iou-wrk belonging to io-wq1 have exited, remove wqe form hash waitqueue, it is guaranteed that there will be no more wqe belonging to io-wq1 in the hash waitqueue. Reported-by: [email protected] Signed-off-by: Zqiang <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 17a9105 commit 3743c17

File tree

1 file changed

+6
-3
lines changed

1 file changed

+6
-3
lines changed

fs/io-wq.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,13 +1006,16 @@ static void io_wq_exit_workers(struct io_wq *wq)
10061006
struct io_wqe *wqe = wq->wqes[node];
10071007

10081008
io_wq_for_each_worker(wqe, io_wq_worker_wake, NULL);
1009-
spin_lock_irq(&wq->hash->wait.lock);
1010-
list_del_init(&wq->wqes[node]->wait.entry);
1011-
spin_unlock_irq(&wq->hash->wait.lock);
10121009
}
10131010
rcu_read_unlock();
10141011
io_worker_ref_put(wq);
10151012
wait_for_completion(&wq->worker_done);
1013+
1014+
for_each_node(node) {
1015+
spin_lock_irq(&wq->hash->wait.lock);
1016+
list_del_init(&wq->wqes[node]->wait.entry);
1017+
spin_unlock_irq(&wq->hash->wait.lock);
1018+
}
10161019
put_task_struct(wq->task);
10171020
wq->task = NULL;
10181021
}

0 commit comments

Comments
 (0)