UPSTREAM: io_uring: don't drop completion lock before timer is fully initialized

No upstream commit exists for this patch.

If we drop the lock right after adding it to the timeout list, then
someone attempting to kill timeouts will find it in an indeterminate
state. That means that cancelation could attempt to cancel and remove
a timeout, and then io_timeout() proceeds to init and add the timer
afterwards.

Ensure the timeout request is fully setup before we drop the
completion lock, which guards cancelation as well.

Bug: 278721720
Reported-and-tested-by: Lee Jones <lee@kernel.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
(cherry picked from commit 6de3014d4b)
Signed-off-by: Lee Jones <joneslee@google.com>
Change-Id: I6247b62e07825a0f06c7997d767dfc26fc4126e3
This commit is contained in:
Jens Axboe 2023-05-23 08:24:31 -06:00 committed by Treehugger Robot
parent ce6a504d69
commit 87ed28db7d

View file

@ -2076,12 +2076,12 @@ static int io_timeout(struct io_kiocb *req, const struct io_uring_sqe *sqe)
req->sequence -= span;
add:
list_add(&req->list, entry);
spin_unlock_irq(&ctx->completion_lock);
hrtimer_init(&req->timeout.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
req->timeout.timer.function = io_timeout_fn;
hrtimer_start(&req->timeout.timer, timespec64_to_ktime(ts),
HRTIMER_MODE_REL);
spin_unlock_irq(&ctx->completion_lock);
return 0;
}