]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
io_uring: don't set COMP_LOCKED if won't put
authorPavel Begunkov <asml.silence@gmail.com>
Tue, 13 Oct 2020 08:43:56 +0000 (09:43 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 5 Nov 2020 10:51:16 +0000 (11:51 +0100)
[ Upstream commit 368c5481ae7c6a9719c40984faea35480d9f4872 ]

__io_kill_linked_timeout() sets REQ_F_COMP_LOCKED for a linked timeout
even if it can't cancel it, e.g. it's already running. It not only races
with io_link_timeout_fn() for ->flags field, but also leaves the flag
set and so io_link_timeout_fn() may find it and decide that it holds the
lock. Hopefully, the second problem is potential.

Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/io_uring.c

index 59ab8c5c2aaaa983e5576b4f5273165d1c1e8c5d..50a7a99dad4cac6babb34bc596e3468e85d6868a 100644 (file)
@@ -1650,6 +1650,7 @@ static bool io_link_cancel_timeout(struct io_kiocb *req)
 
        ret = hrtimer_try_to_cancel(&req->io->timeout.timer);
        if (ret != -1) {
+               req->flags |= REQ_F_COMP_LOCKED;
                io_cqring_fill_event(req, -ECANCELED);
                io_commit_cqring(ctx);
                req->flags &= ~REQ_F_LINK_HEAD;
@@ -1672,7 +1673,6 @@ static bool __io_kill_linked_timeout(struct io_kiocb *req)
                return false;
 
        list_del_init(&link->link_list);
-       link->flags |= REQ_F_COMP_LOCKED;
        wake_ev = io_link_cancel_timeout(link);
        req->flags &= ~REQ_F_LINK_TIMEOUT;
        return wake_ev;