summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2023-03-24 14:01:01 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2023-03-24 14:01:01 -0700
commite344eb7be2a25c66a8bac5d4388f1a4583450a72 (patch)
tree0742287b58bd6e02d4cf1a9b2f129c6dbd1312ab
parentfd3d06ff5f4fa23f32bdb7f4d9f308503801d9e0 (diff)
parent02a4d923e4400a36d340ea12d8058f69ebf3a383 (diff)
Merge tag 'io_uring-6.3-2023-03-24' of git://git.kernel.dk/linux
Pull io_uring fixes from Jens Axboe: - Fix an issue with repeated -ECONNREFUSED on a socket (me) - Fix a NULL pointer deference due to a stale lookup cache for allocating direct descriptors (Savino) * tag 'io_uring-6.3-2023-03-24' of git://git.kernel.dk/linux: io_uring/rsrc: fix null-ptr-deref in io_file_bitmap_get() io_uring/net: avoid sending -ECONNABORTED on repeated connection requests
-rw-r--r--io_uring/filetable.c3
-rw-r--r--io_uring/net.c25
-rw-r--r--io_uring/rsrc.c1
3 files changed, 20 insertions, 9 deletions
diff --git a/io_uring/filetable.c b/io_uring/filetable.c
index 68dfc6936aa7..b80614e7d605 100644
--- a/io_uring/filetable.c
+++ b/io_uring/filetable.c
@@ -19,6 +19,9 @@ static int io_file_bitmap_get(struct io_ring_ctx *ctx)
unsigned long nr = ctx->file_alloc_end;
int ret;
+ if (!table->bitmap)
+ return -ENFILE;
+
do {
ret = find_next_zero_bit(table->bitmap, nr, table->alloc_hint);
if (ret != nr)
diff --git a/io_uring/net.c b/io_uring/net.c
index b7f190ca528e..4040cf093318 100644
--- a/io_uring/net.c
+++ b/io_uring/net.c
@@ -47,6 +47,7 @@ struct io_connect {
struct sockaddr __user *addr;
int addr_len;
bool in_progress;
+ bool seen_econnaborted;
};
struct io_sr_msg {
@@ -1424,7 +1425,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;
+ conn->in_progress = conn->seen_econnaborted = false;
return 0;
}
@@ -1461,18 +1462,24 @@ 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 ((ret == -EAGAIN || ret == -EINPROGRESS || ret == -ECONNABORTED)
+ && force_nonblock) {
if (ret == -EINPROGRESS) {
connect->in_progress = true;
- } else {
- if (req_has_async_data(req))
- return -EAGAIN;
- if (io_alloc_async_data(req)) {
- ret = -ENOMEM;
+ return -EAGAIN;
+ }
+ if (ret == -ECONNABORTED) {
+ if (connect->seen_econnaborted)
goto out;
- }
- memcpy(req->async_data, &__io, sizeof(__io));
+ connect->seen_econnaborted = true;
+ }
+ 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));
return -EAGAIN;
}
if (ret == -ERESTARTSYS)
diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
index e2bac9f89902..7a43aed8e395 100644
--- a/io_uring/rsrc.c
+++ b/io_uring/rsrc.c
@@ -794,6 +794,7 @@ void __io_sqe_files_unregister(struct io_ring_ctx *ctx)
}
#endif
io_free_file_tables(&ctx->file_table);
+ io_file_table_set_alloc_range(ctx, 0, 0);
io_rsrc_data_free(ctx->file_data);
ctx->file_data = NULL;
ctx->nr_user_files = 0;