]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
io_uring: fix multishot recv request leaks
authorPavel Begunkov <asml.silence@gmail.com>
Thu, 17 Nov 2022 18:40:17 +0000 (18:40 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 26 Nov 2022 08:27:49 +0000 (09:27 +0100)
commit 100d6b17c06ee4c2b42fdddf0fe4ab77c86eb77e upstream.

Having REQ_F_POLLED set doesn't guarantee that the request is
executed as a multishot from the polling path. Fortunately for us, if
the code thinks it's multishot issue when it's not, it can only ask to
skip completion so leaking the request. Use issue_flags to mark
multipoll issues.

Cc: stable@vger.kernel.org
Fixes: 1300ebb20286b ("io_uring: multishot recv")
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Link: https://lore.kernel.org/r/37762040ba9c52b81b92a2f5ebfd4ee484088951.1668710222.git.asml.silence@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
io_uring/net.c

index 1ebcff53606dbfc6516fe17237011a5f839c5f06..8205cfecd647cb12f8cd5b00e411c9e2dfc40435 100644 (file)
@@ -66,8 +66,6 @@ struct io_sr_msg {
        struct io_kiocb                 *notif;
 };
 
-#define IO_APOLL_MULTI_POLLED (REQ_F_APOLL_MULTISHOT | REQ_F_POLLED)
-
 int io_shutdown_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
        struct io_shutdown *shutdown = io_kiocb_to_cmd(req, struct io_shutdown);
@@ -558,7 +556,8 @@ static inline void io_recv_prep_retry(struct io_kiocb *req)
  * again (for multishot).
  */
 static inline bool io_recv_finish(struct io_kiocb *req, int *ret,
-                                 unsigned int cflags, bool mshot_finished)
+                                 unsigned int cflags, bool mshot_finished,
+                                 unsigned issue_flags)
 {
        if (!(req->flags & REQ_F_APOLL_MULTISHOT)) {
                io_req_set_res(req, *ret, cflags);
@@ -581,7 +580,7 @@ static inline bool io_recv_finish(struct io_kiocb *req, int *ret,
 
        io_req_set_res(req, *ret, cflags);
 
-       if (req->flags & REQ_F_POLLED)
+       if (issue_flags & IO_URING_F_MULTISHOT)
                *ret = IOU_STOP_MULTISHOT;
        else
                *ret = IOU_OK;
@@ -740,8 +739,7 @@ retry_multishot:
        if (ret < min_ret) {
                if (ret == -EAGAIN && force_nonblock) {
                        ret = io_setup_async_msg(req, kmsg, issue_flags);
-                       if (ret == -EAGAIN && (req->flags & IO_APOLL_MULTI_POLLED) ==
-                                              IO_APOLL_MULTI_POLLED) {
+                       if (ret == -EAGAIN && (issue_flags & IO_URING_F_MULTISHOT)) {
                                io_kbuf_recycle(req, issue_flags);
                                return IOU_ISSUE_SKIP_COMPLETE;
                        }
@@ -770,7 +768,7 @@ retry_multishot:
        if (kmsg->msg.msg_inq)
                cflags |= IORING_CQE_F_SOCK_NONEMPTY;
 
-       if (!io_recv_finish(req, &ret, cflags, mshot_finished))
+       if (!io_recv_finish(req, &ret, cflags, mshot_finished, issue_flags))
                goto retry_multishot;
 
        if (mshot_finished) {
@@ -836,7 +834,7 @@ retry_multishot:
        ret = sock_recvmsg(sock, &msg, flags);
        if (ret < min_ret) {
                if (ret == -EAGAIN && force_nonblock) {
-                       if ((req->flags & IO_APOLL_MULTI_POLLED) == IO_APOLL_MULTI_POLLED) {
+                       if (issue_flags & IO_URING_F_MULTISHOT) {
                                io_kbuf_recycle(req, issue_flags);
                                return IOU_ISSUE_SKIP_COMPLETE;
                        }
@@ -869,7 +867,7 @@ out_free:
        if (msg.msg_inq)
                cflags |= IORING_CQE_F_SOCK_NONEMPTY;
 
-       if (!io_recv_finish(req, &ret, cflags, ret <= 0))
+       if (!io_recv_finish(req, &ret, cflags, ret <= 0, issue_flags))
                goto retry_multishot;
 
        return ret;