public inbox for [email protected]
 help / color / mirror / Atom feed
* [PATCH 0/2] double poll fixes
@ 2021-07-20  9:50 Pavel Begunkov
  2021-07-20  9:50 ` [PATCH 1/2] io_uring: explicitly count entries for poll reqs Pavel Begunkov
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Pavel Begunkov @ 2021-07-20  9:50 UTC (permalink / raw)
  To: Jens Axboe, io-uring; +Cc: asml.silence

2/2 is about recent syzbot report, 1/2 is just a small additional fix

Pavel Begunkov (2):
  io_uring: explicitly count entries for poll reqs
  io_uring: remove double poll entry on arm failure

 fs/io_uring.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

-- 
2.32.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] io_uring: explicitly count entries for poll reqs
  2021-07-20  9:50 [PATCH 0/2] double poll fixes Pavel Begunkov
@ 2021-07-20  9:50 ` Pavel Begunkov
  2021-07-20  9:50 ` [PATCH 2/2] io_uring: remove double poll entry on arm failure Pavel Begunkov
  2021-07-20 13:50 ` [PATCH 0/2] double poll fixes Jens Axboe
  2 siblings, 0 replies; 4+ messages in thread
From: Pavel Begunkov @ 2021-07-20  9:50 UTC (permalink / raw)
  To: Jens Axboe, io-uring; +Cc: asml.silence

If __io_queue_proc() fails to add a second poll entry, e.g. kmalloc()
failed, but it goes on with a third waitqueue, it may succeed and
overwrite the error status. Count the number of poll entries we added,
so we can set pt->error to zero at the beginning and find out when the
mentioned scenario happens.

Cc: [email protected]
Fixes: 18bceab101add ("io_uring: allow POLL_ADD with double poll_wait() users")
Signed-off-by: Pavel Begunkov <[email protected]>
---
 fs/io_uring.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/fs/io_uring.c b/fs/io_uring.c
index 0cac361bf6b8..6668902cf50c 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -4802,6 +4802,7 @@ IO_NETOP_FN(recv);
 struct io_poll_table {
 	struct poll_table_struct pt;
 	struct io_kiocb *req;
+	int nr_entries;
 	int error;
 };
 
@@ -4995,11 +4996,11 @@ static void __io_queue_proc(struct io_poll_iocb *poll, struct io_poll_table *pt,
 	struct io_kiocb *req = pt->req;
 
 	/*
-	 * If poll->head is already set, it's because the file being polled
-	 * uses multiple waitqueues for poll handling (eg one for read, one
-	 * for write). Setup a separate io_poll_iocb if this happens.
+	 * The file being polled uses multiple waitqueues for poll handling
+	 * (e.g. one for read, one for write). Setup a separate io_poll_iocb
+	 * if this happens.
 	 */
-	if (unlikely(poll->head)) {
+	if (unlikely(pt->nr_entries)) {
 		struct io_poll_iocb *poll_one = poll;
 
 		/* already have a 2nd entry, fail a third attempt */
@@ -5027,7 +5028,7 @@ static void __io_queue_proc(struct io_poll_iocb *poll, struct io_poll_table *pt,
 		*poll_ptr = poll;
 	}
 
-	pt->error = 0;
+	pt->nr_entries++;
 	poll->head = head;
 
 	if (poll->events & EPOLLEXCLUSIVE)
@@ -5104,9 +5105,12 @@ static __poll_t __io_arm_poll_handler(struct io_kiocb *req,
 
 	ipt->pt._key = mask;
 	ipt->req = req;
-	ipt->error = -EINVAL;
+	ipt->error = 0;
+	ipt->nr_entries = 0;
 
 	mask = vfs_poll(req->file, &ipt->pt) & poll->events;
+	if (unlikely(!ipt->nr_entries) && !ipt->error)
+		ipt->error = -EINVAL;
 
 	spin_lock_irq(&ctx->completion_lock);
 	if (likely(poll->head)) {
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/2] io_uring: remove double poll entry on arm failure
  2021-07-20  9:50 [PATCH 0/2] double poll fixes Pavel Begunkov
  2021-07-20  9:50 ` [PATCH 1/2] io_uring: explicitly count entries for poll reqs Pavel Begunkov
@ 2021-07-20  9:50 ` Pavel Begunkov
  2021-07-20 13:50 ` [PATCH 0/2] double poll fixes Jens Axboe
  2 siblings, 0 replies; 4+ messages in thread
From: Pavel Begunkov @ 2021-07-20  9:50 UTC (permalink / raw)
  To: Jens Axboe, io-uring; +Cc: asml.silence

__io_queue_proc() can enqueue both poll entries and still fail
afterwards, so the callers trying to cancel it should also try to remove
the second poll entry (if any).

For example, it may leave the request alive referencing a io_uring
context but not accessible for cancellation:

[  282.599913][ T1620] task:iou-sqp-23145   state:D stack:28720 pid:23155 ppid:  8844 flags:0x00004004
[  282.609927][ T1620] Call Trace:
[  282.613711][ T1620]  __schedule+0x93a/0x26f0
[  282.634647][ T1620]  schedule+0xd3/0x270
[  282.638874][ T1620]  io_uring_cancel_generic+0x54d/0x890
[  282.660346][ T1620]  io_sq_thread+0xaac/0x1250
[  282.696394][ T1620]  ret_from_fork+0x1f/0x30

Cc: [email protected]
Fixes: 18bceab101add ("io_uring: allow POLL_ADD with double poll_wait() users")
Reported-and-tested-by: [email protected]
Signed-off-by: Pavel Begunkov <[email protected]>
---
 fs/io_uring.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fs/io_uring.c b/fs/io_uring.c
index 6668902cf50c..6486b54a0f62 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -5113,6 +5113,8 @@ static __poll_t __io_arm_poll_handler(struct io_kiocb *req,
 		ipt->error = -EINVAL;
 
 	spin_lock_irq(&ctx->completion_lock);
+	if (ipt->error)
+		io_poll_remove_double(req);
 	if (likely(poll->head)) {
 		spin_lock(&poll->head->lock);
 		if (unlikely(list_empty(&poll->wait.entry))) {
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 0/2] double poll fixes
  2021-07-20  9:50 [PATCH 0/2] double poll fixes Pavel Begunkov
  2021-07-20  9:50 ` [PATCH 1/2] io_uring: explicitly count entries for poll reqs Pavel Begunkov
  2021-07-20  9:50 ` [PATCH 2/2] io_uring: remove double poll entry on arm failure Pavel Begunkov
@ 2021-07-20 13:50 ` Jens Axboe
  2 siblings, 0 replies; 4+ messages in thread
From: Jens Axboe @ 2021-07-20 13:50 UTC (permalink / raw)
  To: Pavel Begunkov, io-uring

On 7/20/21 3:50 AM, Pavel Begunkov wrote:
> 2/2 is about recent syzbot report, 1/2 is just a small additional fix
> 
> Pavel Begunkov (2):
>   io_uring: explicitly count entries for poll reqs
>   io_uring: remove double poll entry on arm failure
> 
>  fs/io_uring.c | 18 ++++++++++++------
>  1 file changed, 12 insertions(+), 6 deletions(-)

Applied, thanks.

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-07-20 13:54 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-07-20  9:50 [PATCH 0/2] double poll fixes Pavel Begunkov
2021-07-20  9:50 ` [PATCH 1/2] io_uring: explicitly count entries for poll reqs Pavel Begunkov
2021-07-20  9:50 ` [PATCH 2/2] io_uring: remove double poll entry on arm failure Pavel Begunkov
2021-07-20 13:50 ` [PATCH 0/2] double poll fixes Jens Axboe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox