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
308 struct io_timeout_data *data;308 struct io_timeout_data *data;
309};309};
310 310
311struct io_async_connect {
312 struct sockaddr_storage address;
313};
314
311struct io_async_msghdr {315struct io_async_msghdr {
312 struct iovec fast_iov[UIO_FASTIOV];316 struct iovec fast_iov[UIO_FASTIOV];
313 struct iovec *iov;317 struct iovec *iov;
@@ -327,6 +331,7 @@ struct io_async_ctx { · 13 unmodified lines
327 union {331 union {
328 struct io_async_rw rw;332 struct io_async_rw rw;
329 struct io_async_msghdr msg;333 struct io_async_msghdr msg;
334 struct io_async_connect connect;
330 };335 };
331};336};
332 337
@@ -2195,11 +2200,26 @@ static int io_accept(struct io_kiocb *req, const struct io_uring_sqe *sqe, · 1862 unmodified lines
2195#endif2200#endif
2196}2201}
2197 2202
2203static 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
2198static int io_connect(struct io_kiocb *req, const struct io_uring_sqe *sqe,2218static int io_connect(struct io_kiocb *req, const struct io_uring_sqe *sqe,
2199 struct io_kiocb **nxt, bool force_nonblock)2219 struct io_kiocb **nxt, bool force_nonblock)
2200{2220{
2201#if defined(CONFIG_NET)2221#if defined(CONFIG_NET)
2202 struct sockaddr __user *addr;2222 struct io_async_ctx __io, *io;
2203 unsigned file_flags;2223 unsigned file_flags;
2204 int addr_len, ret;2224 int addr_len, ret;
2205 2225
@@ -2208,15 +2228,35 @@ static int io_connect(struct io_kiocb *req, const struct io_uring_sqe *sqe, · 2 unmodified lines
2208 if (sqe->ioprio || sqe->len || sqe->buf_index || sqe->rw_flags)2228 if (sqe->ioprio || sqe->len || sqe->buf_index || sqe->rw_flags)
2209 return -EINVAL;2229 return -EINVAL;
2210 2230
2211 addr = (struct sockaddr __user *) (unsigned long) READ_ONCE(sqe->addr);
2212 addr_len = READ_ONCE(sqe->addr2);2231 addr_len = READ_ONCE(sqe->addr2);
2213 file_flags = force_nonblock ? O_NONBLOCK : 0;2232 file_flags = force_nonblock ? O_NONBLOCK : 0;
2214 2233
2215 ret = __sys_connect_file(req->file, addr, addr_len, file_flags);2234 if (req->io) {
2216 if (ret == -EAGAIN && force_nonblock)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;
2217 return -EAGAIN;2255 return -EAGAIN;
2256 }
2218 if (ret == -ERESTARTSYS)2257 if (ret == -ERESTARTSYS)
2219 ret = -EINTR;2258 ret = -EINTR;
2259out:
2220 if (ret < 0 && (req->flags & REQ_F_LINK))2260 if (ret < 0 && (req->flags & REQ_F_LINK))
2221 req->flags |= REQ_F_FAIL_LINK;2261 req->flags |= REQ_F_FAIL_LINK;
2222 io_cqring_add_event(req, ret);2262 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
2832 case IORING_OP_RECVMSG:2872 case IORING_OP_RECVMSG:
2833 ret = io_recvmsg_prep(req, io);2873 ret = io_recvmsg_prep(req, io);
2834 break;2874 break;
2875 case IORING_OP_CONNECT:
2876 ret = io_connect_prep(req, io);
2877 break;
2835 default:2878 default:
2836 req->io = io;2879 req->io = io;
2837 return 0;2880 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
406 int __user *upeer_addrlen, int flags);406 int __user *upeer_addrlen, int flags);
407extern int __sys_socket(int family, int type, int protocol);407extern int __sys_socket(int family, int type, int protocol);
408extern int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen);408extern int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen);
409extern int __sys_connect_file(struct file *file,409extern int __sys_connect_file(struct file *file, struct sockaddr_storage *addr,
410 struct sockaddr __user *uservaddr, int addrlen,410 int addrlen, int file_flags);
411 int file_flags);
412extern int __sys_connect(int fd, struct sockaddr __user *uservaddr,411extern int __sys_connect(int fd, struct sockaddr __user *uservaddr,
413 int addrlen);412 int addrlen);
414extern int __sys_listen(int fd, int backlog);413extern 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
1826 * include the -EINPROGRESS status for such sockets.1826 * include the -EINPROGRESS status for such sockets.
1827 */1827 */
1828 1828
1829int __sys_connect_file(struct file *file, struct sockaddr __user *uservaddr,1829int __sys_connect_file(struct file *file, struct sockaddr_storage *address,
1830 int addrlen, int file_flags)1830 int addrlen, int file_flags)
1831{1831{
1832 struct socket *sock;1832 struct socket *sock;
1833 struct sockaddr_storage address;
1834 int err;1833 int err;
1835 1834
1836 sock = sock_from_file(file, &err);1835 sock = sock_from_file(file, &err);
1837 if (!sock)1836 if (!sock)
1838 goto out;1837 goto out;
1839 err = move_addr_to_kernel(uservaddr, addrlen, &address);
1840 if (err < 0)
1841 goto out;
1842 1838
1843 err =1839 err =
1844 security_socket_connect(sock, (struct sockaddr *)&address, addrlen);1840 security_socket_connect(sock, (struct sockaddr *)address, addrlen);
1845 if (err)1841 if (err)
1846 goto out;1842 goto out;
1847 1843
1848 err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,1844 err = sock->ops->connect(sock, (struct sockaddr *)address, addrlen,
1849 sock->file->f_flags | file_flags);1845 sock->file->f_flags | file_flags);
1850out:1846out:
1851 return err;1847 return err;
@@ -1858,7 +1854,11 @@ int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen) · 6 unmodified lines
1858 1854
1859 f = fdget(fd);1855 f = fdget(fd);
1860 if (f.file) {1856 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);
1862 if (f.flags)1862 if (f.flags)
1863 fput(f.file);1863 fput(f.file);
1864 }1864 }

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