xref: /openbmc/linux/io_uring/net.c (revision 5702196e)
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"
15f9ead18cSJens Axboe #include "net.h"
16f9ead18cSJens Axboe 
17f9ead18cSJens Axboe #if defined(CONFIG_NET)
18f9ead18cSJens Axboe struct io_shutdown {
19f9ead18cSJens Axboe 	struct file			*file;
20f9ead18cSJens Axboe 	int				how;
21f9ead18cSJens Axboe };
22f9ead18cSJens Axboe 
23f9ead18cSJens Axboe struct io_accept {
24f9ead18cSJens Axboe 	struct file			*file;
25f9ead18cSJens Axboe 	struct sockaddr __user		*addr;
26f9ead18cSJens Axboe 	int __user			*addr_len;
27f9ead18cSJens Axboe 	int				flags;
28f9ead18cSJens Axboe 	u32				file_slot;
29f9ead18cSJens Axboe 	unsigned long			nofile;
30f9ead18cSJens Axboe };
31f9ead18cSJens Axboe 
32f9ead18cSJens Axboe struct io_socket {
33f9ead18cSJens Axboe 	struct file			*file;
34f9ead18cSJens Axboe 	int				domain;
35f9ead18cSJens Axboe 	int				type;
36f9ead18cSJens Axboe 	int				protocol;
37f9ead18cSJens Axboe 	int				flags;
38f9ead18cSJens Axboe 	u32				file_slot;
39f9ead18cSJens Axboe 	unsigned long			nofile;
40f9ead18cSJens Axboe };
41f9ead18cSJens Axboe 
42f9ead18cSJens Axboe struct io_connect {
43f9ead18cSJens Axboe 	struct file			*file;
44f9ead18cSJens Axboe 	struct sockaddr __user		*addr;
45f9ead18cSJens Axboe 	int				addr_len;
46f9ead18cSJens Axboe };
47f9ead18cSJens Axboe 
48f9ead18cSJens Axboe struct io_sr_msg {
49f9ead18cSJens Axboe 	struct file			*file;
50f9ead18cSJens Axboe 	union {
51f9ead18cSJens Axboe 		struct compat_msghdr __user	*umsg_compat;
52f9ead18cSJens Axboe 		struct user_msghdr __user	*umsg;
53f9ead18cSJens Axboe 		void __user			*buf;
54f9ead18cSJens Axboe 	};
55f9ead18cSJens Axboe 	int				msg_flags;
56f9ead18cSJens Axboe 	size_t				len;
57f9ead18cSJens Axboe 	size_t				done_io;
58f9ead18cSJens Axboe 	unsigned int			flags;
59f9ead18cSJens Axboe };
60f9ead18cSJens Axboe 
61f9ead18cSJens Axboe #define IO_APOLL_MULTI_POLLED (REQ_F_APOLL_MULTISHOT | REQ_F_POLLED)
62f9ead18cSJens Axboe 
63f9ead18cSJens Axboe int io_shutdown_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
64f9ead18cSJens Axboe {
65f9ead18cSJens Axboe 	struct io_shutdown *shutdown = io_kiocb_to_cmd(req);
66f9ead18cSJens Axboe 
67f9ead18cSJens Axboe 	if (unlikely(sqe->off || sqe->addr || sqe->rw_flags ||
68f9ead18cSJens Axboe 		     sqe->buf_index || sqe->splice_fd_in))
69f9ead18cSJens Axboe 		return -EINVAL;
70f9ead18cSJens Axboe 
71f9ead18cSJens Axboe 	shutdown->how = READ_ONCE(sqe->len);
72f9ead18cSJens Axboe 	return 0;
73f9ead18cSJens Axboe }
74f9ead18cSJens Axboe 
75f9ead18cSJens Axboe int io_shutdown(struct io_kiocb *req, unsigned int issue_flags)
76f9ead18cSJens Axboe {
77f9ead18cSJens Axboe 	struct io_shutdown *shutdown = io_kiocb_to_cmd(req);
78f9ead18cSJens Axboe 	struct socket *sock;
79f9ead18cSJens Axboe 	int ret;
80f9ead18cSJens Axboe 
81f9ead18cSJens Axboe 	if (issue_flags & IO_URING_F_NONBLOCK)
82f9ead18cSJens Axboe 		return -EAGAIN;
83f9ead18cSJens Axboe 
84f9ead18cSJens Axboe 	sock = sock_from_file(req->file);
85f9ead18cSJens Axboe 	if (unlikely(!sock))
86f9ead18cSJens Axboe 		return -ENOTSOCK;
87f9ead18cSJens Axboe 
88f9ead18cSJens Axboe 	ret = __sys_shutdown_sock(sock, shutdown->how);
89f9ead18cSJens Axboe 	io_req_set_res(req, ret, 0);
90f9ead18cSJens Axboe 	return IOU_OK;
91f9ead18cSJens Axboe }
92f9ead18cSJens Axboe 
93f9ead18cSJens Axboe static bool io_net_retry(struct socket *sock, int flags)
94f9ead18cSJens Axboe {
95f9ead18cSJens Axboe 	if (!(flags & MSG_WAITALL))
96f9ead18cSJens Axboe 		return false;
97f9ead18cSJens Axboe 	return sock->type == SOCK_STREAM || sock->type == SOCK_SEQPACKET;
98f9ead18cSJens Axboe }
99f9ead18cSJens Axboe 
100f9ead18cSJens Axboe static int io_setup_async_msg(struct io_kiocb *req,
101f9ead18cSJens Axboe 			      struct io_async_msghdr *kmsg)
102f9ead18cSJens Axboe {
103f9ead18cSJens Axboe 	struct io_async_msghdr *async_msg = req->async_data;
104f9ead18cSJens Axboe 
105f9ead18cSJens Axboe 	if (async_msg)
106f9ead18cSJens Axboe 		return -EAGAIN;
107f9ead18cSJens Axboe 	if (io_alloc_async_data(req)) {
108f9ead18cSJens Axboe 		kfree(kmsg->free_iov);
109f9ead18cSJens Axboe 		return -ENOMEM;
110f9ead18cSJens Axboe 	}
111f9ead18cSJens Axboe 	async_msg = req->async_data;
112f9ead18cSJens Axboe 	req->flags |= REQ_F_NEED_CLEANUP;
113f9ead18cSJens Axboe 	memcpy(async_msg, kmsg, sizeof(*kmsg));
114f9ead18cSJens Axboe 	async_msg->msg.msg_name = &async_msg->addr;
115f9ead18cSJens Axboe 	/* if were using fast_iov, set it to the new one */
116f9ead18cSJens Axboe 	if (!async_msg->free_iov)
117f9ead18cSJens Axboe 		async_msg->msg.msg_iter.iov = async_msg->fast_iov;
118f9ead18cSJens Axboe 
119f9ead18cSJens Axboe 	return -EAGAIN;
120f9ead18cSJens Axboe }
121f9ead18cSJens Axboe 
122f9ead18cSJens Axboe static int io_sendmsg_copy_hdr(struct io_kiocb *req,
123f9ead18cSJens Axboe 			       struct io_async_msghdr *iomsg)
124f9ead18cSJens Axboe {
125f9ead18cSJens Axboe 	struct io_sr_msg *sr = io_kiocb_to_cmd(req);
126f9ead18cSJens Axboe 
127f9ead18cSJens Axboe 	iomsg->msg.msg_name = &iomsg->addr;
128f9ead18cSJens Axboe 	iomsg->free_iov = iomsg->fast_iov;
129f9ead18cSJens Axboe 	return sendmsg_copy_msghdr(&iomsg->msg, sr->umsg, sr->msg_flags,
130f9ead18cSJens Axboe 					&iomsg->free_iov);
131f9ead18cSJens Axboe }
132f9ead18cSJens Axboe 
133f9ead18cSJens Axboe int io_sendmsg_prep_async(struct io_kiocb *req)
134f9ead18cSJens Axboe {
135f9ead18cSJens Axboe 	int ret;
136f9ead18cSJens Axboe 
137f9ead18cSJens Axboe 	ret = io_sendmsg_copy_hdr(req, req->async_data);
138f9ead18cSJens Axboe 	if (!ret)
139f9ead18cSJens Axboe 		req->flags |= REQ_F_NEED_CLEANUP;
140f9ead18cSJens Axboe 	return ret;
141f9ead18cSJens Axboe }
142f9ead18cSJens Axboe 
143f9ead18cSJens Axboe void io_sendmsg_recvmsg_cleanup(struct io_kiocb *req)
144f9ead18cSJens Axboe {
145f9ead18cSJens Axboe 	struct io_async_msghdr *io = req->async_data;
146f9ead18cSJens Axboe 
147f9ead18cSJens Axboe 	kfree(io->free_iov);
148f9ead18cSJens Axboe }
149f9ead18cSJens Axboe 
150f9ead18cSJens Axboe int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
151f9ead18cSJens Axboe {
152f9ead18cSJens Axboe 	struct io_sr_msg *sr = io_kiocb_to_cmd(req);
153f9ead18cSJens Axboe 
154f9ead18cSJens Axboe 	if (unlikely(sqe->file_index || sqe->addr2))
155f9ead18cSJens Axboe 		return -EINVAL;
156f9ead18cSJens Axboe 
157f9ead18cSJens Axboe 	sr->umsg = u64_to_user_ptr(READ_ONCE(sqe->addr));
158f9ead18cSJens Axboe 	sr->len = READ_ONCE(sqe->len);
159f9ead18cSJens Axboe 	sr->flags = READ_ONCE(sqe->ioprio);
160f9ead18cSJens Axboe 	if (sr->flags & ~IORING_RECVSEND_POLL_FIRST)
161f9ead18cSJens Axboe 		return -EINVAL;
162f9ead18cSJens Axboe 	sr->msg_flags = READ_ONCE(sqe->msg_flags) | MSG_NOSIGNAL;
163f9ead18cSJens Axboe 	if (sr->msg_flags & MSG_DONTWAIT)
164f9ead18cSJens Axboe 		req->flags |= REQ_F_NOWAIT;
165f9ead18cSJens Axboe 
166f9ead18cSJens Axboe #ifdef CONFIG_COMPAT
167f9ead18cSJens Axboe 	if (req->ctx->compat)
168f9ead18cSJens Axboe 		sr->msg_flags |= MSG_CMSG_COMPAT;
169f9ead18cSJens Axboe #endif
170f9ead18cSJens Axboe 	sr->done_io = 0;
171f9ead18cSJens Axboe 	return 0;
172f9ead18cSJens Axboe }
173f9ead18cSJens Axboe 
174f9ead18cSJens Axboe int io_sendmsg(struct io_kiocb *req, unsigned int issue_flags)
175f9ead18cSJens Axboe {
176f9ead18cSJens Axboe 	struct io_sr_msg *sr = io_kiocb_to_cmd(req);
177f9ead18cSJens Axboe 	struct io_async_msghdr iomsg, *kmsg;
178f9ead18cSJens Axboe 	struct socket *sock;
179f9ead18cSJens Axboe 	unsigned flags;
180f9ead18cSJens Axboe 	int min_ret = 0;
181f9ead18cSJens Axboe 	int ret;
182f9ead18cSJens Axboe 
183f9ead18cSJens Axboe 	sock = sock_from_file(req->file);
184f9ead18cSJens Axboe 	if (unlikely(!sock))
185f9ead18cSJens Axboe 		return -ENOTSOCK;
186f9ead18cSJens Axboe 
187f9ead18cSJens Axboe 	if (req_has_async_data(req)) {
188f9ead18cSJens Axboe 		kmsg = req->async_data;
189f9ead18cSJens Axboe 	} else {
190f9ead18cSJens Axboe 		ret = io_sendmsg_copy_hdr(req, &iomsg);
191f9ead18cSJens Axboe 		if (ret)
192f9ead18cSJens Axboe 			return ret;
193f9ead18cSJens Axboe 		kmsg = &iomsg;
194f9ead18cSJens Axboe 	}
195f9ead18cSJens Axboe 
196f9ead18cSJens Axboe 	if (!(req->flags & REQ_F_POLLED) &&
197f9ead18cSJens Axboe 	    (sr->flags & IORING_RECVSEND_POLL_FIRST))
198f9ead18cSJens Axboe 		return io_setup_async_msg(req, kmsg);
199f9ead18cSJens Axboe 
200f9ead18cSJens Axboe 	flags = sr->msg_flags;
201f9ead18cSJens Axboe 	if (issue_flags & IO_URING_F_NONBLOCK)
202f9ead18cSJens Axboe 		flags |= MSG_DONTWAIT;
203f9ead18cSJens Axboe 	if (flags & MSG_WAITALL)
204f9ead18cSJens Axboe 		min_ret = iov_iter_count(&kmsg->msg.msg_iter);
205f9ead18cSJens Axboe 
206f9ead18cSJens Axboe 	ret = __sys_sendmsg_sock(sock, &kmsg->msg, flags);
207f9ead18cSJens Axboe 
208f9ead18cSJens Axboe 	if (ret < min_ret) {
209f9ead18cSJens Axboe 		if (ret == -EAGAIN && (issue_flags & IO_URING_F_NONBLOCK))
210f9ead18cSJens Axboe 			return io_setup_async_msg(req, kmsg);
211f9ead18cSJens Axboe 		if (ret == -ERESTARTSYS)
212f9ead18cSJens Axboe 			ret = -EINTR;
213f9ead18cSJens Axboe 		if (ret > 0 && io_net_retry(sock, flags)) {
214f9ead18cSJens Axboe 			sr->done_io += ret;
215f9ead18cSJens Axboe 			req->flags |= REQ_F_PARTIAL_IO;
216f9ead18cSJens Axboe 			return io_setup_async_msg(req, kmsg);
217f9ead18cSJens Axboe 		}
218f9ead18cSJens Axboe 		req_set_fail(req);
219f9ead18cSJens Axboe 	}
220f9ead18cSJens Axboe 	/* fast path, check for non-NULL to avoid function call */
221f9ead18cSJens Axboe 	if (kmsg->free_iov)
222f9ead18cSJens Axboe 		kfree(kmsg->free_iov);
223f9ead18cSJens Axboe 	req->flags &= ~REQ_F_NEED_CLEANUP;
224f9ead18cSJens Axboe 	if (ret >= 0)
225f9ead18cSJens Axboe 		ret += sr->done_io;
226f9ead18cSJens Axboe 	else if (sr->done_io)
227f9ead18cSJens Axboe 		ret = sr->done_io;
228f9ead18cSJens Axboe 	io_req_set_res(req, ret, 0);
229f9ead18cSJens Axboe 	return IOU_OK;
230f9ead18cSJens Axboe }
231f9ead18cSJens Axboe 
232f9ead18cSJens Axboe int io_send(struct io_kiocb *req, unsigned int issue_flags)
233f9ead18cSJens Axboe {
234f9ead18cSJens Axboe 	struct io_sr_msg *sr = io_kiocb_to_cmd(req);
235f9ead18cSJens Axboe 	struct msghdr msg;
236f9ead18cSJens Axboe 	struct iovec iov;
237f9ead18cSJens Axboe 	struct socket *sock;
238f9ead18cSJens Axboe 	unsigned flags;
239f9ead18cSJens Axboe 	int min_ret = 0;
240f9ead18cSJens Axboe 	int ret;
241f9ead18cSJens Axboe 
242f9ead18cSJens Axboe 	if (!(req->flags & REQ_F_POLLED) &&
243f9ead18cSJens Axboe 	    (sr->flags & IORING_RECVSEND_POLL_FIRST))
244f9ead18cSJens Axboe 		return -EAGAIN;
245f9ead18cSJens Axboe 
246f9ead18cSJens Axboe 	sock = sock_from_file(req->file);
247f9ead18cSJens Axboe 	if (unlikely(!sock))
248f9ead18cSJens Axboe 		return -ENOTSOCK;
249f9ead18cSJens Axboe 
250f9ead18cSJens Axboe 	ret = import_single_range(WRITE, sr->buf, sr->len, &iov, &msg.msg_iter);
251f9ead18cSJens Axboe 	if (unlikely(ret))
252f9ead18cSJens Axboe 		return ret;
253f9ead18cSJens Axboe 
254f9ead18cSJens Axboe 	msg.msg_name = NULL;
255f9ead18cSJens Axboe 	msg.msg_control = NULL;
256f9ead18cSJens Axboe 	msg.msg_controllen = 0;
257f9ead18cSJens Axboe 	msg.msg_namelen = 0;
258f9ead18cSJens Axboe 
259f9ead18cSJens Axboe 	flags = sr->msg_flags;
260f9ead18cSJens Axboe 	if (issue_flags & IO_URING_F_NONBLOCK)
261f9ead18cSJens Axboe 		flags |= MSG_DONTWAIT;
262f9ead18cSJens Axboe 	if (flags & MSG_WAITALL)
263f9ead18cSJens Axboe 		min_ret = iov_iter_count(&msg.msg_iter);
264f9ead18cSJens Axboe 
265f9ead18cSJens Axboe 	msg.msg_flags = flags;
266f9ead18cSJens Axboe 	ret = sock_sendmsg(sock, &msg);
267f9ead18cSJens Axboe 	if (ret < min_ret) {
268f9ead18cSJens Axboe 		if (ret == -EAGAIN && (issue_flags & IO_URING_F_NONBLOCK))
269f9ead18cSJens Axboe 			return -EAGAIN;
270f9ead18cSJens Axboe 		if (ret == -ERESTARTSYS)
271f9ead18cSJens Axboe 			ret = -EINTR;
272f9ead18cSJens Axboe 		if (ret > 0 && io_net_retry(sock, flags)) {
273f9ead18cSJens Axboe 			sr->len -= ret;
274f9ead18cSJens Axboe 			sr->buf += ret;
275f9ead18cSJens Axboe 			sr->done_io += ret;
276f9ead18cSJens Axboe 			req->flags |= REQ_F_PARTIAL_IO;
277f9ead18cSJens Axboe 			return -EAGAIN;
278f9ead18cSJens Axboe 		}
279f9ead18cSJens Axboe 		req_set_fail(req);
280f9ead18cSJens Axboe 	}
281f9ead18cSJens Axboe 	if (ret >= 0)
282f9ead18cSJens Axboe 		ret += sr->done_io;
283f9ead18cSJens Axboe 	else if (sr->done_io)
284f9ead18cSJens Axboe 		ret = sr->done_io;
285f9ead18cSJens Axboe 	io_req_set_res(req, ret, 0);
286f9ead18cSJens Axboe 	return IOU_OK;
287f9ead18cSJens Axboe }
288f9ead18cSJens Axboe 
289f9ead18cSJens Axboe static int __io_recvmsg_copy_hdr(struct io_kiocb *req,
290f9ead18cSJens Axboe 				 struct io_async_msghdr *iomsg)
291f9ead18cSJens Axboe {
292f9ead18cSJens Axboe 	struct io_sr_msg *sr = io_kiocb_to_cmd(req);
293f9ead18cSJens Axboe 	struct iovec __user *uiov;
294f9ead18cSJens Axboe 	size_t iov_len;
295f9ead18cSJens Axboe 	int ret;
296f9ead18cSJens Axboe 
297f9ead18cSJens Axboe 	ret = __copy_msghdr_from_user(&iomsg->msg, sr->umsg,
298f9ead18cSJens Axboe 					&iomsg->uaddr, &uiov, &iov_len);
299f9ead18cSJens Axboe 	if (ret)
300f9ead18cSJens Axboe 		return ret;
301f9ead18cSJens Axboe 
302f9ead18cSJens Axboe 	if (req->flags & REQ_F_BUFFER_SELECT) {
303*5702196eSDylan Yudaken 		if (iov_len == 0) {
304*5702196eSDylan Yudaken 			sr->len = iomsg->fast_iov[0].iov_len = 0;
305*5702196eSDylan Yudaken 			iomsg->fast_iov[0].iov_base = NULL;
306*5702196eSDylan Yudaken 			iomsg->free_iov = NULL;
307*5702196eSDylan Yudaken 		} else if (iov_len > 1) {
308f9ead18cSJens Axboe 			return -EINVAL;
309*5702196eSDylan Yudaken 		} else {
310f9ead18cSJens Axboe 			if (copy_from_user(iomsg->fast_iov, uiov, sizeof(*uiov)))
311f9ead18cSJens Axboe 				return -EFAULT;
312f9ead18cSJens Axboe 			sr->len = iomsg->fast_iov[0].iov_len;
313f9ead18cSJens Axboe 			iomsg->free_iov = NULL;
314*5702196eSDylan Yudaken 		}
315f9ead18cSJens Axboe 	} else {
316f9ead18cSJens Axboe 		iomsg->free_iov = iomsg->fast_iov;
317f9ead18cSJens Axboe 		ret = __import_iovec(READ, uiov, iov_len, UIO_FASTIOV,
318f9ead18cSJens Axboe 				     &iomsg->free_iov, &iomsg->msg.msg_iter,
319f9ead18cSJens Axboe 				     false);
320f9ead18cSJens Axboe 		if (ret > 0)
321f9ead18cSJens Axboe 			ret = 0;
322f9ead18cSJens Axboe 	}
323f9ead18cSJens Axboe 
324f9ead18cSJens Axboe 	return ret;
325f9ead18cSJens Axboe }
326f9ead18cSJens Axboe 
327f9ead18cSJens Axboe #ifdef CONFIG_COMPAT
328f9ead18cSJens Axboe static int __io_compat_recvmsg_copy_hdr(struct io_kiocb *req,
329f9ead18cSJens Axboe 					struct io_async_msghdr *iomsg)
330f9ead18cSJens Axboe {
331f9ead18cSJens Axboe 	struct io_sr_msg *sr = io_kiocb_to_cmd(req);
332f9ead18cSJens Axboe 	struct compat_iovec __user *uiov;
333f9ead18cSJens Axboe 	compat_uptr_t ptr;
334f9ead18cSJens Axboe 	compat_size_t len;
335f9ead18cSJens Axboe 	int ret;
336f9ead18cSJens Axboe 
337f9ead18cSJens Axboe 	ret = __get_compat_msghdr(&iomsg->msg, sr->umsg_compat, &iomsg->uaddr,
338f9ead18cSJens Axboe 				  &ptr, &len);
339f9ead18cSJens Axboe 	if (ret)
340f9ead18cSJens Axboe 		return ret;
341f9ead18cSJens Axboe 
342f9ead18cSJens Axboe 	uiov = compat_ptr(ptr);
343f9ead18cSJens Axboe 	if (req->flags & REQ_F_BUFFER_SELECT) {
344f9ead18cSJens Axboe 		compat_ssize_t clen;
345f9ead18cSJens Axboe 
346f9ead18cSJens Axboe 		if (len > 1)
347f9ead18cSJens Axboe 			return -EINVAL;
348f9ead18cSJens Axboe 		if (!access_ok(uiov, sizeof(*uiov)))
349f9ead18cSJens Axboe 			return -EFAULT;
350f9ead18cSJens Axboe 		if (__get_user(clen, &uiov->iov_len))
351f9ead18cSJens Axboe 			return -EFAULT;
352f9ead18cSJens Axboe 		if (clen < 0)
353f9ead18cSJens Axboe 			return -EINVAL;
354f9ead18cSJens Axboe 		sr->len = clen;
355f9ead18cSJens Axboe 		iomsg->free_iov = NULL;
356f9ead18cSJens Axboe 	} else {
357f9ead18cSJens Axboe 		iomsg->free_iov = iomsg->fast_iov;
358f9ead18cSJens Axboe 		ret = __import_iovec(READ, (struct iovec __user *)uiov, len,
359f9ead18cSJens Axboe 				   UIO_FASTIOV, &iomsg->free_iov,
360f9ead18cSJens Axboe 				   &iomsg->msg.msg_iter, true);
361f9ead18cSJens Axboe 		if (ret < 0)
362f9ead18cSJens Axboe 			return ret;
363f9ead18cSJens Axboe 	}
364f9ead18cSJens Axboe 
365f9ead18cSJens Axboe 	return 0;
366f9ead18cSJens Axboe }
367f9ead18cSJens Axboe #endif
368f9ead18cSJens Axboe 
369f9ead18cSJens Axboe static int io_recvmsg_copy_hdr(struct io_kiocb *req,
370f9ead18cSJens Axboe 			       struct io_async_msghdr *iomsg)
371f9ead18cSJens Axboe {
372f9ead18cSJens Axboe 	iomsg->msg.msg_name = &iomsg->addr;
373f9ead18cSJens Axboe 
374f9ead18cSJens Axboe #ifdef CONFIG_COMPAT
375f9ead18cSJens Axboe 	if (req->ctx->compat)
376f9ead18cSJens Axboe 		return __io_compat_recvmsg_copy_hdr(req, iomsg);
377f9ead18cSJens Axboe #endif
378f9ead18cSJens Axboe 
379f9ead18cSJens Axboe 	return __io_recvmsg_copy_hdr(req, iomsg);
380f9ead18cSJens Axboe }
381f9ead18cSJens Axboe 
382f9ead18cSJens Axboe int io_recvmsg_prep_async(struct io_kiocb *req)
383f9ead18cSJens Axboe {
384f9ead18cSJens Axboe 	int ret;
385f9ead18cSJens Axboe 
386f9ead18cSJens Axboe 	ret = io_recvmsg_copy_hdr(req, req->async_data);
387f9ead18cSJens Axboe 	if (!ret)
388f9ead18cSJens Axboe 		req->flags |= REQ_F_NEED_CLEANUP;
389f9ead18cSJens Axboe 	return ret;
390f9ead18cSJens Axboe }
391f9ead18cSJens Axboe 
392f9ead18cSJens Axboe int io_recvmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
393f9ead18cSJens Axboe {
394f9ead18cSJens Axboe 	struct io_sr_msg *sr = io_kiocb_to_cmd(req);
395f9ead18cSJens Axboe 
396f9ead18cSJens Axboe 	if (unlikely(sqe->file_index || sqe->addr2))
397f9ead18cSJens Axboe 		return -EINVAL;
398f9ead18cSJens Axboe 
399f9ead18cSJens Axboe 	sr->umsg = u64_to_user_ptr(READ_ONCE(sqe->addr));
400f9ead18cSJens Axboe 	sr->len = READ_ONCE(sqe->len);
401f9ead18cSJens Axboe 	sr->flags = READ_ONCE(sqe->ioprio);
402f9ead18cSJens Axboe 	if (sr->flags & ~IORING_RECVSEND_POLL_FIRST)
403f9ead18cSJens Axboe 		return -EINVAL;
404f9ead18cSJens Axboe 	sr->msg_flags = READ_ONCE(sqe->msg_flags) | MSG_NOSIGNAL;
405f9ead18cSJens Axboe 	if (sr->msg_flags & MSG_DONTWAIT)
406f9ead18cSJens Axboe 		req->flags |= REQ_F_NOWAIT;
407f9ead18cSJens Axboe 	if (sr->msg_flags & MSG_ERRQUEUE)
408f9ead18cSJens Axboe 		req->flags |= REQ_F_CLEAR_POLLIN;
409f9ead18cSJens Axboe 
410f9ead18cSJens Axboe #ifdef CONFIG_COMPAT
411f9ead18cSJens Axboe 	if (req->ctx->compat)
412f9ead18cSJens Axboe 		sr->msg_flags |= MSG_CMSG_COMPAT;
413f9ead18cSJens Axboe #endif
414f9ead18cSJens Axboe 	sr->done_io = 0;
415f9ead18cSJens Axboe 	return 0;
416f9ead18cSJens Axboe }
417f9ead18cSJens Axboe 
418f9ead18cSJens Axboe int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
419f9ead18cSJens Axboe {
420f9ead18cSJens Axboe 	struct io_sr_msg *sr = io_kiocb_to_cmd(req);
421f9ead18cSJens Axboe 	struct io_async_msghdr iomsg, *kmsg;
422f9ead18cSJens Axboe 	struct socket *sock;
423f9ead18cSJens Axboe 	unsigned int cflags;
424f9ead18cSJens Axboe 	unsigned flags;
425f9ead18cSJens Axboe 	int ret, min_ret = 0;
426f9ead18cSJens Axboe 	bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
427f9ead18cSJens Axboe 
428f9ead18cSJens Axboe 	sock = sock_from_file(req->file);
429f9ead18cSJens Axboe 	if (unlikely(!sock))
430f9ead18cSJens Axboe 		return -ENOTSOCK;
431f9ead18cSJens Axboe 
432f9ead18cSJens Axboe 	if (req_has_async_data(req)) {
433f9ead18cSJens Axboe 		kmsg = req->async_data;
434f9ead18cSJens Axboe 	} else {
435f9ead18cSJens Axboe 		ret = io_recvmsg_copy_hdr(req, &iomsg);
436f9ead18cSJens Axboe 		if (ret)
437f9ead18cSJens Axboe 			return ret;
438f9ead18cSJens Axboe 		kmsg = &iomsg;
439f9ead18cSJens Axboe 	}
440f9ead18cSJens Axboe 
441f9ead18cSJens Axboe 	if (!(req->flags & REQ_F_POLLED) &&
442f9ead18cSJens Axboe 	    (sr->flags & IORING_RECVSEND_POLL_FIRST))
443f9ead18cSJens Axboe 		return io_setup_async_msg(req, kmsg);
444f9ead18cSJens Axboe 
445f9ead18cSJens Axboe 	if (io_do_buffer_select(req)) {
446f9ead18cSJens Axboe 		void __user *buf;
447f9ead18cSJens Axboe 
448f9ead18cSJens Axboe 		buf = io_buffer_select(req, &sr->len, issue_flags);
449f9ead18cSJens Axboe 		if (!buf)
450f9ead18cSJens Axboe 			return -ENOBUFS;
451f9ead18cSJens Axboe 		kmsg->fast_iov[0].iov_base = buf;
452f9ead18cSJens Axboe 		kmsg->fast_iov[0].iov_len = sr->len;
453f9ead18cSJens Axboe 		iov_iter_init(&kmsg->msg.msg_iter, READ, kmsg->fast_iov, 1,
454f9ead18cSJens Axboe 				sr->len);
455f9ead18cSJens Axboe 	}
456f9ead18cSJens Axboe 
457f9ead18cSJens Axboe 	flags = sr->msg_flags;
458f9ead18cSJens Axboe 	if (force_nonblock)
459f9ead18cSJens Axboe 		flags |= MSG_DONTWAIT;
460f9ead18cSJens Axboe 	if (flags & MSG_WAITALL)
461f9ead18cSJens Axboe 		min_ret = iov_iter_count(&kmsg->msg.msg_iter);
462f9ead18cSJens Axboe 
463f9ead18cSJens Axboe 	kmsg->msg.msg_get_inq = 1;
464f9ead18cSJens Axboe 	ret = __sys_recvmsg_sock(sock, &kmsg->msg, sr->umsg, kmsg->uaddr, flags);
465f9ead18cSJens Axboe 	if (ret < min_ret) {
466f9ead18cSJens Axboe 		if (ret == -EAGAIN && force_nonblock)
467f9ead18cSJens Axboe 			return io_setup_async_msg(req, kmsg);
468f9ead18cSJens Axboe 		if (ret == -ERESTARTSYS)
469f9ead18cSJens Axboe 			ret = -EINTR;
470f9ead18cSJens Axboe 		if (ret > 0 && io_net_retry(sock, flags)) {
471f9ead18cSJens Axboe 			sr->done_io += ret;
472f9ead18cSJens Axboe 			req->flags |= REQ_F_PARTIAL_IO;
473f9ead18cSJens Axboe 			return io_setup_async_msg(req, kmsg);
474f9ead18cSJens Axboe 		}
475f9ead18cSJens Axboe 		req_set_fail(req);
476f9ead18cSJens Axboe 	} else if ((flags & MSG_WAITALL) && (kmsg->msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC))) {
477f9ead18cSJens Axboe 		req_set_fail(req);
478f9ead18cSJens Axboe 	}
479f9ead18cSJens Axboe 
480f9ead18cSJens Axboe 	/* fast path, check for non-NULL to avoid function call */
481f9ead18cSJens Axboe 	if (kmsg->free_iov)
482f9ead18cSJens Axboe 		kfree(kmsg->free_iov);
483f9ead18cSJens Axboe 	req->flags &= ~REQ_F_NEED_CLEANUP;
484f9ead18cSJens Axboe 	if (ret >= 0)
485f9ead18cSJens Axboe 		ret += sr->done_io;
486f9ead18cSJens Axboe 	else if (sr->done_io)
487f9ead18cSJens Axboe 		ret = sr->done_io;
488f9ead18cSJens Axboe 	cflags = io_put_kbuf(req, issue_flags);
489f9ead18cSJens Axboe 	if (kmsg->msg.msg_inq)
490f9ead18cSJens Axboe 		cflags |= IORING_CQE_F_SOCK_NONEMPTY;
491f9ead18cSJens Axboe 	io_req_set_res(req, ret, cflags);
492f9ead18cSJens Axboe 	return IOU_OK;
493f9ead18cSJens Axboe }
494f9ead18cSJens Axboe 
495f9ead18cSJens Axboe int io_recv(struct io_kiocb *req, unsigned int issue_flags)
496f9ead18cSJens Axboe {
497f9ead18cSJens Axboe 	struct io_sr_msg *sr = io_kiocb_to_cmd(req);
498f9ead18cSJens Axboe 	struct msghdr msg;
499f9ead18cSJens Axboe 	struct socket *sock;
500f9ead18cSJens Axboe 	struct iovec iov;
501f9ead18cSJens Axboe 	unsigned int cflags;
502f9ead18cSJens Axboe 	unsigned flags;
503f9ead18cSJens Axboe 	int ret, min_ret = 0;
504f9ead18cSJens Axboe 	bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
505f9ead18cSJens Axboe 
506f9ead18cSJens Axboe 	if (!(req->flags & REQ_F_POLLED) &&
507f9ead18cSJens Axboe 	    (sr->flags & IORING_RECVSEND_POLL_FIRST))
508f9ead18cSJens Axboe 		return -EAGAIN;
509f9ead18cSJens Axboe 
510f9ead18cSJens Axboe 	sock = sock_from_file(req->file);
511f9ead18cSJens Axboe 	if (unlikely(!sock))
512f9ead18cSJens Axboe 		return -ENOTSOCK;
513f9ead18cSJens Axboe 
514f9ead18cSJens Axboe 	if (io_do_buffer_select(req)) {
515f9ead18cSJens Axboe 		void __user *buf;
516f9ead18cSJens Axboe 
517f9ead18cSJens Axboe 		buf = io_buffer_select(req, &sr->len, issue_flags);
518f9ead18cSJens Axboe 		if (!buf)
519f9ead18cSJens Axboe 			return -ENOBUFS;
520f9ead18cSJens Axboe 		sr->buf = buf;
521f9ead18cSJens Axboe 	}
522f9ead18cSJens Axboe 
523f9ead18cSJens Axboe 	ret = import_single_range(READ, sr->buf, sr->len, &iov, &msg.msg_iter);
524f9ead18cSJens Axboe 	if (unlikely(ret))
525f9ead18cSJens Axboe 		goto out_free;
526f9ead18cSJens Axboe 
527f9ead18cSJens Axboe 	msg.msg_name = NULL;
528f9ead18cSJens Axboe 	msg.msg_namelen = 0;
529f9ead18cSJens Axboe 	msg.msg_control = NULL;
530f9ead18cSJens Axboe 	msg.msg_get_inq = 1;
531f9ead18cSJens Axboe 	msg.msg_flags = 0;
532f9ead18cSJens Axboe 	msg.msg_controllen = 0;
533f9ead18cSJens Axboe 	msg.msg_iocb = NULL;
534f9ead18cSJens Axboe 
535f9ead18cSJens Axboe 	flags = sr->msg_flags;
536f9ead18cSJens Axboe 	if (force_nonblock)
537f9ead18cSJens Axboe 		flags |= MSG_DONTWAIT;
538f9ead18cSJens Axboe 	if (flags & MSG_WAITALL)
539f9ead18cSJens Axboe 		min_ret = iov_iter_count(&msg.msg_iter);
540f9ead18cSJens Axboe 
541f9ead18cSJens Axboe 	ret = sock_recvmsg(sock, &msg, flags);
542f9ead18cSJens Axboe 	if (ret < min_ret) {
543f9ead18cSJens Axboe 		if (ret == -EAGAIN && force_nonblock)
544f9ead18cSJens Axboe 			return -EAGAIN;
545f9ead18cSJens Axboe 		if (ret == -ERESTARTSYS)
546f9ead18cSJens Axboe 			ret = -EINTR;
547f9ead18cSJens Axboe 		if (ret > 0 && io_net_retry(sock, flags)) {
548f9ead18cSJens Axboe 			sr->len -= ret;
549f9ead18cSJens Axboe 			sr->buf += ret;
550f9ead18cSJens Axboe 			sr->done_io += ret;
551f9ead18cSJens Axboe 			req->flags |= REQ_F_PARTIAL_IO;
552f9ead18cSJens Axboe 			return -EAGAIN;
553f9ead18cSJens Axboe 		}
554f9ead18cSJens Axboe 		req_set_fail(req);
555f9ead18cSJens Axboe 	} else if ((flags & MSG_WAITALL) && (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC))) {
556f9ead18cSJens Axboe out_free:
557f9ead18cSJens Axboe 		req_set_fail(req);
558f9ead18cSJens Axboe 	}
559f9ead18cSJens Axboe 
560f9ead18cSJens Axboe 	if (ret >= 0)
561f9ead18cSJens Axboe 		ret += sr->done_io;
562f9ead18cSJens Axboe 	else if (sr->done_io)
563f9ead18cSJens Axboe 		ret = sr->done_io;
564f9ead18cSJens Axboe 	cflags = io_put_kbuf(req, issue_flags);
565f9ead18cSJens Axboe 	if (msg.msg_inq)
566f9ead18cSJens Axboe 		cflags |= IORING_CQE_F_SOCK_NONEMPTY;
567f9ead18cSJens Axboe 	io_req_set_res(req, ret, cflags);
568f9ead18cSJens Axboe 	return IOU_OK;
569f9ead18cSJens Axboe }
570f9ead18cSJens Axboe 
571f9ead18cSJens Axboe int io_accept_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
572f9ead18cSJens Axboe {
573f9ead18cSJens Axboe 	struct io_accept *accept = io_kiocb_to_cmd(req);
574f9ead18cSJens Axboe 	unsigned flags;
575f9ead18cSJens Axboe 
576f9ead18cSJens Axboe 	if (sqe->len || sqe->buf_index)
577f9ead18cSJens Axboe 		return -EINVAL;
578f9ead18cSJens Axboe 
579f9ead18cSJens Axboe 	accept->addr = u64_to_user_ptr(READ_ONCE(sqe->addr));
580f9ead18cSJens Axboe 	accept->addr_len = u64_to_user_ptr(READ_ONCE(sqe->addr2));
581f9ead18cSJens Axboe 	accept->flags = READ_ONCE(sqe->accept_flags);
582f9ead18cSJens Axboe 	accept->nofile = rlimit(RLIMIT_NOFILE);
583f9ead18cSJens Axboe 	flags = READ_ONCE(sqe->ioprio);
584f9ead18cSJens Axboe 	if (flags & ~IORING_ACCEPT_MULTISHOT)
585f9ead18cSJens Axboe 		return -EINVAL;
586f9ead18cSJens Axboe 
587f9ead18cSJens Axboe 	accept->file_slot = READ_ONCE(sqe->file_index);
588f9ead18cSJens Axboe 	if (accept->file_slot) {
589f9ead18cSJens Axboe 		if (accept->flags & SOCK_CLOEXEC)
590f9ead18cSJens Axboe 			return -EINVAL;
591f9ead18cSJens Axboe 		if (flags & IORING_ACCEPT_MULTISHOT &&
592f9ead18cSJens Axboe 		    accept->file_slot != IORING_FILE_INDEX_ALLOC)
593f9ead18cSJens Axboe 			return -EINVAL;
594f9ead18cSJens Axboe 	}
595f9ead18cSJens Axboe 	if (accept->flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
596f9ead18cSJens Axboe 		return -EINVAL;
597f9ead18cSJens Axboe 	if (SOCK_NONBLOCK != O_NONBLOCK && (accept->flags & SOCK_NONBLOCK))
598f9ead18cSJens Axboe 		accept->flags = (accept->flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
599f9ead18cSJens Axboe 	if (flags & IORING_ACCEPT_MULTISHOT)
600f9ead18cSJens Axboe 		req->flags |= REQ_F_APOLL_MULTISHOT;
601f9ead18cSJens Axboe 	return 0;
602f9ead18cSJens Axboe }
603f9ead18cSJens Axboe 
604f9ead18cSJens Axboe int io_accept(struct io_kiocb *req, unsigned int issue_flags)
605f9ead18cSJens Axboe {
606f9ead18cSJens Axboe 	struct io_ring_ctx *ctx = req->ctx;
607f9ead18cSJens Axboe 	struct io_accept *accept = io_kiocb_to_cmd(req);
608f9ead18cSJens Axboe 	bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
609f9ead18cSJens Axboe 	unsigned int file_flags = force_nonblock ? O_NONBLOCK : 0;
610f9ead18cSJens Axboe 	bool fixed = !!accept->file_slot;
611f9ead18cSJens Axboe 	struct file *file;
612f9ead18cSJens Axboe 	int ret, fd;
613f9ead18cSJens Axboe 
614f9ead18cSJens Axboe retry:
615f9ead18cSJens Axboe 	if (!fixed) {
616f9ead18cSJens Axboe 		fd = __get_unused_fd_flags(accept->flags, accept->nofile);
617f9ead18cSJens Axboe 		if (unlikely(fd < 0))
618f9ead18cSJens Axboe 			return fd;
619f9ead18cSJens Axboe 	}
620f9ead18cSJens Axboe 	file = do_accept(req->file, file_flags, accept->addr, accept->addr_len,
621f9ead18cSJens Axboe 			 accept->flags);
622f9ead18cSJens Axboe 	if (IS_ERR(file)) {
623f9ead18cSJens Axboe 		if (!fixed)
624f9ead18cSJens Axboe 			put_unused_fd(fd);
625f9ead18cSJens Axboe 		ret = PTR_ERR(file);
626f9ead18cSJens Axboe 		if (ret == -EAGAIN && force_nonblock) {
627f9ead18cSJens Axboe 			/*
628f9ead18cSJens Axboe 			 * if it's multishot and polled, we don't need to
629f9ead18cSJens Axboe 			 * return EAGAIN to arm the poll infra since it
630f9ead18cSJens Axboe 			 * has already been done
631f9ead18cSJens Axboe 			 */
632f9ead18cSJens Axboe 			if ((req->flags & IO_APOLL_MULTI_POLLED) ==
633f9ead18cSJens Axboe 			    IO_APOLL_MULTI_POLLED)
634f9ead18cSJens Axboe 				ret = IOU_ISSUE_SKIP_COMPLETE;
635f9ead18cSJens Axboe 			return ret;
636f9ead18cSJens Axboe 		}
637f9ead18cSJens Axboe 		if (ret == -ERESTARTSYS)
638f9ead18cSJens Axboe 			ret = -EINTR;
639f9ead18cSJens Axboe 		req_set_fail(req);
640f9ead18cSJens Axboe 	} else if (!fixed) {
641f9ead18cSJens Axboe 		fd_install(fd, file);
642f9ead18cSJens Axboe 		ret = fd;
643f9ead18cSJens Axboe 	} else {
644f9ead18cSJens Axboe 		ret = io_fixed_fd_install(req, issue_flags, file,
645f9ead18cSJens Axboe 						accept->file_slot);
646f9ead18cSJens Axboe 	}
647f9ead18cSJens Axboe 
648f9ead18cSJens Axboe 	if (!(req->flags & REQ_F_APOLL_MULTISHOT)) {
649f9ead18cSJens Axboe 		io_req_set_res(req, ret, 0);
650f9ead18cSJens Axboe 		return IOU_OK;
651f9ead18cSJens Axboe 	}
652f9ead18cSJens Axboe 
653d245bca6SPavel Begunkov 	if (ret < 0)
654f9ead18cSJens Axboe 		return ret;
655d245bca6SPavel Begunkov 	if (io_post_aux_cqe(ctx, req->cqe.user_data, ret, IORING_CQE_F_MORE))
656d245bca6SPavel Begunkov 		goto retry;
657d245bca6SPavel Begunkov 	return -ECANCELED;
658f9ead18cSJens Axboe }
659f9ead18cSJens Axboe 
660f9ead18cSJens Axboe int io_socket_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
661f9ead18cSJens Axboe {
662f9ead18cSJens Axboe 	struct io_socket *sock = io_kiocb_to_cmd(req);
663f9ead18cSJens Axboe 
664f9ead18cSJens Axboe 	if (sqe->addr || sqe->rw_flags || sqe->buf_index)
665f9ead18cSJens Axboe 		return -EINVAL;
666f9ead18cSJens Axboe 
667f9ead18cSJens Axboe 	sock->domain = READ_ONCE(sqe->fd);
668f9ead18cSJens Axboe 	sock->type = READ_ONCE(sqe->off);
669f9ead18cSJens Axboe 	sock->protocol = READ_ONCE(sqe->len);
670f9ead18cSJens Axboe 	sock->file_slot = READ_ONCE(sqe->file_index);
671f9ead18cSJens Axboe 	sock->nofile = rlimit(RLIMIT_NOFILE);
672f9ead18cSJens Axboe 
673f9ead18cSJens Axboe 	sock->flags = sock->type & ~SOCK_TYPE_MASK;
674f9ead18cSJens Axboe 	if (sock->file_slot && (sock->flags & SOCK_CLOEXEC))
675f9ead18cSJens Axboe 		return -EINVAL;
676f9ead18cSJens Axboe 	if (sock->flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
677f9ead18cSJens Axboe 		return -EINVAL;
678f9ead18cSJens Axboe 	return 0;
679f9ead18cSJens Axboe }
680f9ead18cSJens Axboe 
681f9ead18cSJens Axboe int io_socket(struct io_kiocb *req, unsigned int issue_flags)
682f9ead18cSJens Axboe {
683f9ead18cSJens Axboe 	struct io_socket *sock = io_kiocb_to_cmd(req);
684f9ead18cSJens Axboe 	bool fixed = !!sock->file_slot;
685f9ead18cSJens Axboe 	struct file *file;
686f9ead18cSJens Axboe 	int ret, fd;
687f9ead18cSJens Axboe 
688f9ead18cSJens Axboe 	if (!fixed) {
689f9ead18cSJens Axboe 		fd = __get_unused_fd_flags(sock->flags, sock->nofile);
690f9ead18cSJens Axboe 		if (unlikely(fd < 0))
691f9ead18cSJens Axboe 			return fd;
692f9ead18cSJens Axboe 	}
693f9ead18cSJens Axboe 	file = __sys_socket_file(sock->domain, sock->type, sock->protocol);
694f9ead18cSJens Axboe 	if (IS_ERR(file)) {
695f9ead18cSJens Axboe 		if (!fixed)
696f9ead18cSJens Axboe 			put_unused_fd(fd);
697f9ead18cSJens Axboe 		ret = PTR_ERR(file);
698f9ead18cSJens Axboe 		if (ret == -EAGAIN && (issue_flags & IO_URING_F_NONBLOCK))
699f9ead18cSJens Axboe 			return -EAGAIN;
700f9ead18cSJens Axboe 		if (ret == -ERESTARTSYS)
701f9ead18cSJens Axboe 			ret = -EINTR;
702f9ead18cSJens Axboe 		req_set_fail(req);
703f9ead18cSJens Axboe 	} else if (!fixed) {
704f9ead18cSJens Axboe 		fd_install(fd, file);
705f9ead18cSJens Axboe 		ret = fd;
706f9ead18cSJens Axboe 	} else {
707f9ead18cSJens Axboe 		ret = io_fixed_fd_install(req, issue_flags, file,
708f9ead18cSJens Axboe 					    sock->file_slot);
709f9ead18cSJens Axboe 	}
710f9ead18cSJens Axboe 	io_req_set_res(req, ret, 0);
711f9ead18cSJens Axboe 	return IOU_OK;
712f9ead18cSJens Axboe }
713f9ead18cSJens Axboe 
714f9ead18cSJens Axboe int io_connect_prep_async(struct io_kiocb *req)
715f9ead18cSJens Axboe {
716f9ead18cSJens Axboe 	struct io_async_connect *io = req->async_data;
717f9ead18cSJens Axboe 	struct io_connect *conn = io_kiocb_to_cmd(req);
718f9ead18cSJens Axboe 
719f9ead18cSJens Axboe 	return move_addr_to_kernel(conn->addr, conn->addr_len, &io->address);
720f9ead18cSJens Axboe }
721f9ead18cSJens Axboe 
722f9ead18cSJens Axboe int io_connect_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
723f9ead18cSJens Axboe {
724f9ead18cSJens Axboe 	struct io_connect *conn = io_kiocb_to_cmd(req);
725f9ead18cSJens Axboe 
726f9ead18cSJens Axboe 	if (sqe->len || sqe->buf_index || sqe->rw_flags || sqe->splice_fd_in)
727f9ead18cSJens Axboe 		return -EINVAL;
728f9ead18cSJens Axboe 
729f9ead18cSJens Axboe 	conn->addr = u64_to_user_ptr(READ_ONCE(sqe->addr));
730f9ead18cSJens Axboe 	conn->addr_len =  READ_ONCE(sqe->addr2);
731f9ead18cSJens Axboe 	return 0;
732f9ead18cSJens Axboe }
733f9ead18cSJens Axboe 
734f9ead18cSJens Axboe int io_connect(struct io_kiocb *req, unsigned int issue_flags)
735f9ead18cSJens Axboe {
736f9ead18cSJens Axboe 	struct io_connect *connect = io_kiocb_to_cmd(req);
737f9ead18cSJens Axboe 	struct io_async_connect __io, *io;
738f9ead18cSJens Axboe 	unsigned file_flags;
739f9ead18cSJens Axboe 	int ret;
740f9ead18cSJens Axboe 	bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
741f9ead18cSJens Axboe 
742f9ead18cSJens Axboe 	if (req_has_async_data(req)) {
743f9ead18cSJens Axboe 		io = req->async_data;
744f9ead18cSJens Axboe 	} else {
745f9ead18cSJens Axboe 		ret = move_addr_to_kernel(connect->addr,
746f9ead18cSJens Axboe 						connect->addr_len,
747f9ead18cSJens Axboe 						&__io.address);
748f9ead18cSJens Axboe 		if (ret)
749f9ead18cSJens Axboe 			goto out;
750f9ead18cSJens Axboe 		io = &__io;
751f9ead18cSJens Axboe 	}
752f9ead18cSJens Axboe 
753f9ead18cSJens Axboe 	file_flags = force_nonblock ? O_NONBLOCK : 0;
754f9ead18cSJens Axboe 
755f9ead18cSJens Axboe 	ret = __sys_connect_file(req->file, &io->address,
756f9ead18cSJens Axboe 					connect->addr_len, file_flags);
757f9ead18cSJens Axboe 	if ((ret == -EAGAIN || ret == -EINPROGRESS) && force_nonblock) {
758f9ead18cSJens Axboe 		if (req_has_async_data(req))
759f9ead18cSJens Axboe 			return -EAGAIN;
760f9ead18cSJens Axboe 		if (io_alloc_async_data(req)) {
761f9ead18cSJens Axboe 			ret = -ENOMEM;
762f9ead18cSJens Axboe 			goto out;
763f9ead18cSJens Axboe 		}
764f9ead18cSJens Axboe 		memcpy(req->async_data, &__io, sizeof(__io));
765f9ead18cSJens Axboe 		return -EAGAIN;
766f9ead18cSJens Axboe 	}
767f9ead18cSJens Axboe 	if (ret == -ERESTARTSYS)
768f9ead18cSJens Axboe 		ret = -EINTR;
769f9ead18cSJens Axboe out:
770f9ead18cSJens Axboe 	if (ret < 0)
771f9ead18cSJens Axboe 		req_set_fail(req);
772f9ead18cSJens Axboe 	io_req_set_res(req, ret, 0);
773f9ead18cSJens Axboe 	return IOU_OK;
774f9ead18cSJens Axboe }
775f9ead18cSJens Axboe #endif
776