io_uring: fix race condition in task_work add and clear
authorJens Axboe <axboe@kernel.dk>
Fri, 26 Feb 2021 21:54:16 +0000 (14:54 -0700)
committerJens Axboe <axboe@kernel.dk>
Mon, 1 Mar 2021 21:56:19 +0000 (14:56 -0700)
commit89f55cf4b7c79e1e3d59aef34c7c8a8b1e0efed9
tree044ef6e7c1f938f47b9e7b46d94135bbbb12b86a
parent2aa3fa29a64027333fd067f5a7839fe8244d58d3
io_uring: fix race condition in task_work add and clear

We clear the bit marking the ctx task_work as active after having run
the queued work, but we really should be clearing it before. Otherwise
we can hit a tiny race ala:

CPU0 CPU1
io_task_work_add() tctx_task_work()
run_work
add_to_list
test_and_set_bit
clear_bit
already set

and CPU0 will return thinking the task_work is queued, while in reality
it's already being run. If we hit the condition after __tctx_task_work()
found no more work, but before we've cleared the bit, then we'll end up
thinking it's queued and will be run. In reality it is queued, but we
didn't queue the ctx task_work to ensure that it gets run.

Fixes: 7cbf1722d5fc ("io_uring: provide FIFO ordering for task_work")
Signed-off-by: Jens Axboe <axboe@kernel.dk>
fs/io_uring.c