From nobody Fri Dec 19 18:43:12 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6A8511FF5DD; Sun, 24 Mar 2024 23:02:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711321376; cv=none; b=LfkYExzwDUgJ4+xtBoxcskdXwUa8vQsJj24y5w3hS34u6ImzCpC0WXv0xl72Z6GQ4xmY5okwyblge8nA2Ebv3GXqEn0ZzdVdfIh961Le3ygtz9zuxGIng3eWe0go67xL95uD/VQ9gl1tOsp1mkswW3CXekX6TZ2UTerjL7geEEc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711321376; c=relaxed/simple; bh=o0P18BDc75hN2CyaedHN48mE5buT5ZzzGqs59ZBu8ls=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=K0nH2M0ox+j+0KeLq/K7OUszLMXQrVNrATHBUJi7UaRdySsiqUU8obZwcShrW4gkrpfu10qfQ4QnUohpDs9wq0Mj3KrKhbinc14sFZXti8n+vO02wlICDbQS+ti3QgAveYpAeC7eSV+jFnfl2qUdkXUTFKIi74YVnjmYs6aA26M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bbLfQZQ7; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="bbLfQZQ7" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BC1B3C43394; Sun, 24 Mar 2024 23:02:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1711321375; bh=o0P18BDc75hN2CyaedHN48mE5buT5ZzzGqs59ZBu8ls=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bbLfQZQ7l/fLQL0ZP2d99HYYWPrZbH2EZP52JfufYvjkC1qhkZ9GFR/OrwPOLN2rC vGyNw8hl83KalsEd8l7HW6rEvL80hZNSnTrCAiAcqthmX/aNy9N4HqXQdXTa8WgCCS JQkX1ezq6XBA+mM0aD6KxRGJW3RpsZ1Y6nCoURqqEfxSk2pU2yWjlJ0hM0yOXcFfen r3tLfi0Po2GpL7iZqbCkSEKw+zqFEK532mla/to8xgwdoIMuWAmpLPdzXGLN8HYMVX k9xOiGvF7j0a2e2f0PJwYDY3ZhJU0DWQA7fuyt6/dgTbolWsSCrg8IX3S7PT6RKjN4 3RTVxhmSMHbxg== From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Jens Axboe , Sasha Levin Subject: [PATCH 6.6 099/638] io_uring/net: unify how recvmsg and sendmsg copy in the msghdr Date: Sun, 24 Mar 2024 18:52:16 -0400 Message-ID: <20240324230116.1348576-100-sashal@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240324230116.1348576-1-sashal@kernel.org> References: <20240324230116.1348576-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Jens Axboe [ Upstream commit 52307ac4f2b507f60bae6df5be938d35e199c688 ] For recvmsg, we roll our own since we support buffer selections. This isn't the case for sendmsg right now, but in preparation for doing so, make the recvmsg copy helpers generic so we can call them from the sendmsg side as well. Signed-off-by: Jens Axboe Stable-dep-of: 8ede3db5061b ("io_uring/net: fix overflow check in io_recvms= g_mshot_prep()") Signed-off-by: Sasha Levin --- io_uring/net.c | 271 ++++++++++++++++++++++++++----------------------- 1 file changed, 142 insertions(+), 129 deletions(-) diff --git a/io_uring/net.c b/io_uring/net.c index 161622029147c..ef495e2aac2bc 100644 --- a/io_uring/net.c +++ b/io_uring/net.c @@ -204,16 +204,150 @@ static int io_setup_async_msg(struct io_kiocb *req, return -EAGAIN; } =20 +static bool io_recvmsg_multishot_overflow(struct io_async_msghdr *iomsg) +{ + int hdr; + + if (iomsg->namelen < 0) + return true; + if (check_add_overflow((int)sizeof(struct io_uring_recvmsg_out), + iomsg->namelen, &hdr)) + return true; + if (check_add_overflow(hdr, (int)iomsg->controllen, &hdr)) + return true; + + return false; +} + +#ifdef CONFIG_COMPAT +static int __io_compat_msg_copy_hdr(struct io_kiocb *req, + struct io_async_msghdr *iomsg, + struct sockaddr __user **addr, int ddir) +{ + struct io_sr_msg *sr =3D io_kiocb_to_cmd(req, struct io_sr_msg); + struct compat_msghdr msg; + struct compat_iovec __user *uiov; + int ret; + + if (copy_from_user(&msg, sr->umsg_compat, sizeof(msg))) + return -EFAULT; + + ret =3D __get_compat_msghdr(&iomsg->msg, &msg, addr); + if (ret) + return ret; + + uiov =3D compat_ptr(msg.msg_iov); + if (req->flags & REQ_F_BUFFER_SELECT) { + compat_ssize_t clen; + + iomsg->free_iov =3D NULL; + if (msg.msg_iovlen =3D=3D 0) { + sr->len =3D 0; + } else if (msg.msg_iovlen > 1) { + return -EINVAL; + } else { + if (!access_ok(uiov, sizeof(*uiov))) + return -EFAULT; + if (__get_user(clen, &uiov->iov_len)) + return -EFAULT; + if (clen < 0) + return -EINVAL; + sr->len =3D clen; + } + + if (ddir =3D=3D ITER_DEST && req->flags & REQ_F_APOLL_MULTISHOT) { + iomsg->namelen =3D msg.msg_namelen; + iomsg->controllen =3D msg.msg_controllen; + if (io_recvmsg_multishot_overflow(iomsg)) + return -EOVERFLOW; + } + + return 0; + } + + iomsg->free_iov =3D iomsg->fast_iov; + ret =3D __import_iovec(ddir, (struct iovec __user *)uiov, msg.msg_iovlen, + UIO_FASTIOV, &iomsg->free_iov, + &iomsg->msg.msg_iter, true); + if (unlikely(ret < 0)) + return ret; + + return 0; +} +#endif + +static int __io_msg_copy_hdr(struct io_kiocb *req, struct io_async_msghdr = *iomsg, + struct sockaddr __user **addr, int ddir) +{ + struct io_sr_msg *sr =3D io_kiocb_to_cmd(req, struct io_sr_msg); + struct user_msghdr msg; + int ret; + + if (copy_from_user(&msg, sr->umsg, sizeof(*sr->umsg))) + return -EFAULT; + + ret =3D __copy_msghdr(&iomsg->msg, &msg, addr); + if (ret) + return ret; + + if (req->flags & REQ_F_BUFFER_SELECT) { + if (msg.msg_iovlen =3D=3D 0) { + sr->len =3D iomsg->fast_iov[0].iov_len =3D 0; + iomsg->fast_iov[0].iov_base =3D NULL; + iomsg->free_iov =3D NULL; + } else if (msg.msg_iovlen > 1) { + return -EINVAL; + } else { + if (copy_from_user(iomsg->fast_iov, msg.msg_iov, + sizeof(*msg.msg_iov))) + return -EFAULT; + sr->len =3D iomsg->fast_iov[0].iov_len; + iomsg->free_iov =3D NULL; + } + + if (ddir =3D=3D ITER_DEST && req->flags & REQ_F_APOLL_MULTISHOT) { + iomsg->namelen =3D msg.msg_namelen; + iomsg->controllen =3D msg.msg_controllen; + if (io_recvmsg_multishot_overflow(iomsg)) + return -EOVERFLOW; + } + + return 0; + } + + iomsg->free_iov =3D iomsg->fast_iov; + ret =3D __import_iovec(ddir, msg.msg_iov, msg.msg_iovlen, UIO_FASTIOV, + &iomsg->free_iov, &iomsg->msg.msg_iter, false); + if (unlikely(ret < 0)) + return ret; + + return 0; +} + +static int io_msg_copy_hdr(struct io_kiocb *req, struct io_async_msghdr *i= omsg, + struct sockaddr __user **addr, int ddir) +{ + iomsg->msg.msg_name =3D &iomsg->addr; + iomsg->msg.msg_iter.nr_segs =3D 0; + +#ifdef CONFIG_COMPAT + if (req->ctx->compat) + return __io_compat_msg_copy_hdr(req, iomsg, addr, ddir); +#endif + + return __io_msg_copy_hdr(req, iomsg, addr, ddir); +} + static int io_sendmsg_copy_hdr(struct io_kiocb *req, struct io_async_msghdr *iomsg) { struct io_sr_msg *sr =3D io_kiocb_to_cmd(req, struct io_sr_msg); int ret; =20 - iomsg->msg.msg_name =3D &iomsg->addr; - iomsg->free_iov =3D iomsg->fast_iov; - ret =3D sendmsg_copy_msghdr(&iomsg->msg, sr->umsg, sr->msg_flags, - &iomsg->free_iov); + ret =3D io_msg_copy_hdr(req, iomsg, NULL, ITER_SOURCE); + if (ret) + return ret; + /* save msg_control as sys_sendmsg() overwrites it */ sr->msg_control =3D iomsg->msg.msg_control_user; return ret; @@ -435,142 +569,21 @@ int io_send(struct io_kiocb *req, unsigned int issue= _flags) return IOU_OK; } =20 -static bool io_recvmsg_multishot_overflow(struct io_async_msghdr *iomsg) -{ - int hdr; - - if (iomsg->namelen < 0) - return true; - if (check_add_overflow((int)sizeof(struct io_uring_recvmsg_out), - iomsg->namelen, &hdr)) - return true; - if (check_add_overflow(hdr, (int)iomsg->controllen, &hdr)) - return true; - - return false; -} - -static int __io_recvmsg_copy_hdr(struct io_kiocb *req, - struct io_async_msghdr *iomsg) -{ - struct io_sr_msg *sr =3D io_kiocb_to_cmd(req, struct io_sr_msg); - struct user_msghdr msg; - int ret; - - if (copy_from_user(&msg, sr->umsg, sizeof(*sr->umsg))) - return -EFAULT; - - ret =3D __copy_msghdr(&iomsg->msg, &msg, &iomsg->uaddr); - if (ret) - return ret; - - if (req->flags & REQ_F_BUFFER_SELECT) { - if (msg.msg_iovlen =3D=3D 0) { - sr->len =3D iomsg->fast_iov[0].iov_len =3D 0; - iomsg->fast_iov[0].iov_base =3D NULL; - iomsg->free_iov =3D NULL; - } else if (msg.msg_iovlen > 1) { - return -EINVAL; - } else { - if (copy_from_user(iomsg->fast_iov, msg.msg_iov, sizeof(*msg.msg_iov))) - return -EFAULT; - sr->len =3D iomsg->fast_iov[0].iov_len; - iomsg->free_iov =3D NULL; - } - - if (req->flags & REQ_F_APOLL_MULTISHOT) { - iomsg->namelen =3D msg.msg_namelen; - iomsg->controllen =3D msg.msg_controllen; - if (io_recvmsg_multishot_overflow(iomsg)) - return -EOVERFLOW; - } - } else { - iomsg->free_iov =3D iomsg->fast_iov; - ret =3D __import_iovec(ITER_DEST, msg.msg_iov, msg.msg_iovlen, UIO_FASTI= OV, - &iomsg->free_iov, &iomsg->msg.msg_iter, - false); - if (ret > 0) - ret =3D 0; - } - - return ret; -} - -#ifdef CONFIG_COMPAT -static int __io_compat_recvmsg_copy_hdr(struct io_kiocb *req, - struct io_async_msghdr *iomsg) -{ - struct io_sr_msg *sr =3D io_kiocb_to_cmd(req, struct io_sr_msg); - struct compat_msghdr msg; - struct compat_iovec __user *uiov; - int ret; - - if (copy_from_user(&msg, sr->umsg_compat, sizeof(msg))) - return -EFAULT; - - ret =3D __get_compat_msghdr(&iomsg->msg, &msg, &iomsg->uaddr); - if (ret) - return ret; - - uiov =3D compat_ptr(msg.msg_iov); - if (req->flags & REQ_F_BUFFER_SELECT) { - compat_ssize_t clen; - - iomsg->free_iov =3D NULL; - if (msg.msg_iovlen =3D=3D 0) { - sr->len =3D 0; - } else if (msg.msg_iovlen > 1) { - return -EINVAL; - } else { - if (!access_ok(uiov, sizeof(*uiov))) - return -EFAULT; - if (__get_user(clen, &uiov->iov_len)) - return -EFAULT; - if (clen < 0) - return -EINVAL; - sr->len =3D clen; - } - - if (req->flags & REQ_F_APOLL_MULTISHOT) { - iomsg->namelen =3D msg.msg_namelen; - iomsg->controllen =3D msg.msg_controllen; - if (io_recvmsg_multishot_overflow(iomsg)) - return -EOVERFLOW; - } - } else { - iomsg->free_iov =3D iomsg->fast_iov; - ret =3D __import_iovec(ITER_DEST, (struct iovec __user *)uiov, msg.msg_i= ovlen, - UIO_FASTIOV, &iomsg->free_iov, - &iomsg->msg.msg_iter, true); - if (ret < 0) - return ret; - } - - return 0; -} -#endif - static int io_recvmsg_copy_hdr(struct io_kiocb *req, struct io_async_msghdr *iomsg) { - iomsg->msg.msg_name =3D &iomsg->addr; - iomsg->msg.msg_iter.nr_segs =3D 0; - -#ifdef CONFIG_COMPAT - if (req->ctx->compat) - return __io_compat_recvmsg_copy_hdr(req, iomsg); -#endif - - return __io_recvmsg_copy_hdr(req, iomsg); + return io_msg_copy_hdr(req, iomsg, &iomsg->uaddr, ITER_DEST); } =20 int io_recvmsg_prep_async(struct io_kiocb *req) { + struct io_async_msghdr *iomsg; int ret; =20 if (!io_msg_alloc_async_prep(req)) return -ENOMEM; - ret =3D io_recvmsg_copy_hdr(req, req->async_data); + iomsg =3D req->async_data; + ret =3D io_recvmsg_copy_hdr(req, iomsg); if (!ret) req->flags |=3D REQ_F_NEED_CLEANUP; return ret; --=20 2.43.0