summaryrefslogtreecommitdiff
path: root/io_uring/kbuf.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2025-06-06 23:09:03 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2025-06-06 23:09:03 +0300
commit794a54920781162c4503acea62d88e725726e319 (patch)
treed68414cc03f7fdd269c1fef28af799fa3dd7e208 /io_uring/kbuf.c
parentc0c9379f235df33a12ceae94370ad80c5278324d (diff)
parent079afb081c4288e94d5e4223d3eb6306d853c68b (diff)
downloadlinux-794a54920781162c4503acea62d88e725726e319.tar.xz
Merge tag 'io_uring-6.16-20250606' of git://git.kernel.dk/linux
Pull io_uring fixes from Jens Axboe: - Fix for a regression introduced in this merge window, where the 'id' passed to xa_find() for ifq lookup is uninitialized - Fix for zcrx release on registration failure. From 6.15, going to stable - Tweak for recv bundles, where msg_inq should be > 1 before being used to gate a retry event - Pavel doesnt want to be a maintainer anymore, remove him from the MAINTAINERS entry - Limit legacy kbuf registrations to 64k, which is the size of the buffer ID field anyway. Hence it's nonsensical to support more than that, and the only purpose that serves is to have syzbot trigger long exit delays for heavily configured debug kernels - Fix for the io_uring futex handling, which got broken for FUTEX2_PRIVATE by a generic futex commit adding private hashes * tag 'io_uring-6.16-20250606' of git://git.kernel.dk/linux: io_uring/futex: mark wait requests as inflight io_uring/futex: get rid of struct io_futex addr union io_uring/kbuf: limit legacy provided buffer lists to USHRT_MAX MAINTAINERS: remove myself from io_uring io_uring/net: only consider msg_inq if larger than 1 io_uring/zcrx: fix area release on registration failure io_uring/zcrx: init id for xa_find
Diffstat (limited to 'io_uring/kbuf.c')
-rw-r--r--io_uring/kbuf.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c
index 8cce3ebd813f..2ea65f3cef72 100644
--- a/io_uring/kbuf.c
+++ b/io_uring/kbuf.c
@@ -108,6 +108,7 @@ bool io_kbuf_recycle_legacy(struct io_kiocb *req, unsigned issue_flags)
buf = req->kbuf;
bl = io_buffer_get_list(ctx, buf->bgid);
list_add(&buf->list, &bl->buf_list);
+ bl->nbufs++;
req->flags &= ~REQ_F_BUFFER_SELECTED;
io_ring_submit_unlock(ctx, issue_flags);
@@ -122,6 +123,7 @@ static void __user *io_provided_buffer_select(struct io_kiocb *req, size_t *len,
kbuf = list_first_entry(&bl->buf_list, struct io_buffer, list);
list_del(&kbuf->list);
+ bl->nbufs--;
if (*len == 0 || *len > kbuf->len)
*len = kbuf->len;
if (list_empty(&bl->buf_list))
@@ -390,6 +392,7 @@ static int io_remove_buffers_legacy(struct io_ring_ctx *ctx,
for (i = 0; i < nbufs && !list_empty(&bl->buf_list); i++) {
nxt = list_first_entry(&bl->buf_list, struct io_buffer, list);
list_del(&nxt->list);
+ bl->nbufs--;
kfree(nxt);
cond_resched();
}
@@ -491,14 +494,24 @@ static int io_add_buffers(struct io_ring_ctx *ctx, struct io_provide_buf *pbuf,
{
struct io_buffer *buf;
u64 addr = pbuf->addr;
- int i, bid = pbuf->bid;
+ int ret = -ENOMEM, i, bid = pbuf->bid;
for (i = 0; i < pbuf->nbufs; i++) {
+ /*
+ * Nonsensical to have more than sizeof(bid) buffers in a
+ * buffer list, as the application then has no way of knowing
+ * which duplicate bid refers to what buffer.
+ */
+ if (bl->nbufs == USHRT_MAX) {
+ ret = -EOVERFLOW;
+ break;
+ }
buf = kmalloc(sizeof(*buf), GFP_KERNEL_ACCOUNT);
if (!buf)
break;
list_add_tail(&buf->list, &bl->buf_list);
+ bl->nbufs++;
buf->addr = addr;
buf->len = min_t(__u32, pbuf->len, MAX_RW_COUNT);
buf->bid = bid;
@@ -508,7 +521,7 @@ static int io_add_buffers(struct io_ring_ctx *ctx, struct io_provide_buf *pbuf,
cond_resched();
}
- return i ? 0 : -ENOMEM;
+ return i ? 0 : ret;
}
static int __io_manage_buffers_legacy(struct io_kiocb *req,