Skip to content

Commit 09ca6c4

Browse files
committed
io-wq: kill hashed waitqueue before manager exits
If we race with shutting down the io-wq context and someone queueing a hashed entry, then we can exit the manager with it armed. If it then triggers after the manager has exited, we can have a use-after-free where io_wqe_hash_wake() attempts to wake a now gone manager process. Move the killing of the hashed write queue into the manager itself, so that we know we've killed it before the task exits. Fixes: e941894 ("io-wq: make buffered file write hashed work map per-ctx") Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent b5b0ecb commit 09ca6c4

1 file changed

Lines changed: 5 additions & 4 deletions

File tree

fs/io-wq.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,11 @@ static int io_wq_manager(void *data)
726726
if (atomic_read(&wq->worker_refs))
727727
wait_for_completion(&wq->worker_done);
728728

729+
spin_lock_irq(&wq->hash->wait.lock);
730+
for_each_node(node)
731+
list_del_init(&wq->wqes[node]->wait.entry);
732+
spin_unlock_irq(&wq->hash->wait.lock);
733+
729734
io_wq_cancel_pending(wq);
730735
complete(&wq->exited);
731736
do_exit(0);
@@ -1051,15 +1056,11 @@ static void io_wq_destroy(struct io_wq *wq)
10511056
set_bit(IO_WQ_BIT_EXIT, &wq->state);
10521057
io_wq_destroy_manager(wq);
10531058

1054-
spin_lock_irq(&wq->hash->wait.lock);
10551059
for_each_node(node) {
10561060
struct io_wqe *wqe = wq->wqes[node];
1057-
1058-
list_del_init(&wqe->wait.entry);
10591061
WARN_ON_ONCE(!wq_list_empty(&wqe->work_list));
10601062
kfree(wqe);
10611063
}
1062-
spin_unlock_irq(&wq->hash->wait.lock);
10631064
io_wq_put_hash(wq->hash);
10641065
kfree(wq->wqes);
10651066
kfree(wq);

0 commit comments

Comments
 (0)