io_uring/poll: add hash if ready poll request can't complete inline
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>
This commit is contained in:
parent
e6db6f9398
commit
febb985c06
@ -533,6 +533,14 @@ static bool io_poll_can_finish_inline(struct io_kiocb *req,
|
|||||||
return pt->owning || io_poll_get_ownership(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
|
* 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
|
* it returns non-zero, but otherwise should not touch it. Negative values
|
||||||
@ -591,18 +599,17 @@ static int __io_arm_poll_handler(struct io_kiocb *req,
|
|||||||
|
|
||||||
if (mask &&
|
if (mask &&
|
||||||
((poll->events & (EPOLLET|EPOLLONESHOT)) == (EPOLLET|EPOLLONESHOT))) {
|
((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;
|
return 0;
|
||||||
|
}
|
||||||
io_poll_remove_entries(req);
|
io_poll_remove_entries(req);
|
||||||
ipt->result_mask = mask;
|
ipt->result_mask = mask;
|
||||||
/* no one else has access to the req, forget about the ref */
|
/* no one else has access to the req, forget about the ref */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->flags & REQ_F_HASH_LOCKED)
|
io_poll_add_hash(req);
|
||||||
io_poll_req_insert_locked(req);
|
|
||||||
else
|
|
||||||
io_poll_req_insert(req);
|
|
||||||
|
|
||||||
if (mask && (poll->events & EPOLLET) &&
|
if (mask && (poll->events & EPOLLET) &&
|
||||||
io_poll_can_finish_inline(req, ipt)) {
|
io_poll_can_finish_inline(req, ipt)) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user