From: Pavel Begunkov <[email protected]>
To: Hao Xu <[email protected]>, [email protected]
Cc: Jens Axboe <[email protected]>, [email protected]
Subject: Re: [PATCH 3/5] io_uring: let fast poll support multishot
Date: Fri, 6 May 2022 18:19:42 +0100 [thread overview]
Message-ID: <[email protected]> (raw)
In-Reply-To: <[email protected]>
On 5/6/22 08:01, Hao Xu wrote:
> From: Hao Xu <[email protected]>
>
> For operations like accept, multishot is a useful feature, since we can
> reduce a number of accept sqe. Let's integrate it to fast poll, it may
> be good for other operations in the future.
>
> Signed-off-by: Hao Xu <[email protected]>
> ---
> fs/io_uring.c | 41 ++++++++++++++++++++++++++---------------
> 1 file changed, 26 insertions(+), 15 deletions(-)
>
> diff --git a/fs/io_uring.c b/fs/io_uring.c
> index 8ebb1a794e36..d33777575faf 100644
> --- a/fs/io_uring.c
> +++ b/fs/io_uring.c
> @@ -5952,7 +5952,7 @@ static void io_poll_remove_entries(struct io_kiocb *req)
> * either spurious wakeup or multishot CQE is served. 0 when it's done with
> * the request, then the mask is stored in req->cqe.res.
> */
> -static int io_poll_check_events(struct io_kiocb *req, bool locked)
> +static int io_poll_check_events(struct io_kiocb *req, bool *locked)
> {
> struct io_ring_ctx *ctx = req->ctx;
> int v;
> @@ -5981,17 +5981,26 @@ static int io_poll_check_events(struct io_kiocb *req, bool locked)
>
> /* multishot, just fill an CQE and proceed */
> if (req->cqe.res && !(req->apoll_events & EPOLLONESHOT)) {
> - __poll_t mask = mangle_poll(req->cqe.res & req->apoll_events);
> - bool filled;
> -
> - spin_lock(&ctx->completion_lock);
> - filled = io_fill_cqe_aux(ctx, req->cqe.user_data, mask,
> - IORING_CQE_F_MORE);
> - io_commit_cqring(ctx);
> - spin_unlock(&ctx->completion_lock);
> - if (unlikely(!filled))
> - return -ECANCELED;
> - io_cqring_ev_posted(ctx);
> + if (req->flags & REQ_F_APOLL_MULTISHOT) {
> + io_tw_lock(req->ctx, locked);
> + if (likely(!(req->task->flags & PF_EXITING)))
> + io_queue_sqe(req);
That looks dangerous, io_queue_sqe() usually takes the request ownership
and doesn't expect that someone, i.e. io_poll_check_events(), may still be
actively using it.
E.g. io_accept() fails on fd < 0, return an error,
io_queue_sqe() -> io_queue_async() -> io_req_complete_failed()
kills it. Then io_poll_check_events() and polling in general
carry on using the freed request => UAF. Didn't look at it
too carefully, but there might other similar cases.
> + else
> + return -EFAULT;
> + } else {
> + __poll_t mask = mangle_poll(req->cqe.res &
> + req->apoll_events);
> + bool filled;
> +
> + spin_lock(&ctx->completion_lock);
> + filled = io_fill_cqe_aux(ctx, req->cqe.user_data,
> + mask, IORING_CQE_F_MORE);
> + io_commit_cqring(ctx);
> + spin_unlock(&ctx->completion_lock);
> + if (unlikely(!filled))
> + return -ECANCELED;
> + io_cqring_ev_posted(ctx);
> + }
> } else if (req->cqe.res) {
> return 0;
> }
> @@ -6010,7 +6019,7 @@ static void io_poll_task_func(struct io_kiocb *req, bool *locked)
> struct io_ring_ctx *ctx = req->ctx;
> int ret;
>
> - ret = io_poll_check_events(req, *locked);
> + ret = io_poll_check_events(req, locked);
> if (ret > 0)
> return;
>
> @@ -6035,7 +6044,7 @@ static void io_apoll_task_func(struct io_kiocb *req, bool *locked)
> struct io_ring_ctx *ctx = req->ctx;
> int ret;
>
> - ret = io_poll_check_events(req, *locked);
> + ret = io_poll_check_events(req, locked);
> if (ret > 0)
> return;
>
> @@ -6275,7 +6284,7 @@ static int io_arm_poll_handler(struct io_kiocb *req, unsigned issue_flags)
> struct io_ring_ctx *ctx = req->ctx;
> struct async_poll *apoll;
> struct io_poll_table ipt;
> - __poll_t mask = EPOLLONESHOT | POLLERR | POLLPRI;
> + __poll_t mask = POLLERR | POLLPRI;
> int ret;
>
> if (!def->pollin && !def->pollout)
> @@ -6284,6 +6293,8 @@ static int io_arm_poll_handler(struct io_kiocb *req, unsigned issue_flags)
> return IO_APOLL_ABORTED;
> if ((req->flags & (REQ_F_POLLED|REQ_F_PARTIAL_IO)) == REQ_F_POLLED)
> return IO_APOLL_ABORTED;
> + if (!(req->flags & REQ_F_APOLL_MULTISHOT))
> + mask |= EPOLLONESHOT;
>
> if (def->pollin) {
> mask |= POLLIN | POLLRDNORM;
--
Pavel Begunkov
next prev parent reply other threads:[~2022-05-06 17:20 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-05-06 7:00 [PATCH v2 0/5] fast poll multishot mode Hao Xu
2022-05-06 7:00 ` [PATCH 1/5] io_uring: add IORING_ACCEPT_MULTISHOT for accept Hao Xu
2022-05-06 14:32 ` Jens Axboe
2022-05-07 4:05 ` Hao Xu
2022-05-06 7:00 ` [PATCH 2/5] io_uring: add REQ_F_APOLL_MULTISHOT for requests Hao Xu
2022-05-06 7:01 ` [PATCH 3/5] io_uring: let fast poll support multishot Hao Xu
2022-05-06 17:19 ` Pavel Begunkov [this message]
2022-05-06 22:02 ` Jens Axboe
2022-05-07 6:32 ` Hao Xu
2022-05-07 9:26 ` Pavel Begunkov
2022-05-07 7:08 ` Hao Xu
2022-05-07 9:47 ` Pavel Begunkov
2022-05-07 11:06 ` Hao Xu
2022-05-06 18:02 ` kernel test robot
2022-05-06 7:01 ` [PATCH 4/5] io_uring: add a helper for poll clean Hao Xu
2022-05-06 11:04 ` kernel test robot
2022-05-06 12:47 ` kernel test robot
2022-05-06 14:36 ` Jens Axboe
2022-05-07 6:37 ` Hao Xu
2022-05-06 16:22 ` Pavel Begunkov
2022-05-07 6:43 ` Hao Xu
2022-05-07 9:29 ` Pavel Begunkov
2022-05-06 7:01 ` [PATCH 5/5] io_uring: implement multishot mode for accept Hao Xu
2022-05-06 14:42 ` Jens Axboe
2022-05-07 9:13 ` Hao Xu
2022-05-06 20:50 ` Jens Axboe
2022-05-06 21:29 ` Jens Axboe
2022-05-06 7:36 ` [PATCH v2 0/5] fast poll multishot mode Hao Xu
2022-05-06 14:18 ` Jens Axboe
2022-05-06 16:01 ` Pavel Begunkov
2022-05-06 16:03 ` Jens Axboe
2022-05-06 22:23 ` Jens Axboe
2022-05-06 23:26 ` Jens Axboe
2022-05-07 2:33 ` Jens Axboe
2022-05-07 3:08 ` Jens Axboe
2022-05-07 16:01 ` Hao Xu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
[email protected] \
[email protected] \
[email protected] \
[email protected] \
[email protected] \
[email protected] \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox