1 |
From febb985c06cb6f5fac63598c0bffd4fd823d110d Mon Sep 17 00:00:00 2001 |
2 |
From: Jens Axboe <axboe@kernel.dk> |
3 |
Date: Mon, 9 Jan 2023 14:46:10 -0700 |
4 |
Subject: io_uring/poll: add hash if ready poll request can't complete inline |
5 |
|
6 |
From: Jens Axboe <axboe@kernel.dk> |
7 |
|
8 |
commit febb985c06cb6f5fac63598c0bffd4fd823d110d upstream. |
9 |
|
10 |
If we don't, then we may lose access to it completely, leading to a |
11 |
request leak. This will eventually stall the ring exit process as |
12 |
well. |
13 |
|
14 |
Cc: stable@vger.kernel.org |
15 |
Fixes: 49f1c68e048f ("io_uring: optimise submission side poll_refs") |
16 |
Reported-and-tested-by: syzbot+6c95df01470a47fc3af4@syzkaller.appspotmail.com |
17 |
Link: https://lore.kernel.org/io-uring/0000000000009f829805f1ce87b2@google.com/ |
18 |
Suggested-by: Pavel Begunkov <asml.silence@gmail.com> |
19 |
Signed-off-by: Jens Axboe <axboe@kernel.dk> |
20 |
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
21 |
--- |
22 |
io_uring/poll.c | 17 ++++++++++++----- |
23 |
1 file changed, 12 insertions(+), 5 deletions(-) |
24 |
|
25 |
--- a/io_uring/poll.c |
26 |
+++ b/io_uring/poll.c |
27 |
@@ -549,6 +549,14 @@ static bool io_poll_can_finish_inline(st |
28 |
return pt->owning || io_poll_get_ownership(req); |
29 |
} |
30 |
|
31 |
+static void io_poll_add_hash(struct io_kiocb *req) |
32 |
+{ |
33 |
+ if (req->flags & REQ_F_HASH_LOCKED) |
34 |
+ io_poll_req_insert_locked(req); |
35 |
+ else |
36 |
+ io_poll_req_insert(req); |
37 |
+} |
38 |
+ |
39 |
/* |
40 |
* Returns 0 when it's handed over for polling. The caller owns the requests if |
41 |
* it returns non-zero, but otherwise should not touch it. Negative values |
42 |
@@ -607,18 +615,17 @@ static int __io_arm_poll_handler(struct |
43 |
|
44 |
if (mask && |
45 |
((poll->events & (EPOLLET|EPOLLONESHOT)) == (EPOLLET|EPOLLONESHOT))) { |
46 |
- if (!io_poll_can_finish_inline(req, ipt)) |
47 |
+ if (!io_poll_can_finish_inline(req, ipt)) { |
48 |
+ io_poll_add_hash(req); |
49 |
return 0; |
50 |
+ } |
51 |
io_poll_remove_entries(req); |
52 |
ipt->result_mask = mask; |
53 |
/* no one else has access to the req, forget about the ref */ |
54 |
return 1; |
55 |
} |
56 |
|
57 |
- if (req->flags & REQ_F_HASH_LOCKED) |
58 |
- io_poll_req_insert_locked(req); |
59 |
- else |
60 |
- io_poll_req_insert(req); |
61 |
+ io_poll_add_hash(req); |
62 |
|
63 |
if (mask && (poll->events & EPOLLET) && |
64 |
io_poll_can_finish_inline(req, ipt)) { |