History

Merge tag 'io_uring-7.1-20260515' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux

Pull io_uring fixes from Jens Axboe: - Small series sanitizing the locking done for either modifying or reading a chain of requests - If the application has a pid namespace, ensure that the sqthread pid is correctly printed in fdinfo - Fix for a hashing issue in the io-wq thread pool, which could lead to a use-after-free - Kill dead argument from io_prep_rw_pi() - Fix for a missed validation of the CQ ring head, affecting CQE refill * tag 'io_uring-7.1-20260515' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux: io_uring: validate user-controlled cq.head in io_cqe_cache_refill() io-wq: check that the predecessor is hashed in io_wq_remove_pending() io_uring/rw: drop unused attr_type_mask from io_prep_rw_pi() io_uring: hold uring_lock across io_kill_timeouts() in cancel path io_uring: defer linked-timeout chain splice out of hrtimer context io_uring: hold uring_lock when walking link chain in io_wq_free_work() io_uring/fdinfo: translate SqThread PID through caller's pid_ns

Linus Torvalds committed 6 months ago

Commit ee7226b2 parents 78e8370 f44d38a6 files · +44 −13Browse files

Unified · Split

6 files
  1. io_uring/cancel.c +1 −1
  2. io_uring/fdinfo.c +2 −1
  3. io_uring/io-wq.c +2 −1
  4. io_uring/io_uring.c +23 −6
  5. io_uring/rw.c +2 −2
  6. io_uring/timeout.c +14 −2
io_uring/cancel.c+1−1
@@ -561,8 +561,8 @@ __cold bool io_uring_try_cancel_requests(struct io_ring_ctx *ctx, · 560 unmodified lines
561 ret |= io_waitid_remove_all(ctx, tctx, cancel_all);561 ret |= io_waitid_remove_all(ctx, tctx, cancel_all);
562 ret |= io_futex_remove_all(ctx, tctx, cancel_all);562 ret |= io_futex_remove_all(ctx, tctx, cancel_all);
563 ret |= io_uring_try_cancel_uring_cmd(ctx, tctx, cancel_all);563 ret |= io_uring_try_cancel_uring_cmd(ctx, tctx, cancel_all);
564 mutex_unlock(&ctx->uring_lock);
565 ret |= io_kill_timeouts(ctx, tctx, cancel_all);564 ret |= io_kill_timeouts(ctx, tctx, cancel_all);
565 mutex_unlock(&ctx->uring_lock);
566 if (tctx)566 if (tctx)
567 ret |= io_run_task_work() > 0;567 ret |= io_run_task_work() > 0;
568 else568 else
io_uring/fdinfo.c+2−1
@@ -190,8 +190,9 @@ static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m) · 189 unmodified lines
190 get_task_struct(tsk);190 get_task_struct(tsk);
191 rcu_read_unlock();191 rcu_read_unlock();
192 usec = io_sq_cpu_usec(tsk);192 usec = io_sq_cpu_usec(tsk);
193 sq_pid = task_pid_nr_ns(tsk,
194 proc_pid_ns(file_inode(m->file)->i_sb));
193 put_task_struct(tsk);195 put_task_struct(tsk);
194 sq_pid = sq->task_pid;
195 sq_cpu = sq->sq_cpu;196 sq_cpu = sq->sq_cpu;
196 sq_total_time = usec;197 sq_total_time = usec;
197 sq_work_time = sq->work_time;198 sq_work_time = sq->work_time;
io_uring/io-wq.c+2−1
@@ -1124,7 +1124,8 @@ static inline void io_wq_remove_pending(struct io_wq *wq, · 1123 unmodified lines
1124 if (io_wq_is_hashed(work) && work == wq->hash_tail[hash]) {1124 if (io_wq_is_hashed(work) && work == wq->hash_tail[hash]) {
1125 if (prev)1125 if (prev)
1126 prev_work = container_of(prev, struct io_wq_work, list);1126 prev_work = container_of(prev, struct io_wq_work, list);
1127 if (prev_work && io_get_work_hash(prev_work) == hash)1127 if (prev_work && io_wq_is_hashed(prev_work) &&
1128 io_get_work_hash(prev_work) == hash)
1128 wq->hash_tail[hash] = prev_work;1129 wq->hash_tail[hash] = prev_work;
1129 else1130 else
1130 wq->hash_tail[hash] = NULL;1131 wq->hash_tail[hash] = NULL;
io_uring/io_uring.c+23−6
@@ -686,13 +686,27 @@ static struct io_overflow_cqe *io_alloc_ocqe(struct io_ring_ctx *ctx, · 685 unmodified lines
686 return ocqe;686 return ocqe;
687}687}
688 688
689/*
690 * Compute queued CQEs for free-space calculation, clamped to cq_entries.
691 */
692static unsigned int io_cqring_queued(struct io_ring_ctx *ctx)
693{
694 struct io_rings *rings = io_get_rings(ctx);
695 int diff;
696
697 diff = (int)(ctx->cached_cq_tail - READ_ONCE(rings->cq.head));
698 if (diff >= 0)
699 return min((unsigned int)diff, ctx->cq_entries);
700 return 0;
701}
702
689/*703/*
690 * Fill an empty dummy CQE, in case alignment is off for posting a 32b CQE704 * Fill an empty dummy CQE, in case alignment is off for posting a 32b CQE
691 * because the ring is a single 16b entry away from wrapping.705 * because the ring is a single 16b entry away from wrapping.
692 */706 */
693static bool io_fill_nop_cqe(struct io_ring_ctx *ctx, unsigned int off)707static bool io_fill_nop_cqe(struct io_ring_ctx *ctx, unsigned int off)
694{708{
695 if (__io_cqring_events(ctx) < ctx->cq_entries) {709 if (io_cqring_queued(ctx) < ctx->cq_entries) {
696 struct io_uring_cqe *cqe = &ctx->rings->cqes[off];710 struct io_uring_cqe *cqe = &ctx->rings->cqes[off];
697 711
698 cqe->user_data = 0;712 cqe->user_data = 0;
@@ -713,7 +727,7 @@ bool io_cqe_cache_refill(struct io_ring_ctx *ctx, bool overflow, bool cqe32) · 14 unmodified lines
713{727{
714 struct io_rings *rings = ctx->rings;728 struct io_rings *rings = ctx->rings;
715 unsigned int off = ctx->cached_cq_tail & (ctx->cq_entries - 1);729 unsigned int off = ctx->cached_cq_tail & (ctx->cq_entries - 1);
716 unsigned int free, queued, len;730 unsigned int free, len;
717 731
718 /*732 /*
719 * Posting into the CQ when there are pending overflowed CQEs may break733 * Posting into the CQ when there are pending overflowed CQEs may break
@@ -733,9 +747,7 @@ bool io_cqe_cache_refill(struct io_ring_ctx *ctx, bool overflow, bool cqe32) · 13 unmodified lines
733 off = 0;747 off = 0;
734 }748 }
735 749
736 /* userspace may cheat modifying the tail, be safe and do min */750 free = ctx->cq_entries - io_cqring_queued(ctx);
737 queued = min(__io_cqring_events(ctx), ctx->cq_entries);
738 free = ctx->cq_entries - queued;
739 /* we need a contiguous range, limit based on the current array offset */751 /* we need a contiguous range, limit based on the current array offset */
740 len = min(free, ctx->cq_entries - off);752 len = min(free, ctx->cq_entries - off);
741 if (len < (cqe32 + 1))753 if (len < (cqe32 + 1))
@@ -1452,8 +1464,13 @@ struct io_wq_work *io_wq_free_work(struct io_wq_work *work) · 710 unmodified lines
1452 struct io_kiocb *nxt = NULL;1464 struct io_kiocb *nxt = NULL;
1453 1465
1454 if (req_ref_put_and_test_atomic(req)) {1466 if (req_ref_put_and_test_atomic(req)) {
1455 if (req->flags & IO_REQ_LINK_FLAGS)1467 if (req->flags & IO_REQ_LINK_FLAGS) {
1468 struct io_ring_ctx *ctx = req->ctx;
1469
1470 mutex_lock(&ctx->uring_lock);
1456 nxt = io_req_find_next(req);1471 nxt = io_req_find_next(req);
1472 mutex_unlock(&ctx->uring_lock);
1473 }
1457 io_free_req(req);1474 io_free_req(req);
1458 }1475 }
1459 return nxt ? &nxt->work : NULL;1476 return nxt ? &nxt->work : NULL;
io_uring/rw.c+2−2
@@ -230,7 +230,7 @@ static inline void io_meta_restore(struct io_async_rw *io, struct kiocb *kiocb) · 229 unmodified lines
230}230}
231 231
232static int io_prep_rw_pi(struct io_kiocb *req, struct io_rw *rw, int ddir,232static int io_prep_rw_pi(struct io_kiocb *req, struct io_rw *rw, int ddir,
233 u64 attr_ptr, u64 attr_type_mask)233 u64 attr_ptr)
234{234{
235 struct io_uring_attr_pi pi_attr;235 struct io_uring_attr_pi pi_attr;
236 struct io_async_rw *io;236 struct io_async_rw *io;
@@ -305,7 +305,7 @@ static int __io_prep_rw(struct io_kiocb *req, const struct io_uring_sqe *sqe, · 68 unmodified lines
305 return -EINVAL;305 return -EINVAL;
306 306
307 attr_ptr = READ_ONCE(sqe->attr_ptr);307 attr_ptr = READ_ONCE(sqe->attr_ptr);
308 return io_prep_rw_pi(req, rw, ddir, attr_ptr, attr_type_mask);308 return io_prep_rw_pi(req, rw, ddir, attr_ptr);
309 }309 }
310 return 0;310 return 0;
311}311}
io_uring/timeout.c+14−2
@@ -284,6 +284,10 @@ static struct io_kiocb *__io_disarm_linked_timeout(struct io_kiocb *req, · 283 unmodified lines
284 struct io_timeout *timeout = io_kiocb_to_cmd(link, struct io_timeout);284 struct io_timeout *timeout = io_kiocb_to_cmd(link, struct io_timeout);
285 285
286 io_remove_next_linked(req);286 io_remove_next_linked(req);
287
288 /* If this is NULL, then timer already claimed it and will complete it */
289 if (!timeout->head)
290 return NULL;
287 timeout->head = NULL;291 timeout->head = NULL;
288 if (hrtimer_try_to_cancel(&io->timer) != -1) {292 if (hrtimer_try_to_cancel(&io->timer) != -1) {
289 list_del(&timeout->list);293 list_del(&timeout->list);
@@ -367,6 +371,14 @@ static void io_req_task_link_timeout(struct io_tw_req tw_req, io_tw_token_t tw) · 77 unmodified lines
367 int ret;371 int ret;
368 372
369 if (prev) {373 if (prev) {
374 /*
375 * splice the linked timeout out of prev's chain if the regular
376 * completion path didn't already do it.
377 */
378 if (prev->link == req)
379 prev->link = req->link;
380 req->link = NULL;
381
370 if (!tw.cancel) {382 if (!tw.cancel) {
371 struct io_cancel_data cd = {383 struct io_cancel_data cd = {
372 .ctx = req->ctx,384 .ctx = req->ctx,
@@ -401,10 +413,10 @@ static enum hrtimer_restart io_link_timeout_fn(struct hrtimer *timer) · 28 unmodified lines
401 413
402 /*414 /*
403 * We don't expect the list to be empty, that will only happen if we415 * We don't expect the list to be empty, that will only happen if we
404 * race with the completion of the linked work.416 * race with the completion of the linked work. Splice of prev is
417 * done in io_req_task_link_timeout(), if needed.
405 */418 */
406 if (prev) {419 if (prev) {
407 io_remove_next_linked(prev);
408 if (!req_ref_inc_not_zero(prev))420 if (!req_ref_inc_not_zero(prev))
409 prev = NULL;421 prev = NULL;
410 }422 }