diff options
author | Jens Axboe <axboe@kernel.dk> | 2023-01-10 00:46:10 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2023-01-18 13:58:10 +0300 |
commit | 4ad6c063541665c407d17e1faf2fe4f04e947dcc (patch) | |
tree | e10173f672b74d2e9805c0772737d801089ea91f | |
parent | 78c8b66a697abed34c34a37eaa7fc3865b4f3ec4 (diff) | |
download | linux-4ad6c063541665c407d17e1faf2fe4f04e947dcc.tar.xz |
io_uring/poll: add hash if ready poll request can't complete inline
commit febb985c06cb6f5fac63598c0bffd4fd823d110d upstream.
If we don't, then we may lose access to it completely, leading to a
request leak. This will eventually stall the ring exit process as
well.
Cc: stable@vger.kernel.org
Fixes: 49f1c68e048f ("io_uring: optimise submission side poll_refs")
Reported-and-tested-by: syzbot+6c95df01470a47fc3af4@syzkaller.appspotmail.com
Link: https://lore.kernel.org/io-uring/0000000000009f829805f1ce87b2@google.com/
Suggested-by: Pavel Begunkov <asml.silence@gmail.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | io_uring/poll.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/io_uring/poll.c b/io_uring/poll.c index fded1445a803..df42fd8a6ab0 100644 --- a/io_uring/poll.c +++ b/io_uring/poll.c @@ -549,6 +549,14 @@ static bool io_poll_can_finish_inline(struct io_kiocb *req, return pt->owning || io_poll_get_ownership(req); } +static void io_poll_add_hash(struct io_kiocb *req) +{ + if (req->flags & REQ_F_HASH_LOCKED) + io_poll_req_insert_locked(req); + else + io_poll_req_insert(req); +} + /* * Returns 0 when it's handed over for polling. The caller owns the requests if * it returns non-zero, but otherwise should not touch it. Negative values @@ -607,18 +615,17 @@ static int __io_arm_poll_handler(struct io_kiocb *req, if (mask && ((poll->events & (EPOLLET|EPOLLONESHOT)) == (EPOLLET|EPOLLONESHOT))) { - if (!io_poll_can_finish_inline(req, ipt)) + if (!io_poll_can_finish_inline(req, ipt)) { + io_poll_add_hash(req); return 0; + } io_poll_remove_entries(req); ipt->result_mask = mask; /* no one else has access to the req, forget about the ref */ return 1; } - if (req->flags & REQ_F_HASH_LOCKED) - io_poll_req_insert_locked(req); - else - io_poll_req_insert(req); + io_poll_add_hash(req); if (mask && (poll->events & EPOLLET) && io_poll_can_finish_inline(req, ipt)) { |