summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-10-04 10:39:36 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2024-10-04 10:39:36 -0700
commit43454e83916dc515e3d11fd07d50c40e6e555873 (patch)
tree39945a4fac28116e66b8872192f851e3d68cff91
parente02f08e217165500a9500e0db1b2da9f4db4e964 (diff)
parentc314094cb4cfa6fc5a17f4881ead2dfebfa717a7 (diff)
Merge tag 'io_uring-6.12-20241004' of git://git.kernel.dk/linux
Pull io_uring fixes from Jens Axboe: - Fix an error path memory leak, if one part fails to allocate. Obviously not something that'll generally hit without error injection. - Fix an io_req_flags_t cast to make sparse happier. - Improve the recv multishot termination. Not a bug now, but could be one in the future. This makes it do the same thing that recvmsg does in terms of when to terminate a request or not. * tag 'io_uring-6.12-20241004' of git://git.kernel.dk/linux: io_uring/net: harden multishot termination case for recv io_uring: fix casts to io_req_flags_t io_uring: fix memory leak when cache init fail
-rw-r--r--io_uring/io_uring.c7
-rw-r--r--io_uring/net.c4
2 files changed, 8 insertions, 3 deletions
diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
index feb61d68dca6..b2736e3491b8 100644
--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -321,7 +321,7 @@ static __cold struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
sizeof(struct io_kiocb));
ret |= io_futex_cache_init(ctx);
if (ret)
- goto err;
+ goto free_ref;
init_completion(&ctx->ref_comp);
xa_init_flags(&ctx->personalities, XA_FLAGS_ALLOC1);
mutex_init(&ctx->uring_lock);
@@ -349,6 +349,9 @@ static __cold struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
io_napi_init(ctx);
return ctx;
+
+free_ref:
+ percpu_ref_exit(&ctx->refs);
err:
io_alloc_cache_free(&ctx->rsrc_node_cache, kfree);
io_alloc_cache_free(&ctx->apoll_cache, kfree);
@@ -2038,7 +2041,7 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req,
req->opcode = opcode = READ_ONCE(sqe->opcode);
/* same numerical values with corresponding REQ_F_*, safe to copy */
sqe_flags = READ_ONCE(sqe->flags);
- req->flags = (io_req_flags_t) sqe_flags;
+ req->flags = (__force io_req_flags_t) sqe_flags;
req->cqe.user_data = READ_ONCE(sqe->user_data);
req->file = NULL;
req->rsrc_node = NULL;
diff --git a/io_uring/net.c b/io_uring/net.c
index f10f5a22d66a..18507658a921 100644
--- a/io_uring/net.c
+++ b/io_uring/net.c
@@ -1133,6 +1133,7 @@ int io_recv(struct io_kiocb *req, unsigned int issue_flags)
int ret, min_ret = 0;
bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
size_t len = sr->len;
+ bool mshot_finished;
if (!(req->flags & REQ_F_POLLED) &&
(sr->flags & IORING_RECVSEND_POLL_FIRST))
@@ -1187,6 +1188,7 @@ out_free:
req_set_fail(req);
}
+ mshot_finished = ret <= 0;
if (ret > 0)
ret += sr->done_io;
else if (sr->done_io)
@@ -1194,7 +1196,7 @@ out_free:
else
io_kbuf_recycle(req, issue_flags);
- if (!io_recv_finish(req, &ret, kmsg, ret <= 0, issue_flags))
+ if (!io_recv_finish(req, &ret, kmsg, mshot_finished, issue_flags))
goto retry_multishot;
return ret;