1f9ead18cSJens Axboe // SPDX-License-Identifier: GPL-2.0 2f9ead18cSJens Axboe #include <linux/kernel.h> 3f9ead18cSJens Axboe #include <linux/errno.h> 4f9ead18cSJens Axboe #include <linux/file.h> 5f9ead18cSJens Axboe #include <linux/slab.h> 6f9ead18cSJens Axboe #include <linux/net.h> 7f9ead18cSJens Axboe #include <linux/compat.h> 8f9ead18cSJens Axboe #include <net/compat.h> 9f9ead18cSJens Axboe #include <linux/io_uring.h> 10f9ead18cSJens Axboe 11f9ead18cSJens Axboe #include <uapi/linux/io_uring.h> 12f9ead18cSJens Axboe 13f9ead18cSJens Axboe #include "io_uring.h" 143b77495aSJens Axboe #include "kbuf.h" 1543e0bbbdSJens Axboe #include "alloc_cache.h" 16f9ead18cSJens Axboe #include "net.h" 17f9ead18cSJens Axboe 18f9ead18cSJens Axboe #if defined(CONFIG_NET) 19f9ead18cSJens Axboe struct io_shutdown { 20f9ead18cSJens Axboe struct file *file; 21f9ead18cSJens Axboe int how; 22f9ead18cSJens Axboe }; 23f9ead18cSJens Axboe 24f9ead18cSJens Axboe struct io_accept { 25f9ead18cSJens Axboe struct file *file; 26f9ead18cSJens Axboe struct sockaddr __user *addr; 27f9ead18cSJens Axboe int __user *addr_len; 28f9ead18cSJens Axboe int flags; 29f9ead18cSJens Axboe u32 file_slot; 30f9ead18cSJens Axboe unsigned long nofile; 31f9ead18cSJens Axboe }; 32f9ead18cSJens Axboe 33f9ead18cSJens Axboe struct io_socket { 34f9ead18cSJens Axboe struct file *file; 35f9ead18cSJens Axboe int domain; 36f9ead18cSJens Axboe int type; 37f9ead18cSJens Axboe int protocol; 38f9ead18cSJens Axboe int flags; 39f9ead18cSJens Axboe u32 file_slot; 40f9ead18cSJens Axboe unsigned long nofile; 41f9ead18cSJens Axboe }; 42f9ead18cSJens Axboe 43f9ead18cSJens Axboe struct io_connect { 44f9ead18cSJens Axboe struct file *file; 45f9ead18cSJens Axboe struct sockaddr __user *addr; 46f9ead18cSJens Axboe int addr_len; 47f9ead18cSJens Axboe }; 48f9ead18cSJens Axboe 49f9ead18cSJens Axboe struct io_sr_msg { 50f9ead18cSJens Axboe struct file *file; 51f9ead18cSJens Axboe union { 52f9ead18cSJens Axboe struct compat_msghdr __user *umsg_compat; 53f9ead18cSJens Axboe struct user_msghdr __user *umsg; 54f9ead18cSJens Axboe void __user *buf; 55f9ead18cSJens Axboe }; 56f9ead18cSJens Axboe int msg_flags; 57f9ead18cSJens Axboe size_t len; 58f9ead18cSJens Axboe size_t done_io; 59f9ead18cSJens Axboe unsigned int flags; 60f9ead18cSJens Axboe }; 61f9ead18cSJens Axboe 62f9ead18cSJens Axboe #define IO_APOLL_MULTI_POLLED (REQ_F_APOLL_MULTISHOT | REQ_F_POLLED) 63f9ead18cSJens Axboe 64f9ead18cSJens Axboe int io_shutdown_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 65f9ead18cSJens Axboe { 66f9ead18cSJens Axboe struct io_shutdown *shutdown = io_kiocb_to_cmd(req); 67f9ead18cSJens Axboe 68f9ead18cSJens Axboe if (unlikely(sqe->off || sqe->addr || sqe->rw_flags || 69f9ead18cSJens Axboe sqe->buf_index || sqe->splice_fd_in)) 70f9ead18cSJens Axboe return -EINVAL; 71f9ead18cSJens Axboe 72f9ead18cSJens Axboe shutdown->how = READ_ONCE(sqe->len); 73f9ead18cSJens Axboe return 0; 74f9ead18cSJens Axboe } 75f9ead18cSJens Axboe 76f9ead18cSJens Axboe int io_shutdown(struct io_kiocb *req, unsigned int issue_flags) 77f9ead18cSJens Axboe { 78f9ead18cSJens Axboe struct io_shutdown *shutdown = io_kiocb_to_cmd(req); 79f9ead18cSJens Axboe struct socket *sock; 80f9ead18cSJens Axboe int ret; 81f9ead18cSJens Axboe 82f9ead18cSJens Axboe if (issue_flags & IO_URING_F_NONBLOCK) 83f9ead18cSJens Axboe return -EAGAIN; 84f9ead18cSJens Axboe 85f9ead18cSJens Axboe sock = sock_from_file(req->file); 86f9ead18cSJens Axboe if (unlikely(!sock)) 87f9ead18cSJens Axboe return -ENOTSOCK; 88f9ead18cSJens Axboe 89f9ead18cSJens Axboe ret = __sys_shutdown_sock(sock, shutdown->how); 90f9ead18cSJens Axboe io_req_set_res(req, ret, 0); 91f9ead18cSJens Axboe return IOU_OK; 92f9ead18cSJens Axboe } 93f9ead18cSJens Axboe 94f9ead18cSJens Axboe static bool io_net_retry(struct socket *sock, int flags) 95f9ead18cSJens Axboe { 96f9ead18cSJens Axboe if (!(flags & MSG_WAITALL)) 97f9ead18cSJens Axboe return false; 98f9ead18cSJens Axboe return sock->type == SOCK_STREAM || sock->type == SOCK_SEQPACKET; 99f9ead18cSJens Axboe } 100f9ead18cSJens Axboe 10143e0bbbdSJens Axboe static void io_netmsg_recycle(struct io_kiocb *req, unsigned int issue_flags) 10243e0bbbdSJens Axboe { 10343e0bbbdSJens Axboe struct io_async_msghdr *hdr = req->async_data; 10443e0bbbdSJens Axboe 10543e0bbbdSJens Axboe if (!hdr || issue_flags & IO_URING_F_UNLOCKED) 10643e0bbbdSJens Axboe return; 10743e0bbbdSJens Axboe 10843e0bbbdSJens Axboe /* Let normal cleanup path reap it if we fail adding to the cache */ 10943e0bbbdSJens Axboe if (io_alloc_cache_put(&req->ctx->netmsg_cache, &hdr->cache)) { 11043e0bbbdSJens Axboe req->async_data = NULL; 11143e0bbbdSJens Axboe req->flags &= ~REQ_F_ASYNC_DATA; 11243e0bbbdSJens Axboe } 11343e0bbbdSJens Axboe } 11443e0bbbdSJens Axboe 11543e0bbbdSJens Axboe static struct io_async_msghdr *io_recvmsg_alloc_async(struct io_kiocb *req, 11643e0bbbdSJens Axboe unsigned int issue_flags) 11743e0bbbdSJens Axboe { 11843e0bbbdSJens Axboe struct io_ring_ctx *ctx = req->ctx; 11943e0bbbdSJens Axboe struct io_cache_entry *entry; 12043e0bbbdSJens Axboe 12143e0bbbdSJens Axboe if (!(issue_flags & IO_URING_F_UNLOCKED) && 12243e0bbbdSJens Axboe (entry = io_alloc_cache_get(&ctx->netmsg_cache)) != NULL) { 12343e0bbbdSJens Axboe struct io_async_msghdr *hdr; 12443e0bbbdSJens Axboe 12543e0bbbdSJens Axboe hdr = container_of(entry, struct io_async_msghdr, cache); 12643e0bbbdSJens Axboe req->flags |= REQ_F_ASYNC_DATA; 12743e0bbbdSJens Axboe req->async_data = hdr; 12843e0bbbdSJens Axboe return hdr; 12943e0bbbdSJens Axboe } 13043e0bbbdSJens Axboe 13143e0bbbdSJens Axboe if (!io_alloc_async_data(req)) 13243e0bbbdSJens Axboe return req->async_data; 13343e0bbbdSJens Axboe 13443e0bbbdSJens Axboe return NULL; 13543e0bbbdSJens Axboe } 13643e0bbbdSJens Axboe 137f9ead18cSJens Axboe static int io_setup_async_msg(struct io_kiocb *req, 13843e0bbbdSJens Axboe struct io_async_msghdr *kmsg, 13943e0bbbdSJens Axboe unsigned int issue_flags) 140f9ead18cSJens Axboe { 141f9ead18cSJens Axboe struct io_async_msghdr *async_msg = req->async_data; 142f9ead18cSJens Axboe 143f9ead18cSJens Axboe if (async_msg) 144f9ead18cSJens Axboe return -EAGAIN; 14543e0bbbdSJens Axboe async_msg = io_recvmsg_alloc_async(req, issue_flags); 14643e0bbbdSJens Axboe if (!async_msg) { 147f9ead18cSJens Axboe kfree(kmsg->free_iov); 148f9ead18cSJens Axboe return -ENOMEM; 149f9ead18cSJens Axboe } 150f9ead18cSJens Axboe req->flags |= REQ_F_NEED_CLEANUP; 151f9ead18cSJens Axboe memcpy(async_msg, kmsg, sizeof(*kmsg)); 152f9ead18cSJens Axboe async_msg->msg.msg_name = &async_msg->addr; 153f9ead18cSJens Axboe /* if were using fast_iov, set it to the new one */ 154f9ead18cSJens Axboe if (!async_msg->free_iov) 155f9ead18cSJens Axboe async_msg->msg.msg_iter.iov = async_msg->fast_iov; 156f9ead18cSJens Axboe 157f9ead18cSJens Axboe return -EAGAIN; 158f9ead18cSJens Axboe } 159f9ead18cSJens Axboe 160f9ead18cSJens Axboe static int io_sendmsg_copy_hdr(struct io_kiocb *req, 161f9ead18cSJens Axboe struct io_async_msghdr *iomsg) 162f9ead18cSJens Axboe { 163f9ead18cSJens Axboe struct io_sr_msg *sr = io_kiocb_to_cmd(req); 164f9ead18cSJens Axboe 165f9ead18cSJens Axboe iomsg->msg.msg_name = &iomsg->addr; 166f9ead18cSJens Axboe iomsg->free_iov = iomsg->fast_iov; 167f9ead18cSJens Axboe return sendmsg_copy_msghdr(&iomsg->msg, sr->umsg, sr->msg_flags, 168f9ead18cSJens Axboe &iomsg->free_iov); 169f9ead18cSJens Axboe } 170f9ead18cSJens Axboe 171f9ead18cSJens Axboe int io_sendmsg_prep_async(struct io_kiocb *req) 172f9ead18cSJens Axboe { 173f9ead18cSJens Axboe int ret; 174f9ead18cSJens Axboe 175f9ead18cSJens Axboe ret = io_sendmsg_copy_hdr(req, req->async_data); 176f9ead18cSJens Axboe if (!ret) 177f9ead18cSJens Axboe req->flags |= REQ_F_NEED_CLEANUP; 178f9ead18cSJens Axboe return ret; 179f9ead18cSJens Axboe } 180f9ead18cSJens Axboe 181f9ead18cSJens Axboe void io_sendmsg_recvmsg_cleanup(struct io_kiocb *req) 182f9ead18cSJens Axboe { 183f9ead18cSJens Axboe struct io_async_msghdr *io = req->async_data; 184f9ead18cSJens Axboe 185f9ead18cSJens Axboe kfree(io->free_iov); 186f9ead18cSJens Axboe } 187f9ead18cSJens Axboe 188f9ead18cSJens Axboe int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 189f9ead18cSJens Axboe { 190f9ead18cSJens Axboe struct io_sr_msg *sr = io_kiocb_to_cmd(req); 191f9ead18cSJens Axboe 192f9ead18cSJens Axboe if (unlikely(sqe->file_index || sqe->addr2)) 193f9ead18cSJens Axboe return -EINVAL; 194f9ead18cSJens Axboe 195f9ead18cSJens Axboe sr->umsg = u64_to_user_ptr(READ_ONCE(sqe->addr)); 196f9ead18cSJens Axboe sr->len = READ_ONCE(sqe->len); 197f9ead18cSJens Axboe sr->flags = READ_ONCE(sqe->ioprio); 198f9ead18cSJens Axboe if (sr->flags & ~IORING_RECVSEND_POLL_FIRST) 199f9ead18cSJens Axboe return -EINVAL; 200f9ead18cSJens Axboe sr->msg_flags = READ_ONCE(sqe->msg_flags) | MSG_NOSIGNAL; 201f9ead18cSJens Axboe if (sr->msg_flags & MSG_DONTWAIT) 202f9ead18cSJens Axboe req->flags |= REQ_F_NOWAIT; 203f9ead18cSJens Axboe 204f9ead18cSJens Axboe #ifdef CONFIG_COMPAT 205f9ead18cSJens Axboe if (req->ctx->compat) 206f9ead18cSJens Axboe sr->msg_flags |= MSG_CMSG_COMPAT; 207f9ead18cSJens Axboe #endif 208f9ead18cSJens Axboe sr->done_io = 0; 209f9ead18cSJens Axboe return 0; 210f9ead18cSJens Axboe } 211f9ead18cSJens Axboe 212f9ead18cSJens Axboe int io_sendmsg(struct io_kiocb *req, unsigned int issue_flags) 213f9ead18cSJens Axboe { 214f9ead18cSJens Axboe struct io_sr_msg *sr = io_kiocb_to_cmd(req); 215f9ead18cSJens Axboe struct io_async_msghdr iomsg, *kmsg; 216f9ead18cSJens Axboe struct socket *sock; 217f9ead18cSJens Axboe unsigned flags; 218f9ead18cSJens Axboe int min_ret = 0; 219f9ead18cSJens Axboe int ret; 220f9ead18cSJens Axboe 221f9ead18cSJens Axboe sock = sock_from_file(req->file); 222f9ead18cSJens Axboe if (unlikely(!sock)) 223f9ead18cSJens Axboe return -ENOTSOCK; 224f9ead18cSJens Axboe 225f9ead18cSJens Axboe if (req_has_async_data(req)) { 226f9ead18cSJens Axboe kmsg = req->async_data; 227f9ead18cSJens Axboe } else { 228f9ead18cSJens Axboe ret = io_sendmsg_copy_hdr(req, &iomsg); 229f9ead18cSJens Axboe if (ret) 230f9ead18cSJens Axboe return ret; 231f9ead18cSJens Axboe kmsg = &iomsg; 232f9ead18cSJens Axboe } 233f9ead18cSJens Axboe 234f9ead18cSJens Axboe if (!(req->flags & REQ_F_POLLED) && 235f9ead18cSJens Axboe (sr->flags & IORING_RECVSEND_POLL_FIRST)) 23643e0bbbdSJens Axboe return io_setup_async_msg(req, kmsg, issue_flags); 237f9ead18cSJens Axboe 238f9ead18cSJens Axboe flags = sr->msg_flags; 239f9ead18cSJens Axboe if (issue_flags & IO_URING_F_NONBLOCK) 240f9ead18cSJens Axboe flags |= MSG_DONTWAIT; 241f9ead18cSJens Axboe if (flags & MSG_WAITALL) 242f9ead18cSJens Axboe min_ret = iov_iter_count(&kmsg->msg.msg_iter); 243f9ead18cSJens Axboe 244f9ead18cSJens Axboe ret = __sys_sendmsg_sock(sock, &kmsg->msg, flags); 245f9ead18cSJens Axboe 246f9ead18cSJens Axboe if (ret < min_ret) { 247f9ead18cSJens Axboe if (ret == -EAGAIN && (issue_flags & IO_URING_F_NONBLOCK)) 24843e0bbbdSJens Axboe return io_setup_async_msg(req, kmsg, issue_flags); 249f9ead18cSJens Axboe if (ret == -ERESTARTSYS) 250f9ead18cSJens Axboe ret = -EINTR; 251f9ead18cSJens Axboe if (ret > 0 && io_net_retry(sock, flags)) { 252f9ead18cSJens Axboe sr->done_io += ret; 253f9ead18cSJens Axboe req->flags |= REQ_F_PARTIAL_IO; 25443e0bbbdSJens Axboe return io_setup_async_msg(req, kmsg, issue_flags); 255f9ead18cSJens Axboe } 256f9ead18cSJens Axboe req_set_fail(req); 257f9ead18cSJens Axboe } 258f9ead18cSJens Axboe /* fast path, check for non-NULL to avoid function call */ 259f9ead18cSJens Axboe if (kmsg->free_iov) 260f9ead18cSJens Axboe kfree(kmsg->free_iov); 261f9ead18cSJens Axboe req->flags &= ~REQ_F_NEED_CLEANUP; 26243e0bbbdSJens Axboe io_netmsg_recycle(req, issue_flags); 263f9ead18cSJens Axboe if (ret >= 0) 264f9ead18cSJens Axboe ret += sr->done_io; 265f9ead18cSJens Axboe else if (sr->done_io) 266f9ead18cSJens Axboe ret = sr->done_io; 267f9ead18cSJens Axboe io_req_set_res(req, ret, 0); 268f9ead18cSJens Axboe return IOU_OK; 269f9ead18cSJens Axboe } 270f9ead18cSJens Axboe 271f9ead18cSJens Axboe int io_send(struct io_kiocb *req, unsigned int issue_flags) 272f9ead18cSJens Axboe { 273f9ead18cSJens Axboe struct io_sr_msg *sr = io_kiocb_to_cmd(req); 274f9ead18cSJens Axboe struct msghdr msg; 275f9ead18cSJens Axboe struct iovec iov; 276f9ead18cSJens Axboe struct socket *sock; 277f9ead18cSJens Axboe unsigned flags; 278f9ead18cSJens Axboe int min_ret = 0; 279f9ead18cSJens Axboe int ret; 280f9ead18cSJens Axboe 281f9ead18cSJens Axboe if (!(req->flags & REQ_F_POLLED) && 282f9ead18cSJens Axboe (sr->flags & IORING_RECVSEND_POLL_FIRST)) 283f9ead18cSJens Axboe return -EAGAIN; 284f9ead18cSJens Axboe 285f9ead18cSJens Axboe sock = sock_from_file(req->file); 286f9ead18cSJens Axboe if (unlikely(!sock)) 287f9ead18cSJens Axboe return -ENOTSOCK; 288f9ead18cSJens Axboe 289f9ead18cSJens Axboe ret = import_single_range(WRITE, sr->buf, sr->len, &iov, &msg.msg_iter); 290f9ead18cSJens Axboe if (unlikely(ret)) 291f9ead18cSJens Axboe return ret; 292f9ead18cSJens Axboe 293f9ead18cSJens Axboe msg.msg_name = NULL; 294f9ead18cSJens Axboe msg.msg_control = NULL; 295f9ead18cSJens Axboe msg.msg_controllen = 0; 296f9ead18cSJens Axboe msg.msg_namelen = 0; 297f9ead18cSJens Axboe 298f9ead18cSJens Axboe flags = sr->msg_flags; 299f9ead18cSJens Axboe if (issue_flags & IO_URING_F_NONBLOCK) 300f9ead18cSJens Axboe flags |= MSG_DONTWAIT; 301f9ead18cSJens Axboe if (flags & MSG_WAITALL) 302f9ead18cSJens Axboe min_ret = iov_iter_count(&msg.msg_iter); 303f9ead18cSJens Axboe 304f9ead18cSJens Axboe msg.msg_flags = flags; 305f9ead18cSJens Axboe ret = sock_sendmsg(sock, &msg); 306f9ead18cSJens Axboe if (ret < min_ret) { 307f9ead18cSJens Axboe if (ret == -EAGAIN && (issue_flags & IO_URING_F_NONBLOCK)) 308f9ead18cSJens Axboe return -EAGAIN; 309f9ead18cSJens Axboe if (ret == -ERESTARTSYS) 310f9ead18cSJens Axboe ret = -EINTR; 311f9ead18cSJens Axboe if (ret > 0 && io_net_retry(sock, flags)) { 312f9ead18cSJens Axboe sr->len -= ret; 313f9ead18cSJens Axboe sr->buf += ret; 314f9ead18cSJens Axboe sr->done_io += ret; 315f9ead18cSJens Axboe req->flags |= REQ_F_PARTIAL_IO; 316f9ead18cSJens Axboe return -EAGAIN; 317f9ead18cSJens Axboe } 318f9ead18cSJens Axboe req_set_fail(req); 319f9ead18cSJens Axboe } 320f9ead18cSJens Axboe if (ret >= 0) 321f9ead18cSJens Axboe ret += sr->done_io; 322f9ead18cSJens Axboe else if (sr->done_io) 323f9ead18cSJens Axboe ret = sr->done_io; 324f9ead18cSJens Axboe io_req_set_res(req, ret, 0); 325f9ead18cSJens Axboe return IOU_OK; 326f9ead18cSJens Axboe } 327f9ead18cSJens Axboe 3289bb66906SDylan Yudaken static bool io_recvmsg_multishot_overflow(struct io_async_msghdr *iomsg) 3299bb66906SDylan Yudaken { 3309b0fc3c0SDylan Yudaken int hdr; 3319bb66906SDylan Yudaken 3329b0fc3c0SDylan Yudaken if (iomsg->namelen < 0) 3339bb66906SDylan Yudaken return true; 3349b0fc3c0SDylan Yudaken if (check_add_overflow((int)sizeof(struct io_uring_recvmsg_out), 3359b0fc3c0SDylan Yudaken iomsg->namelen, &hdr)) 3369bb66906SDylan Yudaken return true; 3379b0fc3c0SDylan Yudaken if (check_add_overflow(hdr, (int)iomsg->controllen, &hdr)) 3389bb66906SDylan Yudaken return true; 3399bb66906SDylan Yudaken 3409bb66906SDylan Yudaken return false; 3419bb66906SDylan Yudaken } 3429bb66906SDylan Yudaken 343f9ead18cSJens Axboe static int __io_recvmsg_copy_hdr(struct io_kiocb *req, 344f9ead18cSJens Axboe struct io_async_msghdr *iomsg) 345f9ead18cSJens Axboe { 346f9ead18cSJens Axboe struct io_sr_msg *sr = io_kiocb_to_cmd(req); 3477fa875b8SDylan Yudaken struct user_msghdr msg; 348f9ead18cSJens Axboe int ret; 349f9ead18cSJens Axboe 3507fa875b8SDylan Yudaken if (copy_from_user(&msg, sr->umsg, sizeof(*sr->umsg))) 3517fa875b8SDylan Yudaken return -EFAULT; 3527fa875b8SDylan Yudaken 3537fa875b8SDylan Yudaken ret = __copy_msghdr(&iomsg->msg, &msg, &iomsg->uaddr); 354f9ead18cSJens Axboe if (ret) 355f9ead18cSJens Axboe return ret; 356f9ead18cSJens Axboe 357f9ead18cSJens Axboe if (req->flags & REQ_F_BUFFER_SELECT) { 3587fa875b8SDylan Yudaken if (msg.msg_iovlen == 0) { 3595702196eSDylan Yudaken sr->len = iomsg->fast_iov[0].iov_len = 0; 3605702196eSDylan Yudaken iomsg->fast_iov[0].iov_base = NULL; 3615702196eSDylan Yudaken iomsg->free_iov = NULL; 3627fa875b8SDylan Yudaken } else if (msg.msg_iovlen > 1) { 363f9ead18cSJens Axboe return -EINVAL; 3645702196eSDylan Yudaken } else { 3657fa875b8SDylan Yudaken if (copy_from_user(iomsg->fast_iov, msg.msg_iov, sizeof(*msg.msg_iov))) 366f9ead18cSJens Axboe return -EFAULT; 367f9ead18cSJens Axboe sr->len = iomsg->fast_iov[0].iov_len; 368f9ead18cSJens Axboe iomsg->free_iov = NULL; 3695702196eSDylan Yudaken } 3709bb66906SDylan Yudaken 3719bb66906SDylan Yudaken if (req->flags & REQ_F_APOLL_MULTISHOT) { 3729bb66906SDylan Yudaken iomsg->namelen = msg.msg_namelen; 3739bb66906SDylan Yudaken iomsg->controllen = msg.msg_controllen; 3749bb66906SDylan Yudaken if (io_recvmsg_multishot_overflow(iomsg)) 3759bb66906SDylan Yudaken return -EOVERFLOW; 3769bb66906SDylan Yudaken } 377f9ead18cSJens Axboe } else { 378f9ead18cSJens Axboe iomsg->free_iov = iomsg->fast_iov; 3797fa875b8SDylan Yudaken ret = __import_iovec(READ, msg.msg_iov, msg.msg_iovlen, UIO_FASTIOV, 380f9ead18cSJens Axboe &iomsg->free_iov, &iomsg->msg.msg_iter, 381f9ead18cSJens Axboe false); 382f9ead18cSJens Axboe if (ret > 0) 383f9ead18cSJens Axboe ret = 0; 384f9ead18cSJens Axboe } 385f9ead18cSJens Axboe 386f9ead18cSJens Axboe return ret; 387f9ead18cSJens Axboe } 388f9ead18cSJens Axboe 389f9ead18cSJens Axboe #ifdef CONFIG_COMPAT 390f9ead18cSJens Axboe static int __io_compat_recvmsg_copy_hdr(struct io_kiocb *req, 391f9ead18cSJens Axboe struct io_async_msghdr *iomsg) 392f9ead18cSJens Axboe { 393f9ead18cSJens Axboe struct io_sr_msg *sr = io_kiocb_to_cmd(req); 39472c531f8SDylan Yudaken struct compat_msghdr msg; 395f9ead18cSJens Axboe struct compat_iovec __user *uiov; 396f9ead18cSJens Axboe int ret; 397f9ead18cSJens Axboe 39872c531f8SDylan Yudaken if (copy_from_user(&msg, sr->umsg_compat, sizeof(msg))) 39972c531f8SDylan Yudaken return -EFAULT; 40072c531f8SDylan Yudaken 401*4f6a94d3SJens Axboe ret = __get_compat_msghdr(&iomsg->msg, &msg, &iomsg->uaddr); 402f9ead18cSJens Axboe if (ret) 403f9ead18cSJens Axboe return ret; 404f9ead18cSJens Axboe 40572c531f8SDylan Yudaken uiov = compat_ptr(msg.msg_iov); 406f9ead18cSJens Axboe if (req->flags & REQ_F_BUFFER_SELECT) { 407f9ead18cSJens Axboe compat_ssize_t clen; 408f9ead18cSJens Axboe 40972c531f8SDylan Yudaken if (msg.msg_iovlen == 0) { 4106d2f75a0SDylan Yudaken sr->len = 0; 4116d2f75a0SDylan Yudaken iomsg->free_iov = NULL; 41272c531f8SDylan Yudaken } else if (msg.msg_iovlen > 1) { 413f9ead18cSJens Axboe return -EINVAL; 4146d2f75a0SDylan Yudaken } else { 415f9ead18cSJens Axboe if (!access_ok(uiov, sizeof(*uiov))) 416f9ead18cSJens Axboe return -EFAULT; 417f9ead18cSJens Axboe if (__get_user(clen, &uiov->iov_len)) 418f9ead18cSJens Axboe return -EFAULT; 419f9ead18cSJens Axboe if (clen < 0) 420f9ead18cSJens Axboe return -EINVAL; 421f9ead18cSJens Axboe sr->len = clen; 422f9ead18cSJens Axboe iomsg->free_iov = NULL; 4236d2f75a0SDylan Yudaken } 4249bb66906SDylan Yudaken 4259bb66906SDylan Yudaken if (req->flags & REQ_F_APOLL_MULTISHOT) { 4269bb66906SDylan Yudaken iomsg->namelen = msg.msg_namelen; 4279bb66906SDylan Yudaken iomsg->controllen = msg.msg_controllen; 4289bb66906SDylan Yudaken if (io_recvmsg_multishot_overflow(iomsg)) 4299bb66906SDylan Yudaken return -EOVERFLOW; 4309bb66906SDylan Yudaken } 431f9ead18cSJens Axboe } else { 432f9ead18cSJens Axboe iomsg->free_iov = iomsg->fast_iov; 43372c531f8SDylan Yudaken ret = __import_iovec(READ, (struct iovec __user *)uiov, msg.msg_iovlen, 434f9ead18cSJens Axboe UIO_FASTIOV, &iomsg->free_iov, 435f9ead18cSJens Axboe &iomsg->msg.msg_iter, true); 436f9ead18cSJens Axboe if (ret < 0) 437f9ead18cSJens Axboe return ret; 438f9ead18cSJens Axboe } 439f9ead18cSJens Axboe 440f9ead18cSJens Axboe return 0; 441f9ead18cSJens Axboe } 442f9ead18cSJens Axboe #endif 443f9ead18cSJens Axboe 444f9ead18cSJens Axboe static int io_recvmsg_copy_hdr(struct io_kiocb *req, 445f9ead18cSJens Axboe struct io_async_msghdr *iomsg) 446f9ead18cSJens Axboe { 447f9ead18cSJens Axboe iomsg->msg.msg_name = &iomsg->addr; 448f9ead18cSJens Axboe 449f9ead18cSJens Axboe #ifdef CONFIG_COMPAT 450f9ead18cSJens Axboe if (req->ctx->compat) 451f9ead18cSJens Axboe return __io_compat_recvmsg_copy_hdr(req, iomsg); 452f9ead18cSJens Axboe #endif 453f9ead18cSJens Axboe 454f9ead18cSJens Axboe return __io_recvmsg_copy_hdr(req, iomsg); 455f9ead18cSJens Axboe } 456f9ead18cSJens Axboe 457f9ead18cSJens Axboe int io_recvmsg_prep_async(struct io_kiocb *req) 458f9ead18cSJens Axboe { 459f9ead18cSJens Axboe int ret; 460f9ead18cSJens Axboe 461f9ead18cSJens Axboe ret = io_recvmsg_copy_hdr(req, req->async_data); 462f9ead18cSJens Axboe if (!ret) 463f9ead18cSJens Axboe req->flags |= REQ_F_NEED_CLEANUP; 464f9ead18cSJens Axboe return ret; 465f9ead18cSJens Axboe } 466f9ead18cSJens Axboe 467b3fdea6eSDylan Yudaken #define RECVMSG_FLAGS (IORING_RECVSEND_POLL_FIRST | IORING_RECV_MULTISHOT) 468b3fdea6eSDylan Yudaken 469f9ead18cSJens Axboe int io_recvmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 470f9ead18cSJens Axboe { 471f9ead18cSJens Axboe struct io_sr_msg *sr = io_kiocb_to_cmd(req); 472f9ead18cSJens Axboe 473f9ead18cSJens Axboe if (unlikely(sqe->file_index || sqe->addr2)) 474f9ead18cSJens Axboe return -EINVAL; 475f9ead18cSJens Axboe 476f9ead18cSJens Axboe sr->umsg = u64_to_user_ptr(READ_ONCE(sqe->addr)); 477f9ead18cSJens Axboe sr->len = READ_ONCE(sqe->len); 478f9ead18cSJens Axboe sr->flags = READ_ONCE(sqe->ioprio); 479b3fdea6eSDylan Yudaken if (sr->flags & ~(RECVMSG_FLAGS)) 480f9ead18cSJens Axboe return -EINVAL; 481f9ead18cSJens Axboe sr->msg_flags = READ_ONCE(sqe->msg_flags) | MSG_NOSIGNAL; 482f9ead18cSJens Axboe if (sr->msg_flags & MSG_DONTWAIT) 483f9ead18cSJens Axboe req->flags |= REQ_F_NOWAIT; 484f9ead18cSJens Axboe if (sr->msg_flags & MSG_ERRQUEUE) 485f9ead18cSJens Axboe req->flags |= REQ_F_CLEAR_POLLIN; 486b3fdea6eSDylan Yudaken if (sr->flags & IORING_RECV_MULTISHOT) { 487b3fdea6eSDylan Yudaken if (!(req->flags & REQ_F_BUFFER_SELECT)) 488b3fdea6eSDylan Yudaken return -EINVAL; 489b3fdea6eSDylan Yudaken if (sr->msg_flags & MSG_WAITALL) 490b3fdea6eSDylan Yudaken return -EINVAL; 491b3fdea6eSDylan Yudaken if (req->opcode == IORING_OP_RECV && sr->len) 492b3fdea6eSDylan Yudaken return -EINVAL; 493b3fdea6eSDylan Yudaken req->flags |= REQ_F_APOLL_MULTISHOT; 494b3fdea6eSDylan Yudaken } 495f9ead18cSJens Axboe 496f9ead18cSJens Axboe #ifdef CONFIG_COMPAT 497f9ead18cSJens Axboe if (req->ctx->compat) 498f9ead18cSJens Axboe sr->msg_flags |= MSG_CMSG_COMPAT; 499f9ead18cSJens Axboe #endif 500f9ead18cSJens Axboe sr->done_io = 0; 501f9ead18cSJens Axboe return 0; 502f9ead18cSJens Axboe } 503f9ead18cSJens Axboe 504b3fdea6eSDylan Yudaken static inline void io_recv_prep_retry(struct io_kiocb *req) 505b3fdea6eSDylan Yudaken { 506b3fdea6eSDylan Yudaken struct io_sr_msg *sr = io_kiocb_to_cmd(req); 507b3fdea6eSDylan Yudaken 508b3fdea6eSDylan Yudaken sr->done_io = 0; 509b3fdea6eSDylan Yudaken sr->len = 0; /* get from the provided buffer */ 510b3fdea6eSDylan Yudaken } 511b3fdea6eSDylan Yudaken 512b3fdea6eSDylan Yudaken /* 5139bb66906SDylan Yudaken * Finishes io_recv and io_recvmsg. 514b3fdea6eSDylan Yudaken * 515b3fdea6eSDylan Yudaken * Returns true if it is actually finished, or false if it should run 516b3fdea6eSDylan Yudaken * again (for multishot). 517b3fdea6eSDylan Yudaken */ 5189bb66906SDylan Yudaken static inline bool io_recv_finish(struct io_kiocb *req, int *ret, 5199bb66906SDylan Yudaken unsigned int cflags, bool mshot_finished) 520b3fdea6eSDylan Yudaken { 521b3fdea6eSDylan Yudaken if (!(req->flags & REQ_F_APOLL_MULTISHOT)) { 522b3fdea6eSDylan Yudaken io_req_set_res(req, *ret, cflags); 523b3fdea6eSDylan Yudaken *ret = IOU_OK; 524b3fdea6eSDylan Yudaken return true; 525b3fdea6eSDylan Yudaken } 526b3fdea6eSDylan Yudaken 5279bb66906SDylan Yudaken if (!mshot_finished) { 528b3fdea6eSDylan Yudaken if (io_post_aux_cqe(req->ctx, req->cqe.user_data, *ret, 529b3fdea6eSDylan Yudaken cflags | IORING_CQE_F_MORE, false)) { 530b3fdea6eSDylan Yudaken io_recv_prep_retry(req); 531b3fdea6eSDylan Yudaken return false; 532b3fdea6eSDylan Yudaken } 533b3fdea6eSDylan Yudaken /* 534b3fdea6eSDylan Yudaken * Otherwise stop multishot but use the current result. 535b3fdea6eSDylan Yudaken * Probably will end up going into overflow, but this means 536b3fdea6eSDylan Yudaken * we cannot trust the ordering anymore 537b3fdea6eSDylan Yudaken */ 538b3fdea6eSDylan Yudaken } 539b3fdea6eSDylan Yudaken 540b3fdea6eSDylan Yudaken io_req_set_res(req, *ret, cflags); 541b3fdea6eSDylan Yudaken 542b3fdea6eSDylan Yudaken if (req->flags & REQ_F_POLLED) 543b3fdea6eSDylan Yudaken *ret = IOU_STOP_MULTISHOT; 544e2df2ccbSDylan Yudaken else 545e2df2ccbSDylan Yudaken *ret = IOU_OK; 546b3fdea6eSDylan Yudaken return true; 547b3fdea6eSDylan Yudaken } 548b3fdea6eSDylan Yudaken 5499bb66906SDylan Yudaken static int io_recvmsg_prep_multishot(struct io_async_msghdr *kmsg, 5509bb66906SDylan Yudaken struct io_sr_msg *sr, void __user **buf, 5519bb66906SDylan Yudaken size_t *len) 5529bb66906SDylan Yudaken { 5539bb66906SDylan Yudaken unsigned long ubuf = (unsigned long) *buf; 5549bb66906SDylan Yudaken unsigned long hdr; 5559bb66906SDylan Yudaken 5569bb66906SDylan Yudaken hdr = sizeof(struct io_uring_recvmsg_out) + kmsg->namelen + 5579bb66906SDylan Yudaken kmsg->controllen; 5589bb66906SDylan Yudaken if (*len < hdr) 5599bb66906SDylan Yudaken return -EFAULT; 5609bb66906SDylan Yudaken 5619bb66906SDylan Yudaken if (kmsg->controllen) { 5629bb66906SDylan Yudaken unsigned long control = ubuf + hdr - kmsg->controllen; 5639bb66906SDylan Yudaken 5649bb66906SDylan Yudaken kmsg->msg.msg_control_user = (void *) control; 5659bb66906SDylan Yudaken kmsg->msg.msg_controllen = kmsg->controllen; 5669bb66906SDylan Yudaken } 5679bb66906SDylan Yudaken 5689bb66906SDylan Yudaken sr->buf = *buf; /* stash for later copy */ 5699bb66906SDylan Yudaken *buf = (void *) (ubuf + hdr); 5709bb66906SDylan Yudaken kmsg->payloadlen = *len = *len - hdr; 5719bb66906SDylan Yudaken return 0; 5729bb66906SDylan Yudaken } 5739bb66906SDylan Yudaken 5749bb66906SDylan Yudaken struct io_recvmsg_multishot_hdr { 5759bb66906SDylan Yudaken struct io_uring_recvmsg_out msg; 5769bb66906SDylan Yudaken struct sockaddr_storage addr; 5779bb66906SDylan Yudaken }; 5789bb66906SDylan Yudaken 5799bb66906SDylan Yudaken static int io_recvmsg_multishot(struct socket *sock, struct io_sr_msg *io, 5809bb66906SDylan Yudaken struct io_async_msghdr *kmsg, 5819bb66906SDylan Yudaken unsigned int flags, bool *finished) 5829bb66906SDylan Yudaken { 5839bb66906SDylan Yudaken int err; 5849bb66906SDylan Yudaken int copy_len; 5859bb66906SDylan Yudaken struct io_recvmsg_multishot_hdr hdr; 5869bb66906SDylan Yudaken 5879bb66906SDylan Yudaken if (kmsg->namelen) 5889bb66906SDylan Yudaken kmsg->msg.msg_name = &hdr.addr; 5899bb66906SDylan Yudaken kmsg->msg.msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT); 5909bb66906SDylan Yudaken kmsg->msg.msg_namelen = 0; 5919bb66906SDylan Yudaken 5929bb66906SDylan Yudaken if (sock->file->f_flags & O_NONBLOCK) 5939bb66906SDylan Yudaken flags |= MSG_DONTWAIT; 5949bb66906SDylan Yudaken 5959bb66906SDylan Yudaken err = sock_recvmsg(sock, &kmsg->msg, flags); 5969bb66906SDylan Yudaken *finished = err <= 0; 5979bb66906SDylan Yudaken if (err < 0) 5989bb66906SDylan Yudaken return err; 5999bb66906SDylan Yudaken 6009bb66906SDylan Yudaken hdr.msg = (struct io_uring_recvmsg_out) { 6019bb66906SDylan Yudaken .controllen = kmsg->controllen - kmsg->msg.msg_controllen, 6029bb66906SDylan Yudaken .flags = kmsg->msg.msg_flags & ~MSG_CMSG_COMPAT 6039bb66906SDylan Yudaken }; 6049bb66906SDylan Yudaken 6059bb66906SDylan Yudaken hdr.msg.payloadlen = err; 6069bb66906SDylan Yudaken if (err > kmsg->payloadlen) 6079bb66906SDylan Yudaken err = kmsg->payloadlen; 6089bb66906SDylan Yudaken 6099bb66906SDylan Yudaken copy_len = sizeof(struct io_uring_recvmsg_out); 6109bb66906SDylan Yudaken if (kmsg->msg.msg_namelen > kmsg->namelen) 6119bb66906SDylan Yudaken copy_len += kmsg->namelen; 6129bb66906SDylan Yudaken else 6139bb66906SDylan Yudaken copy_len += kmsg->msg.msg_namelen; 6149bb66906SDylan Yudaken 6159bb66906SDylan Yudaken /* 6169bb66906SDylan Yudaken * "fromlen shall refer to the value before truncation.." 6179bb66906SDylan Yudaken * 1003.1g 6189bb66906SDylan Yudaken */ 6199bb66906SDylan Yudaken hdr.msg.namelen = kmsg->msg.msg_namelen; 6209bb66906SDylan Yudaken 6219bb66906SDylan Yudaken /* ensure that there is no gap between hdr and sockaddr_storage */ 6229bb66906SDylan Yudaken BUILD_BUG_ON(offsetof(struct io_recvmsg_multishot_hdr, addr) != 6239bb66906SDylan Yudaken sizeof(struct io_uring_recvmsg_out)); 6249bb66906SDylan Yudaken if (copy_to_user(io->buf, &hdr, copy_len)) { 6259bb66906SDylan Yudaken *finished = true; 6269bb66906SDylan Yudaken return -EFAULT; 6279bb66906SDylan Yudaken } 6289bb66906SDylan Yudaken 6299bb66906SDylan Yudaken return sizeof(struct io_uring_recvmsg_out) + kmsg->namelen + 6309bb66906SDylan Yudaken kmsg->controllen + err; 6319bb66906SDylan Yudaken } 6329bb66906SDylan Yudaken 633f9ead18cSJens Axboe int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags) 634f9ead18cSJens Axboe { 635f9ead18cSJens Axboe struct io_sr_msg *sr = io_kiocb_to_cmd(req); 636f9ead18cSJens Axboe struct io_async_msghdr iomsg, *kmsg; 637f9ead18cSJens Axboe struct socket *sock; 638f9ead18cSJens Axboe unsigned int cflags; 639f9ead18cSJens Axboe unsigned flags; 640f9ead18cSJens Axboe int ret, min_ret = 0; 641f9ead18cSJens Axboe bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK; 6429bb66906SDylan Yudaken bool mshot_finished = true; 643f9ead18cSJens Axboe 644f9ead18cSJens Axboe sock = sock_from_file(req->file); 645f9ead18cSJens Axboe if (unlikely(!sock)) 646f9ead18cSJens Axboe return -ENOTSOCK; 647f9ead18cSJens Axboe 648f9ead18cSJens Axboe if (req_has_async_data(req)) { 649f9ead18cSJens Axboe kmsg = req->async_data; 650f9ead18cSJens Axboe } else { 651f9ead18cSJens Axboe ret = io_recvmsg_copy_hdr(req, &iomsg); 652f9ead18cSJens Axboe if (ret) 653f9ead18cSJens Axboe return ret; 654f9ead18cSJens Axboe kmsg = &iomsg; 655f9ead18cSJens Axboe } 656f9ead18cSJens Axboe 657f9ead18cSJens Axboe if (!(req->flags & REQ_F_POLLED) && 658f9ead18cSJens Axboe (sr->flags & IORING_RECVSEND_POLL_FIRST)) 65943e0bbbdSJens Axboe return io_setup_async_msg(req, kmsg, issue_flags); 660f9ead18cSJens Axboe 6619bb66906SDylan Yudaken retry_multishot: 662f9ead18cSJens Axboe if (io_do_buffer_select(req)) { 663f9ead18cSJens Axboe void __user *buf; 6649bb66906SDylan Yudaken size_t len = sr->len; 665f9ead18cSJens Axboe 6669bb66906SDylan Yudaken buf = io_buffer_select(req, &len, issue_flags); 667f9ead18cSJens Axboe if (!buf) 668f9ead18cSJens Axboe return -ENOBUFS; 6699bb66906SDylan Yudaken 6709bb66906SDylan Yudaken if (req->flags & REQ_F_APOLL_MULTISHOT) { 6719bb66906SDylan Yudaken ret = io_recvmsg_prep_multishot(kmsg, sr, &buf, &len); 6729bb66906SDylan Yudaken if (ret) { 6739bb66906SDylan Yudaken io_kbuf_recycle(req, issue_flags); 6749bb66906SDylan Yudaken return ret; 6759bb66906SDylan Yudaken } 6769bb66906SDylan Yudaken } 6779bb66906SDylan Yudaken 678f9ead18cSJens Axboe kmsg->fast_iov[0].iov_base = buf; 6799bb66906SDylan Yudaken kmsg->fast_iov[0].iov_len = len; 680f9ead18cSJens Axboe iov_iter_init(&kmsg->msg.msg_iter, READ, kmsg->fast_iov, 1, 6819bb66906SDylan Yudaken len); 682f9ead18cSJens Axboe } 683f9ead18cSJens Axboe 684f9ead18cSJens Axboe flags = sr->msg_flags; 685f9ead18cSJens Axboe if (force_nonblock) 686f9ead18cSJens Axboe flags |= MSG_DONTWAIT; 687f9ead18cSJens Axboe if (flags & MSG_WAITALL) 688f9ead18cSJens Axboe min_ret = iov_iter_count(&kmsg->msg.msg_iter); 689f9ead18cSJens Axboe 690f9ead18cSJens Axboe kmsg->msg.msg_get_inq = 1; 6919bb66906SDylan Yudaken if (req->flags & REQ_F_APOLL_MULTISHOT) 6929bb66906SDylan Yudaken ret = io_recvmsg_multishot(sock, sr, kmsg, flags, 6939bb66906SDylan Yudaken &mshot_finished); 6949bb66906SDylan Yudaken else 6959bb66906SDylan Yudaken ret = __sys_recvmsg_sock(sock, &kmsg->msg, sr->umsg, 6969bb66906SDylan Yudaken kmsg->uaddr, flags); 6979bb66906SDylan Yudaken 698f9ead18cSJens Axboe if (ret < min_ret) { 6999bb66906SDylan Yudaken if (ret == -EAGAIN && force_nonblock) { 7009bb66906SDylan Yudaken ret = io_setup_async_msg(req, kmsg, issue_flags); 7019bb66906SDylan Yudaken if (ret == -EAGAIN && (req->flags & IO_APOLL_MULTI_POLLED) == 7029bb66906SDylan Yudaken IO_APOLL_MULTI_POLLED) { 7039bb66906SDylan Yudaken io_kbuf_recycle(req, issue_flags); 7049bb66906SDylan Yudaken return IOU_ISSUE_SKIP_COMPLETE; 7059bb66906SDylan Yudaken } 7069bb66906SDylan Yudaken return ret; 7079bb66906SDylan Yudaken } 708f9ead18cSJens Axboe if (ret == -ERESTARTSYS) 709f9ead18cSJens Axboe ret = -EINTR; 710f9ead18cSJens Axboe if (ret > 0 && io_net_retry(sock, flags)) { 711f9ead18cSJens Axboe sr->done_io += ret; 712f9ead18cSJens Axboe req->flags |= REQ_F_PARTIAL_IO; 71343e0bbbdSJens Axboe return io_setup_async_msg(req, kmsg, issue_flags); 714f9ead18cSJens Axboe } 715f9ead18cSJens Axboe req_set_fail(req); 716f9ead18cSJens Axboe } else if ((flags & MSG_WAITALL) && (kmsg->msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC))) { 717f9ead18cSJens Axboe req_set_fail(req); 718f9ead18cSJens Axboe } 719f9ead18cSJens Axboe 720d4e097daSDylan Yudaken if (ret > 0) 721f9ead18cSJens Axboe ret += sr->done_io; 722f9ead18cSJens Axboe else if (sr->done_io) 723f9ead18cSJens Axboe ret = sr->done_io; 724d4e097daSDylan Yudaken else 725d4e097daSDylan Yudaken io_kbuf_recycle(req, issue_flags); 726d4e097daSDylan Yudaken 727f9ead18cSJens Axboe cflags = io_put_kbuf(req, issue_flags); 728f9ead18cSJens Axboe if (kmsg->msg.msg_inq) 729f9ead18cSJens Axboe cflags |= IORING_CQE_F_SOCK_NONEMPTY; 730b3fdea6eSDylan Yudaken 7319bb66906SDylan Yudaken if (!io_recv_finish(req, &ret, cflags, mshot_finished)) 7329bb66906SDylan Yudaken goto retry_multishot; 7339bb66906SDylan Yudaken 7349bb66906SDylan Yudaken if (mshot_finished) { 7359bb66906SDylan Yudaken io_netmsg_recycle(req, issue_flags); 7369bb66906SDylan Yudaken /* fast path, check for non-NULL to avoid function call */ 7379bb66906SDylan Yudaken if (kmsg->free_iov) 7389bb66906SDylan Yudaken kfree(kmsg->free_iov); 7399bb66906SDylan Yudaken req->flags &= ~REQ_F_NEED_CLEANUP; 7409bb66906SDylan Yudaken } 7419bb66906SDylan Yudaken 7429bb66906SDylan Yudaken return ret; 743f9ead18cSJens Axboe } 744f9ead18cSJens Axboe 745f9ead18cSJens Axboe int io_recv(struct io_kiocb *req, unsigned int issue_flags) 746f9ead18cSJens Axboe { 747f9ead18cSJens Axboe struct io_sr_msg *sr = io_kiocb_to_cmd(req); 748f9ead18cSJens Axboe struct msghdr msg; 749f9ead18cSJens Axboe struct socket *sock; 750f9ead18cSJens Axboe struct iovec iov; 751f9ead18cSJens Axboe unsigned int cflags; 752f9ead18cSJens Axboe unsigned flags; 753f9ead18cSJens Axboe int ret, min_ret = 0; 754f9ead18cSJens Axboe bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK; 755b3fdea6eSDylan Yudaken size_t len = sr->len; 756f9ead18cSJens Axboe 757f9ead18cSJens Axboe if (!(req->flags & REQ_F_POLLED) && 758f9ead18cSJens Axboe (sr->flags & IORING_RECVSEND_POLL_FIRST)) 759f9ead18cSJens Axboe return -EAGAIN; 760f9ead18cSJens Axboe 761f9ead18cSJens Axboe sock = sock_from_file(req->file); 762f9ead18cSJens Axboe if (unlikely(!sock)) 763f9ead18cSJens Axboe return -ENOTSOCK; 764f9ead18cSJens Axboe 765b3fdea6eSDylan Yudaken retry_multishot: 766f9ead18cSJens Axboe if (io_do_buffer_select(req)) { 767f9ead18cSJens Axboe void __user *buf; 768f9ead18cSJens Axboe 769b3fdea6eSDylan Yudaken buf = io_buffer_select(req, &len, issue_flags); 770f9ead18cSJens Axboe if (!buf) 771f9ead18cSJens Axboe return -ENOBUFS; 772f9ead18cSJens Axboe sr->buf = buf; 773f9ead18cSJens Axboe } 774f9ead18cSJens Axboe 775b3fdea6eSDylan Yudaken ret = import_single_range(READ, sr->buf, len, &iov, &msg.msg_iter); 776f9ead18cSJens Axboe if (unlikely(ret)) 777f9ead18cSJens Axboe goto out_free; 778f9ead18cSJens Axboe 779f9ead18cSJens Axboe msg.msg_name = NULL; 780f9ead18cSJens Axboe msg.msg_namelen = 0; 781f9ead18cSJens Axboe msg.msg_control = NULL; 782f9ead18cSJens Axboe msg.msg_get_inq = 1; 783f9ead18cSJens Axboe msg.msg_flags = 0; 784f9ead18cSJens Axboe msg.msg_controllen = 0; 785f9ead18cSJens Axboe msg.msg_iocb = NULL; 786f9ead18cSJens Axboe 787f9ead18cSJens Axboe flags = sr->msg_flags; 788f9ead18cSJens Axboe if (force_nonblock) 789f9ead18cSJens Axboe flags |= MSG_DONTWAIT; 790f9ead18cSJens Axboe if (flags & MSG_WAITALL) 791f9ead18cSJens Axboe min_ret = iov_iter_count(&msg.msg_iter); 792f9ead18cSJens Axboe 793f9ead18cSJens Axboe ret = sock_recvmsg(sock, &msg, flags); 794f9ead18cSJens Axboe if (ret < min_ret) { 795b3fdea6eSDylan Yudaken if (ret == -EAGAIN && force_nonblock) { 796b3fdea6eSDylan Yudaken if ((req->flags & IO_APOLL_MULTI_POLLED) == IO_APOLL_MULTI_POLLED) { 797b3fdea6eSDylan Yudaken io_kbuf_recycle(req, issue_flags); 798b3fdea6eSDylan Yudaken return IOU_ISSUE_SKIP_COMPLETE; 799b3fdea6eSDylan Yudaken } 800b3fdea6eSDylan Yudaken 801f9ead18cSJens Axboe return -EAGAIN; 802b3fdea6eSDylan Yudaken } 803f9ead18cSJens Axboe if (ret == -ERESTARTSYS) 804f9ead18cSJens Axboe ret = -EINTR; 805f9ead18cSJens Axboe if (ret > 0 && io_net_retry(sock, flags)) { 806f9ead18cSJens Axboe sr->len -= ret; 807f9ead18cSJens Axboe sr->buf += ret; 808f9ead18cSJens Axboe sr->done_io += ret; 809f9ead18cSJens Axboe req->flags |= REQ_F_PARTIAL_IO; 810f9ead18cSJens Axboe return -EAGAIN; 811f9ead18cSJens Axboe } 812f9ead18cSJens Axboe req_set_fail(req); 813f9ead18cSJens Axboe } else if ((flags & MSG_WAITALL) && (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC))) { 814f9ead18cSJens Axboe out_free: 815f9ead18cSJens Axboe req_set_fail(req); 816f9ead18cSJens Axboe } 817f9ead18cSJens Axboe 818d4e097daSDylan Yudaken if (ret > 0) 819f9ead18cSJens Axboe ret += sr->done_io; 820f9ead18cSJens Axboe else if (sr->done_io) 821f9ead18cSJens Axboe ret = sr->done_io; 822d4e097daSDylan Yudaken else 823d4e097daSDylan Yudaken io_kbuf_recycle(req, issue_flags); 824d4e097daSDylan Yudaken 825f9ead18cSJens Axboe cflags = io_put_kbuf(req, issue_flags); 826f9ead18cSJens Axboe if (msg.msg_inq) 827f9ead18cSJens Axboe cflags |= IORING_CQE_F_SOCK_NONEMPTY; 828b3fdea6eSDylan Yudaken 8299bb66906SDylan Yudaken if (!io_recv_finish(req, &ret, cflags, ret <= 0)) 830b3fdea6eSDylan Yudaken goto retry_multishot; 831b3fdea6eSDylan Yudaken 832b3fdea6eSDylan Yudaken return ret; 833f9ead18cSJens Axboe } 834f9ead18cSJens Axboe 835f9ead18cSJens Axboe int io_accept_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 836f9ead18cSJens Axboe { 837f9ead18cSJens Axboe struct io_accept *accept = io_kiocb_to_cmd(req); 838f9ead18cSJens Axboe unsigned flags; 839f9ead18cSJens Axboe 840f9ead18cSJens Axboe if (sqe->len || sqe->buf_index) 841f9ead18cSJens Axboe return -EINVAL; 842f9ead18cSJens Axboe 843f9ead18cSJens Axboe accept->addr = u64_to_user_ptr(READ_ONCE(sqe->addr)); 844f9ead18cSJens Axboe accept->addr_len = u64_to_user_ptr(READ_ONCE(sqe->addr2)); 845f9ead18cSJens Axboe accept->flags = READ_ONCE(sqe->accept_flags); 846f9ead18cSJens Axboe accept->nofile = rlimit(RLIMIT_NOFILE); 847f9ead18cSJens Axboe flags = READ_ONCE(sqe->ioprio); 848f9ead18cSJens Axboe if (flags & ~IORING_ACCEPT_MULTISHOT) 849f9ead18cSJens Axboe return -EINVAL; 850f9ead18cSJens Axboe 851f9ead18cSJens Axboe accept->file_slot = READ_ONCE(sqe->file_index); 852f9ead18cSJens Axboe if (accept->file_slot) { 853f9ead18cSJens Axboe if (accept->flags & SOCK_CLOEXEC) 854f9ead18cSJens Axboe return -EINVAL; 855f9ead18cSJens Axboe if (flags & IORING_ACCEPT_MULTISHOT && 856f9ead18cSJens Axboe accept->file_slot != IORING_FILE_INDEX_ALLOC) 857f9ead18cSJens Axboe return -EINVAL; 858f9ead18cSJens Axboe } 859f9ead18cSJens Axboe if (accept->flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 860f9ead18cSJens Axboe return -EINVAL; 861f9ead18cSJens Axboe if (SOCK_NONBLOCK != O_NONBLOCK && (accept->flags & SOCK_NONBLOCK)) 862f9ead18cSJens Axboe accept->flags = (accept->flags & ~SOCK_NONBLOCK) | O_NONBLOCK; 863f9ead18cSJens Axboe if (flags & IORING_ACCEPT_MULTISHOT) 864f9ead18cSJens Axboe req->flags |= REQ_F_APOLL_MULTISHOT; 865f9ead18cSJens Axboe return 0; 866f9ead18cSJens Axboe } 867f9ead18cSJens Axboe 868f9ead18cSJens Axboe int io_accept(struct io_kiocb *req, unsigned int issue_flags) 869f9ead18cSJens Axboe { 870f9ead18cSJens Axboe struct io_ring_ctx *ctx = req->ctx; 871f9ead18cSJens Axboe struct io_accept *accept = io_kiocb_to_cmd(req); 872f9ead18cSJens Axboe bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK; 873f9ead18cSJens Axboe unsigned int file_flags = force_nonblock ? O_NONBLOCK : 0; 874f9ead18cSJens Axboe bool fixed = !!accept->file_slot; 875f9ead18cSJens Axboe struct file *file; 876f9ead18cSJens Axboe int ret, fd; 877f9ead18cSJens Axboe 878f9ead18cSJens Axboe retry: 879f9ead18cSJens Axboe if (!fixed) { 880f9ead18cSJens Axboe fd = __get_unused_fd_flags(accept->flags, accept->nofile); 881f9ead18cSJens Axboe if (unlikely(fd < 0)) 882f9ead18cSJens Axboe return fd; 883f9ead18cSJens Axboe } 884f9ead18cSJens Axboe file = do_accept(req->file, file_flags, accept->addr, accept->addr_len, 885f9ead18cSJens Axboe accept->flags); 886f9ead18cSJens Axboe if (IS_ERR(file)) { 887f9ead18cSJens Axboe if (!fixed) 888f9ead18cSJens Axboe put_unused_fd(fd); 889f9ead18cSJens Axboe ret = PTR_ERR(file); 890f9ead18cSJens Axboe if (ret == -EAGAIN && force_nonblock) { 891f9ead18cSJens Axboe /* 892f9ead18cSJens Axboe * if it's multishot and polled, we don't need to 893f9ead18cSJens Axboe * return EAGAIN to arm the poll infra since it 894f9ead18cSJens Axboe * has already been done 895f9ead18cSJens Axboe */ 896f9ead18cSJens Axboe if ((req->flags & IO_APOLL_MULTI_POLLED) == 897f9ead18cSJens Axboe IO_APOLL_MULTI_POLLED) 898f9ead18cSJens Axboe ret = IOU_ISSUE_SKIP_COMPLETE; 899f9ead18cSJens Axboe return ret; 900f9ead18cSJens Axboe } 901f9ead18cSJens Axboe if (ret == -ERESTARTSYS) 902f9ead18cSJens Axboe ret = -EINTR; 903f9ead18cSJens Axboe req_set_fail(req); 904f9ead18cSJens Axboe } else if (!fixed) { 905f9ead18cSJens Axboe fd_install(fd, file); 906f9ead18cSJens Axboe ret = fd; 907f9ead18cSJens Axboe } else { 908f9ead18cSJens Axboe ret = io_fixed_fd_install(req, issue_flags, file, 909f9ead18cSJens Axboe accept->file_slot); 910f9ead18cSJens Axboe } 911f9ead18cSJens Axboe 912f9ead18cSJens Axboe if (!(req->flags & REQ_F_APOLL_MULTISHOT)) { 913f9ead18cSJens Axboe io_req_set_res(req, ret, 0); 914f9ead18cSJens Axboe return IOU_OK; 915f9ead18cSJens Axboe } 916f9ead18cSJens Axboe 917cbd25748SDylan Yudaken if (ret >= 0 && 918cbd25748SDylan Yudaken io_post_aux_cqe(ctx, req->cqe.user_data, ret, IORING_CQE_F_MORE, false)) 919d245bca6SPavel Begunkov goto retry; 920cbd25748SDylan Yudaken 921cbd25748SDylan Yudaken io_req_set_res(req, ret, 0); 922cbd25748SDylan Yudaken if (req->flags & REQ_F_POLLED) 923cbd25748SDylan Yudaken return IOU_STOP_MULTISHOT; 924cbd25748SDylan Yudaken return IOU_OK; 925f9ead18cSJens Axboe } 926f9ead18cSJens Axboe 927f9ead18cSJens Axboe int io_socket_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 928f9ead18cSJens Axboe { 929f9ead18cSJens Axboe struct io_socket *sock = io_kiocb_to_cmd(req); 930f9ead18cSJens Axboe 931f9ead18cSJens Axboe if (sqe->addr || sqe->rw_flags || sqe->buf_index) 932f9ead18cSJens Axboe return -EINVAL; 933f9ead18cSJens Axboe 934f9ead18cSJens Axboe sock->domain = READ_ONCE(sqe->fd); 935f9ead18cSJens Axboe sock->type = READ_ONCE(sqe->off); 936f9ead18cSJens Axboe sock->protocol = READ_ONCE(sqe->len); 937f9ead18cSJens Axboe sock->file_slot = READ_ONCE(sqe->file_index); 938f9ead18cSJens Axboe sock->nofile = rlimit(RLIMIT_NOFILE); 939f9ead18cSJens Axboe 940f9ead18cSJens Axboe sock->flags = sock->type & ~SOCK_TYPE_MASK; 941f9ead18cSJens Axboe if (sock->file_slot && (sock->flags & SOCK_CLOEXEC)) 942f9ead18cSJens Axboe return -EINVAL; 943f9ead18cSJens Axboe if (sock->flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) 944f9ead18cSJens Axboe return -EINVAL; 945f9ead18cSJens Axboe return 0; 946f9ead18cSJens Axboe } 947f9ead18cSJens Axboe 948f9ead18cSJens Axboe int io_socket(struct io_kiocb *req, unsigned int issue_flags) 949f9ead18cSJens Axboe { 950f9ead18cSJens Axboe struct io_socket *sock = io_kiocb_to_cmd(req); 951f9ead18cSJens Axboe bool fixed = !!sock->file_slot; 952f9ead18cSJens Axboe struct file *file; 953f9ead18cSJens Axboe int ret, fd; 954f9ead18cSJens Axboe 955f9ead18cSJens Axboe if (!fixed) { 956f9ead18cSJens Axboe fd = __get_unused_fd_flags(sock->flags, sock->nofile); 957f9ead18cSJens Axboe if (unlikely(fd < 0)) 958f9ead18cSJens Axboe return fd; 959f9ead18cSJens Axboe } 960f9ead18cSJens Axboe file = __sys_socket_file(sock->domain, sock->type, sock->protocol); 961f9ead18cSJens Axboe if (IS_ERR(file)) { 962f9ead18cSJens Axboe if (!fixed) 963f9ead18cSJens Axboe put_unused_fd(fd); 964f9ead18cSJens Axboe ret = PTR_ERR(file); 965f9ead18cSJens Axboe if (ret == -EAGAIN && (issue_flags & IO_URING_F_NONBLOCK)) 966f9ead18cSJens Axboe return -EAGAIN; 967f9ead18cSJens Axboe if (ret == -ERESTARTSYS) 968f9ead18cSJens Axboe ret = -EINTR; 969f9ead18cSJens Axboe req_set_fail(req); 970f9ead18cSJens Axboe } else if (!fixed) { 971f9ead18cSJens Axboe fd_install(fd, file); 972f9ead18cSJens Axboe ret = fd; 973f9ead18cSJens Axboe } else { 974f9ead18cSJens Axboe ret = io_fixed_fd_install(req, issue_flags, file, 975f9ead18cSJens Axboe sock->file_slot); 976f9ead18cSJens Axboe } 977f9ead18cSJens Axboe io_req_set_res(req, ret, 0); 978f9ead18cSJens Axboe return IOU_OK; 979f9ead18cSJens Axboe } 980f9ead18cSJens Axboe 981f9ead18cSJens Axboe int io_connect_prep_async(struct io_kiocb *req) 982f9ead18cSJens Axboe { 983f9ead18cSJens Axboe struct io_async_connect *io = req->async_data; 984f9ead18cSJens Axboe struct io_connect *conn = io_kiocb_to_cmd(req); 985f9ead18cSJens Axboe 986f9ead18cSJens Axboe return move_addr_to_kernel(conn->addr, conn->addr_len, &io->address); 987f9ead18cSJens Axboe } 988f9ead18cSJens Axboe 989f9ead18cSJens Axboe int io_connect_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) 990f9ead18cSJens Axboe { 991f9ead18cSJens Axboe struct io_connect *conn = io_kiocb_to_cmd(req); 992f9ead18cSJens Axboe 993f9ead18cSJens Axboe if (sqe->len || sqe->buf_index || sqe->rw_flags || sqe->splice_fd_in) 994f9ead18cSJens Axboe return -EINVAL; 995f9ead18cSJens Axboe 996f9ead18cSJens Axboe conn->addr = u64_to_user_ptr(READ_ONCE(sqe->addr)); 997f9ead18cSJens Axboe conn->addr_len = READ_ONCE(sqe->addr2); 998f9ead18cSJens Axboe return 0; 999f9ead18cSJens Axboe } 1000f9ead18cSJens Axboe 1001f9ead18cSJens Axboe int io_connect(struct io_kiocb *req, unsigned int issue_flags) 1002f9ead18cSJens Axboe { 1003f9ead18cSJens Axboe struct io_connect *connect = io_kiocb_to_cmd(req); 1004f9ead18cSJens Axboe struct io_async_connect __io, *io; 1005f9ead18cSJens Axboe unsigned file_flags; 1006f9ead18cSJens Axboe int ret; 1007f9ead18cSJens Axboe bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK; 1008f9ead18cSJens Axboe 1009f9ead18cSJens Axboe if (req_has_async_data(req)) { 1010f9ead18cSJens Axboe io = req->async_data; 1011f9ead18cSJens Axboe } else { 1012f9ead18cSJens Axboe ret = move_addr_to_kernel(connect->addr, 1013f9ead18cSJens Axboe connect->addr_len, 1014f9ead18cSJens Axboe &__io.address); 1015f9ead18cSJens Axboe if (ret) 1016f9ead18cSJens Axboe goto out; 1017f9ead18cSJens Axboe io = &__io; 1018f9ead18cSJens Axboe } 1019f9ead18cSJens Axboe 1020f9ead18cSJens Axboe file_flags = force_nonblock ? O_NONBLOCK : 0; 1021f9ead18cSJens Axboe 1022f9ead18cSJens Axboe ret = __sys_connect_file(req->file, &io->address, 1023f9ead18cSJens Axboe connect->addr_len, file_flags); 1024f9ead18cSJens Axboe if ((ret == -EAGAIN || ret == -EINPROGRESS) && force_nonblock) { 1025f9ead18cSJens Axboe if (req_has_async_data(req)) 1026f9ead18cSJens Axboe return -EAGAIN; 1027f9ead18cSJens Axboe if (io_alloc_async_data(req)) { 1028f9ead18cSJens Axboe ret = -ENOMEM; 1029f9ead18cSJens Axboe goto out; 1030f9ead18cSJens Axboe } 1031f9ead18cSJens Axboe memcpy(req->async_data, &__io, sizeof(__io)); 1032f9ead18cSJens Axboe return -EAGAIN; 1033f9ead18cSJens Axboe } 1034f9ead18cSJens Axboe if (ret == -ERESTARTSYS) 1035f9ead18cSJens Axboe ret = -EINTR; 1036f9ead18cSJens Axboe out: 1037f9ead18cSJens Axboe if (ret < 0) 1038f9ead18cSJens Axboe req_set_fail(req); 1039f9ead18cSJens Axboe io_req_set_res(req, ret, 0); 1040f9ead18cSJens Axboe return IOU_OK; 1041f9ead18cSJens Axboe } 104243e0bbbdSJens Axboe 104343e0bbbdSJens Axboe void io_netmsg_cache_free(struct io_cache_entry *entry) 104443e0bbbdSJens Axboe { 104543e0bbbdSJens Axboe kfree(container_of(entry, struct io_async_msghdr, cache)); 104643e0bbbdSJens Axboe } 1047f9ead18cSJens Axboe #endif 1048