mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-24 01:41:39 +00:00
io_uring/net: handle -EINPROGRESS correct for IORING_OP_CONNECT
commit3fb1bd6881
upstream. We treat EINPROGRESS like EAGAIN, but if we're retrying post getting EINPROGRESS, then we just need to check the socket for errors and terminate the request. This was exposed on a bluetooth connection request which ends up taking a while and hitting EINPROGRESS, and yields a CQE result of -EBADFD because we're retrying a connect on a socket that is now connected. Cc: stable@vger.kernel.org Fixes:87f80d623c
("io_uring: handle connect -EINPROGRESS like -EAGAIN") Link: https://github.com/axboe/liburing/issues/671 Reported-by: Aidan Sun <aidansun05@gmail.com> Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
a4af0ca07f
commit
826d45aaac
1 changed files with 22 additions and 6 deletions
|
@ -46,6 +46,7 @@ struct io_connect {
|
|||
struct file *file;
|
||||
struct sockaddr __user *addr;
|
||||
int addr_len;
|
||||
bool in_progress;
|
||||
};
|
||||
|
||||
struct io_sr_msg {
|
||||
|
@ -1263,6 +1264,7 @@ int io_connect_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
|
|||
|
||||
conn->addr = u64_to_user_ptr(READ_ONCE(sqe->addr));
|
||||
conn->addr_len = READ_ONCE(sqe->addr2);
|
||||
conn->in_progress = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1274,6 +1276,16 @@ int io_connect(struct io_kiocb *req, unsigned int issue_flags)
|
|||
int ret;
|
||||
bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
|
||||
|
||||
if (connect->in_progress) {
|
||||
struct socket *socket;
|
||||
|
||||
ret = -ENOTSOCK;
|
||||
socket = sock_from_file(req->file);
|
||||
if (socket)
|
||||
ret = sock_error(socket->sk);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (req_has_async_data(req)) {
|
||||
io = req->async_data;
|
||||
} else {
|
||||
|
@ -1290,13 +1302,17 @@ int io_connect(struct io_kiocb *req, unsigned int issue_flags)
|
|||
ret = __sys_connect_file(req->file, &io->address,
|
||||
connect->addr_len, file_flags);
|
||||
if ((ret == -EAGAIN || ret == -EINPROGRESS) && force_nonblock) {
|
||||
if (req_has_async_data(req))
|
||||
return -EAGAIN;
|
||||
if (io_alloc_async_data(req)) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
if (ret == -EINPROGRESS) {
|
||||
connect->in_progress = true;
|
||||
} else {
|
||||
if (req_has_async_data(req))
|
||||
return -EAGAIN;
|
||||
if (io_alloc_async_data(req)) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
memcpy(req->async_data, &__io, sizeof(__io));
|
||||
}
|
||||
memcpy(req->async_data, &__io, sizeof(__io));
|
||||
return -EAGAIN;
|
||||
}
|
||||
if (ret == -ERESTARTSYS)
|
||||
|
|
Loading…
Reference in a new issue