]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
io_uring: fix multishot accept request leaks
authorPavel Begunkov <asml.silence@gmail.com>
Thu, 17 Nov 2022 18:40:16 +0000 (18:40 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 26 Nov 2022 08:27:49 +0000 (09:27 +0100)
commit 91482864768a874c4290ef93b84a78f4f1dac51b 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: 390ed29b5e425 ("io_uring: add IORING_ACCEPT_MULTISHOT for accept")
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Link: https://lore.kernel.org/r/7700ac57653f2823e30b34dc74da68678c0c5f13.1668710222.git.asml.silence@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
include/linux/io_uring.h
io_uring/io_uring.c
io_uring/io_uring.h
io_uring/net.c

index 4a2f6cc5a4927fdc0280b2b5b86d47938b8bd768..ad88c4fa1113259243364280bc7980b7751a6bdc 100644 (file)
@@ -15,6 +15,9 @@ enum io_uring_cmd_flags {
        IO_URING_F_SQE128               = 4,
        IO_URING_F_CQE32                = 8,
        IO_URING_F_IOPOLL               = 16,
+
+       /* the request is executed from poll, it should not be freed */
+       IO_URING_F_MULTISHOT            = 32,
 };
 
 struct io_uring_cmd {
index f347e81e2d986b1a13fd9c74806f22cb7d9e9452..adf73d162521869fa9f5f08bd5fadb0fa8dc1d79 100644 (file)
@@ -1618,7 +1618,7 @@ int io_poll_issue(struct io_kiocb *req, bool *locked)
        io_tw_lock(req->ctx, locked);
        if (unlikely(req->task->flags & PF_EXITING))
                return -EFAULT;
-       return io_issue_sqe(req, IO_URING_F_NONBLOCK);
+       return io_issue_sqe(req, IO_URING_F_NONBLOCK|IO_URING_F_MULTISHOT);
 }
 
 struct io_wq_work *io_wq_free_work(struct io_wq_work *work)
index 5121b20a9193681d2da2b3d83495077d28d15dd0..1b552d2137635183142adc4013c4194e20e716cb 100644 (file)
@@ -17,8 +17,8 @@ enum {
        IOU_ISSUE_SKIP_COMPLETE = -EIOCBQUEUED,
 
        /*
-        * Intended only when both REQ_F_POLLED and REQ_F_APOLL_MULTISHOT
-        * are set to indicate to the poll runner that multishot should be
+        * Intended only when both IO_URING_F_MULTISHOT is passed
+        * to indicate to the poll runner that multishot should be
         * removed and the result is set on req->cqe.res.
         */
        IOU_STOP_MULTISHOT      = -ECANCELED,
index 7804ac77745b15ffdb6654d9500c5a74d0ee6f4c..1ebcff53606dbfc6516fe17237011a5f839c5f06 100644 (file)
@@ -1168,8 +1168,7 @@ retry:
                         * return EAGAIN to arm the poll infra since it
                         * has already been done
                         */
-                       if ((req->flags & IO_APOLL_MULTI_POLLED) ==
-                           IO_APOLL_MULTI_POLLED)
+                       if (issue_flags & IO_URING_F_MULTISHOT)
                                ret = IOU_ISSUE_SKIP_COMPLETE;
                        return ret;
                }
@@ -1194,9 +1193,7 @@ retry:
                goto retry;
 
        io_req_set_res(req, ret, 0);
-       if (req->flags & REQ_F_POLLED)
-               return IOU_STOP_MULTISHOT;
-       return IOU_OK;
+       return (issue_flags & IO_URING_F_MULTISHOT) ? IOU_STOP_MULTISHOT : IOU_OK;
 }
 
 int io_socket_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)