]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
io_uring/net: derive iovec storage later
authorPavel Begunkov <asml.silence@gmail.com>
Wed, 26 Feb 2025 11:41:19 +0000 (11:41 +0000)
committerJens Axboe <axboe@kernel.dk>
Thu, 27 Feb 2025 14:27:55 +0000 (07:27 -0700)
Don't read free_iov until right before we need it to import the iovec.
The only place that uses it before that is provided buffer selection,
but it only serves as temporary storage and iovec content is not reused
afterwards, so use a local variable for that.

Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Link: https://lore.kernel.org/r/8bfa7d74c33e37860a724f4e0e96660c25cd4c02.1740569495.git.asml.silence@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
io_uring/net.c

index c362dd6fc8901a3d18c45d8f9fbb599cb27460f9..36e218b62319c28666a604668b0cbb0ae7e49801 100644 (file)
@@ -203,14 +203,6 @@ static int io_compat_msg_copy_hdr(struct io_kiocb *req,
        struct iovec *iov;
        int ret, nr_segs;
 
-       if (iomsg->free_iov) {
-               nr_segs = iomsg->free_iov_nr;
-               iov = iomsg->free_iov;
-       } else {
-               iov = &iomsg->fast_iov;
-               nr_segs = 1;
-       }
-
        if (copy_from_user(msg, sr->umsg_compat, sizeof(*msg)))
                return -EFAULT;
 
@@ -221,8 +213,7 @@ static int io_compat_msg_copy_hdr(struct io_kiocb *req,
        uiov = compat_ptr(msg->msg_iov);
        if (req->flags & REQ_F_BUFFER_SELECT) {
                if (msg->msg_iovlen == 0) {
-                       sr->len = iov->iov_len = 0;
-                       iov->iov_base = NULL;
+                       sr->len = 0;
                } else if (msg->msg_iovlen > 1) {
                        return -EINVAL;
                } else {
@@ -236,6 +227,14 @@ static int io_compat_msg_copy_hdr(struct io_kiocb *req,
                return 0;
        }
 
+       if (iomsg->free_iov) {
+               nr_segs = iomsg->free_iov_nr;
+               iov = iomsg->free_iov;
+       } else {
+               iov = &iomsg->fast_iov;
+               nr_segs = 1;
+       }
+
        ret = __import_iovec(ddir, (struct iovec __user *)uiov, msg->msg_iovlen,
                                nr_segs, &iov, &iomsg->msg.msg_iter, true);
        if (unlikely(ret < 0))
@@ -273,14 +272,6 @@ static int io_msg_copy_hdr(struct io_kiocb *req, struct io_async_msghdr *iomsg,
        struct iovec *iov;
        int ret, nr_segs;
 
-       if (iomsg->free_iov) {
-               nr_segs = iomsg->free_iov_nr;
-               iov = iomsg->free_iov;
-       } else {
-               iov = &iomsg->fast_iov;
-               nr_segs = 1;
-       }
-
        ret = io_copy_msghdr_from_user(msg, umsg);
        if (unlikely(ret))
                return ret;
@@ -293,20 +284,28 @@ static int io_msg_copy_hdr(struct io_kiocb *req, struct io_async_msghdr *iomsg,
 
        if (req->flags & REQ_F_BUFFER_SELECT) {
                if (msg->msg_iovlen == 0) {
-                       sr->len = iov->iov_len = 0;
-                       iov->iov_base = NULL;
+                       sr->len = 0;
                } else if (msg->msg_iovlen > 1) {
                        return -EINVAL;
                } else {
                        struct iovec __user *uiov = msg->msg_iov;
+                       struct iovec tmp_iov;
 
-                       if (copy_from_user(iov, uiov, sizeof(*iov)))
+                       if (copy_from_user(&tmp_iov, uiov, sizeof(tmp_iov)))
                                return -EFAULT;
-                       sr->len = iov->iov_len;
+                       sr->len = tmp_iov.iov_len;
                }
                return 0;
        }
 
+       if (iomsg->free_iov) {
+               nr_segs = iomsg->free_iov_nr;
+               iov = iomsg->free_iov;
+       } else {
+               iov = &iomsg->fast_iov;
+               nr_segs = 1;
+       }
+
        ret = __import_iovec(ddir, msg->msg_iov, msg->msg_iovlen, nr_segs,
                                &iov, &iomsg->msg.msg_iter, false);
        if (unlikely(ret < 0))