History

io_uring: ensure async punted connect requests copy data

Just like commit f67676d160c6 for read/write requests, this one ensures that the sockaddr data has been copied for IORING_OP_CONNECT if we need to punt the request to async context.

Jens Axboe committed 6 years ago

Commit f499a021 parent 03b12303 files · +57 −15Browse files

Unified · Split

3 files
  1. fs/io_uring.c +47 −4
  2. include/linux/socket.h +2 −3
  3. net/socket.c +8 −8
fs/io_uring.c+47−4
@@ -308,6 +308,10 @@ struct io_timeout { · 307 unmodified lines
308308 struct io_timeout_data *data;
309309 };
310310
311+struct io_async_connect {
312+ struct sockaddr_storage address;
313+};
314+
311315 struct io_async_msghdr {
312316 struct iovec fast_iov[UIO_FASTIOV];
313317 struct iovec *iov;
@@ -327,6 +331,7 @@ struct io_async_ctx { · 13 unmodified lines
327331 union {
328332 struct io_async_rw rw;
329333 struct io_async_msghdr msg;
334+ struct io_async_connect connect;
330335 };
331336 };
332337
@@ -2195,11 +2200,26 @@ static int io_accept(struct io_kiocb *req, const struct io_uring_sqe *sqe, · 1862 unmodified lines
21952200 #endif
21962201 }
21972202
2203+static int io_connect_prep(struct io_kiocb *req, struct io_async_ctx *io)
2204+{
2205+#if defined(CONFIG_NET)
2206+ const struct io_uring_sqe *sqe = req->sqe;
2207+ struct sockaddr __user *addr;
2208+ int addr_len;
2209+
2210+ addr = (struct sockaddr __user *) (unsigned long) READ_ONCE(sqe->addr);
2211+ addr_len = READ_ONCE(sqe->addr2);
2212+ return move_addr_to_kernel(addr, addr_len, &io->connect.address);
2213+#else
2214+ return 0;
2215+#endif
2216+}
2217+
21982218 static int io_connect(struct io_kiocb *req, const struct io_uring_sqe *sqe,
21992219 struct io_kiocb **nxt, bool force_nonblock)
22002220 {
22012221 #if defined(CONFIG_NET)
2202− struct sockaddr __user *addr;
2222+ struct io_async_ctx __io, *io;
22032223 unsigned file_flags;
22042224 int addr_len, ret;
22052225
@@ -2208,15 +2228,35 @@ static int io_connect(struct io_kiocb *req, const struct io_uring_sqe *sqe, · 2 unmodified lines
22082228 if (sqe->ioprio || sqe->len || sqe->buf_index || sqe->rw_flags)
22092229 return -EINVAL;
22102230
2211− addr = (struct sockaddr __user *) (unsigned long) READ_ONCE(sqe->addr);
22122231 addr_len = READ_ONCE(sqe->addr2);
22132232 file_flags = force_nonblock ? O_NONBLOCK : 0;
22142233
2215− ret = __sys_connect_file(req->file, addr, addr_len, file_flags);
2216− if (ret == -EAGAIN && force_nonblock)
2234+ if (req->io) {
2235+ io = req->io;
2236+ } else {
2237+ ret = io_connect_prep(req, &__io);
2238+ if (ret)
2239+ goto out;
2240+ io = &__io;
2241+ }
2242+
2243+ ret = __sys_connect_file(req->file, &io->connect.address, addr_len,
2244+ file_flags);
2245+ if (ret == -EAGAIN && force_nonblock) {
2246+ io = kmalloc(sizeof(*io), GFP_KERNEL);
2247+ if (!io) {
2248+ ret = -ENOMEM;
2249+ goto out;
2250+ }
2251+ memcpy(&io->connect, &__io.connect, sizeof(io->connect));
2252+ req->io = io;
2253+ memcpy(&io->sqe, req->sqe, sizeof(*req->sqe));
2254+ req->sqe = &io->sqe;
22172255 return -EAGAIN;
2256+ }
22182257 if (ret == -ERESTARTSYS)
22192258 ret = -EINTR;
2259+out:
22202260 if (ret < 0 && (req->flags & REQ_F_LINK))
22212261 req->flags |= REQ_F_FAIL_LINK;
22222262 io_cqring_add_event(req, ret);
@@ -2832,6 +2872,9 @@ static int io_req_defer_prep(struct io_kiocb *req, struct io_async_ctx *io) · 609 unmodified lines
28322872 case IORING_OP_RECVMSG:
28332873 ret = io_recvmsg_prep(req, io);
28342874 break;
2875+ case IORING_OP_CONNECT:
2876+ ret = io_connect_prep(req, io);
2877+ break;
28352878 default:
28362879 req->io = io;
28372880 return 0;
include/linux/socket.h+2−3
@@ -406,9 +406,8 @@ extern int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr, · 405 unmodified lines
406406 int __user *upeer_addrlen, int flags);
407407 extern int __sys_socket(int family, int type, int protocol);
408408 extern int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen);
409−extern int __sys_connect_file(struct file *file,
410− struct sockaddr __user *uservaddr, int addrlen,
411− int file_flags);
409+extern int __sys_connect_file(struct file *file, struct sockaddr_storage *addr,
410+ int addrlen, int file_flags);
412411 extern int __sys_connect(int fd, struct sockaddr __user *uservaddr,
413412 int addrlen);
414413 extern int __sys_listen(int fd, int backlog);
net/socket.c+8−8
@@ -1826,26 +1826,22 @@ SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr, · 1825 unmodified lines
18261826 * include the -EINPROGRESS status for such sockets.
18271827 */
18281828
1829−int __sys_connect_file(struct file *file, struct sockaddr __user *uservaddr,
1829+int __sys_connect_file(struct file *file, struct sockaddr_storage *address,
18301830 int addrlen, int file_flags)
18311831 {
18321832 struct socket *sock;
1833− struct sockaddr_storage address;
18341833 int err;
18351834
18361835 sock = sock_from_file(file, &err);
18371836 if (!sock)
18381837 goto out;
1839− err = move_addr_to_kernel(uservaddr, addrlen, &address);
1840− if (err < 0)
1841− goto out;
18421838
18431839 err =
1844− security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
1840+ security_socket_connect(sock, (struct sockaddr *)address, addrlen);
18451841 if (err)
18461842 goto out;
18471843
1848− err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
1844+ err = sock->ops->connect(sock, (struct sockaddr *)address, addrlen,
18491845 sock->file->f_flags | file_flags);
18501846 out:
18511847 return err;
@@ -1858,7 +1854,11 @@ int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen) · 6 unmodified lines
18581854
18591855 f = fdget(fd);
18601856 if (f.file) {
1861− ret = __sys_connect_file(f.file, uservaddr, addrlen, 0);
1857+ struct sockaddr_storage address;
1858+
1859+ ret = move_addr_to_kernel(uservaddr, addrlen, &address);
1860+ if (!ret)
1861+ ret = __sys_connect_file(f.file, &address, addrlen, 0);
18621862 if (f.flags)
18631863 fput(f.file);
18641864 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t