Skip to content

Commit 794a549

Browse files
committed
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
2 parents c0c9379 + 079afb0 commit 794a549

File tree

8 files changed

+37
-13
lines changed

8 files changed

+37
-13
lines changed

MAINTAINERS

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12670,7 +12670,6 @@ F: include/linux/iosys-map.h
1267012670

1267112671
IO_URING
1267212672
M: Jens Axboe <[email protected]>
12673-
M: Pavel Begunkov <[email protected]>
1267412673
1267512674
S: Maintained
1267612675
T: git git://git.kernel.dk/linux-block

io_uring/futex.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@
1414

1515
struct io_futex {
1616
struct file *file;
17-
union {
18-
u32 __user *uaddr;
19-
struct futex_waitv __user *uwaitv;
20-
};
17+
void __user *uaddr;
2118
unsigned long futex_val;
2219
unsigned long futex_mask;
2320
unsigned long futexv_owned;
@@ -148,6 +145,8 @@ int io_futex_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
148145
!futex_validate_input(iof->futex_flags, iof->futex_mask))
149146
return -EINVAL;
150147

148+
/* Mark as inflight, so file exit cancelation will find it */
149+
io_req_track_inflight(req);
151150
return 0;
152151
}
153152

@@ -186,13 +185,15 @@ int io_futexv_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
186185
if (!futexv)
187186
return -ENOMEM;
188187

189-
ret = futex_parse_waitv(futexv, iof->uwaitv, iof->futex_nr,
188+
ret = futex_parse_waitv(futexv, iof->uaddr, iof->futex_nr,
190189
io_futex_wakev_fn, req);
191190
if (ret) {
192191
kfree(futexv);
193192
return ret;
194193
}
195194

195+
/* Mark as inflight, so file exit cancelation will find it */
196+
io_req_track_inflight(req);
196197
iof->futexv_owned = 0;
197198
iof->futexv_unqueued = 0;
198199
req->flags |= REQ_F_ASYNC_DATA;

io_uring/io_uring.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,12 @@ static void io_clean_op(struct io_kiocb *req)
408408
req->flags &= ~IO_REQ_CLEAN_FLAGS;
409409
}
410410

411-
static inline void io_req_track_inflight(struct io_kiocb *req)
411+
/*
412+
* Mark the request as inflight, so that file cancelation will find it.
413+
* Can be used if the file is an io_uring instance, or if the request itself
414+
* relies on ->mm being alive for the duration of the request.
415+
*/
416+
inline void io_req_track_inflight(struct io_kiocb *req)
412417
{
413418
if (!(req->flags & REQ_F_INFLIGHT)) {
414419
req->flags |= REQ_F_INFLIGHT;

io_uring/io_uring.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ void io_add_aux_cqe(struct io_ring_ctx *ctx, u64 user_data, s32 res, u32 cflags)
8383
bool io_req_post_cqe(struct io_kiocb *req, s32 res, u32 cflags);
8484
void __io_commit_cqring_flush(struct io_ring_ctx *ctx);
8585

86+
void io_req_track_inflight(struct io_kiocb *req);
8687
struct file *io_file_get_normal(struct io_kiocb *req, int fd);
8788
struct file *io_file_get_fixed(struct io_kiocb *req, int fd,
8889
unsigned issue_flags);

io_uring/kbuf.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ bool io_kbuf_recycle_legacy(struct io_kiocb *req, unsigned issue_flags)
108108
buf = req->kbuf;
109109
bl = io_buffer_get_list(ctx, buf->bgid);
110110
list_add(&buf->list, &bl->buf_list);
111+
bl->nbufs++;
111112
req->flags &= ~REQ_F_BUFFER_SELECTED;
112113

113114
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,
122123

123124
kbuf = list_first_entry(&bl->buf_list, struct io_buffer, list);
124125
list_del(&kbuf->list);
126+
bl->nbufs--;
125127
if (*len == 0 || *len > kbuf->len)
126128
*len = kbuf->len;
127129
if (list_empty(&bl->buf_list))
@@ -390,6 +392,7 @@ static int io_remove_buffers_legacy(struct io_ring_ctx *ctx,
390392
for (i = 0; i < nbufs && !list_empty(&bl->buf_list); i++) {
391393
nxt = list_first_entry(&bl->buf_list, struct io_buffer, list);
392394
list_del(&nxt->list);
395+
bl->nbufs--;
393396
kfree(nxt);
394397
cond_resched();
395398
}
@@ -491,14 +494,24 @@ static int io_add_buffers(struct io_ring_ctx *ctx, struct io_provide_buf *pbuf,
491494
{
492495
struct io_buffer *buf;
493496
u64 addr = pbuf->addr;
494-
int i, bid = pbuf->bid;
497+
int ret = -ENOMEM, i, bid = pbuf->bid;
495498

496499
for (i = 0; i < pbuf->nbufs; i++) {
500+
/*
501+
* Nonsensical to have more than sizeof(bid) buffers in a
502+
* buffer list, as the application then has no way of knowing
503+
* which duplicate bid refers to what buffer.
504+
*/
505+
if (bl->nbufs == USHRT_MAX) {
506+
ret = -EOVERFLOW;
507+
break;
508+
}
497509
buf = kmalloc(sizeof(*buf), GFP_KERNEL_ACCOUNT);
498510
if (!buf)
499511
break;
500512

501513
list_add_tail(&buf->list, &bl->buf_list);
514+
bl->nbufs++;
502515
buf->addr = addr;
503516
buf->len = min_t(__u32, pbuf->len, MAX_RW_COUNT);
504517
buf->bid = bid;
@@ -508,7 +521,7 @@ static int io_add_buffers(struct io_ring_ctx *ctx, struct io_provide_buf *pbuf,
508521
cond_resched();
509522
}
510523

511-
return i ? 0 : -ENOMEM;
524+
return i ? 0 : ret;
512525
}
513526

514527
static int __io_manage_buffers_legacy(struct io_kiocb *req,

io_uring/kbuf.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ struct io_buffer_list {
2121
struct list_head buf_list;
2222
struct io_uring_buf_ring *buf_ring;
2323
};
24+
/* count of classic/legacy buffers in buffer list */
25+
int nbufs;
26+
2427
__u16 bgid;
2528

2629
/* below is for ring provided buffers */

io_uring/net.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -832,7 +832,7 @@ static inline bool io_recv_finish(struct io_kiocb *req, int *ret,
832832
* If more is available AND it was a full transfer, retry and
833833
* append to this one
834834
*/
835-
if (!sr->retry && kmsg->msg.msg_inq > 0 && this_ret > 0 &&
835+
if (!sr->retry && kmsg->msg.msg_inq > 1 && this_ret > 0 &&
836836
!iov_iter_count(&kmsg->msg.msg_iter)) {
837837
req->cqe.flags = cflags & ~CQE_F_MASK;
838838
sr->len = kmsg->msg.msg_inq;
@@ -1070,7 +1070,7 @@ static int io_recv_buf_select(struct io_kiocb *req, struct io_async_msghdr *kmsg
10701070
arg.mode |= KBUF_MODE_FREE;
10711071
}
10721072

1073-
if (kmsg->msg.msg_inq > 0)
1073+
if (kmsg->msg.msg_inq > 1)
10741074
arg.max_len = min_not_zero(sr->len, kmsg->msg.msg_inq);
10751075

10761076
ret = io_buffers_peek(req, &arg);

io_uring/zcrx.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,8 @@ static void io_free_rbuf_ring(struct io_zcrx_ifq *ifq)
366366

367367
static void io_zcrx_free_area(struct io_zcrx_area *area)
368368
{
369-
io_zcrx_unmap_area(area->ifq, area);
369+
if (area->ifq)
370+
io_zcrx_unmap_area(area->ifq, area);
370371
io_release_area_mem(&area->mem);
371372

372373
kvfree(area->freelist);
@@ -631,12 +632,13 @@ int io_register_zcrx_ifq(struct io_ring_ctx *ctx,
631632
void io_unregister_zcrx_ifqs(struct io_ring_ctx *ctx)
632633
{
633634
struct io_zcrx_ifq *ifq;
634-
unsigned long id;
635635

636636
lockdep_assert_held(&ctx->uring_lock);
637637

638638
while (1) {
639639
scoped_guard(mutex, &ctx->mmap_lock) {
640+
unsigned long id = 0;
641+
640642
ifq = xa_find(&ctx->zcrx_ctxs, &id, ULONG_MAX, XA_PRESENT);
641643
if (ifq)
642644
xa_erase(&ctx->zcrx_ctxs, id);

0 commit comments

Comments
 (0)