| @@ -308,6 +308,10 @@ struct io_timeout { · 307 unmodified lines |
| 308 | 308 | struct io_timeout_data *data; |
| 309 | 309 | }; |
| 310 | 310 | |
| 311 | +struct io_async_connect { |
| 312 | + struct sockaddr_storage address; |
| 313 | +}; |
| 314 | + |
| 311 | 315 | struct io_async_msghdr { |
| 312 | 316 | struct iovec fast_iov[UIO_FASTIOV]; |
| 313 | 317 | struct iovec *iov; |
| @@ -327,6 +331,7 @@ struct io_async_ctx { · 13 unmodified lines |
| 327 | 331 | union { |
| 328 | 332 | struct io_async_rw rw; |
| 329 | 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 | 2200 | #endif |
| 2196 | 2201 | } |
| 2197 | 2202 | |
| 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 | + |
| 2198 | 2218 | static int io_connect(struct io_kiocb *req, const struct io_uring_sqe *sqe, |
| 2199 | 2219 | struct io_kiocb **nxt, bool force_nonblock) |
| 2200 | 2220 | { |
| 2201 | 2221 | #if defined(CONFIG_NET) |
| 2202 | | − struct sockaddr __user *addr; |
| 2222 | + struct io_async_ctx __io, *io; |
| 2203 | 2223 | unsigned file_flags; |
| 2204 | 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 | 2228 | if (sqe->ioprio || sqe->len || sqe->buf_index || sqe->rw_flags) |
| 2209 | 2229 | return -EINVAL; |
| 2210 | 2230 | |
| 2211 | | − addr = (struct sockaddr __user *) (unsigned long) READ_ONCE(sqe->addr); |
| 2212 | 2231 | addr_len = READ_ONCE(sqe->addr2); |
| 2213 | 2232 | file_flags = force_nonblock ? O_NONBLOCK : 0; |
| 2214 | 2233 | |
| 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; |
| 2217 | 2255 | return -EAGAIN; |
| 2256 | + } |
| 2218 | 2257 | if (ret == -ERESTARTSYS) |
| 2219 | 2258 | ret = -EINTR; |
| 2259 | +out: |
| 2220 | 2260 | if (ret < 0 && (req->flags & REQ_F_LINK)) |
| 2221 | 2261 | req->flags |= REQ_F_FAIL_LINK; |
| 2222 | 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 | 2872 | case IORING_OP_RECVMSG: |
| 2833 | 2873 | ret = io_recvmsg_prep(req, io); |
| 2834 | 2874 | break; |
| 2875 | + case IORING_OP_CONNECT: |
| 2876 | + ret = io_connect_prep(req, io); |
| 2877 | + break; |
| 2835 | 2878 | default: |
| 2836 | 2879 | req->io = io; |
| 2837 | 2880 | return 0; |