Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'io_uring-5.16-2021-11-27' of git://git.kernel.dk/linux-block

Pull more io_uring fixes from Jens Axboe:
"The locking fixup that was applied earlier this rc has both a deadlock
and IRQ safety issue, let's get that ironed out before -rc3. This
contains:

- Link traversal locking fix (Pavel)

- Cancelation fix (Pavel)

- Relocate cond_resched() for huge buffer chain freeing, avoiding a
softlockup warning (Ye)

- Fix timespec validation (Ye)"

* tag 'io_uring-5.16-2021-11-27' of git://git.kernel.dk/linux-block:
io_uring: Fix undefined-behaviour in io_issue_sqe
io_uring: fix soft lockup when call __io_remove_buffers
io_uring: fix link traversal locking
io_uring: fail cancellation for EXITING tasks

+50 -23
+50 -23
fs/io_uring.c
··· 1278 1278 1279 1279 static bool io_match_task(struct io_kiocb *head, struct task_struct *task, 1280 1280 bool cancel_all) 1281 + __must_hold(&req->ctx->timeout_lock) 1281 1282 { 1282 1283 struct io_kiocb *req; 1283 1284 ··· 1292 1291 return true; 1293 1292 } 1294 1293 return false; 1294 + } 1295 + 1296 + static bool io_match_linked(struct io_kiocb *head) 1297 + { 1298 + struct io_kiocb *req; 1299 + 1300 + io_for_each_link(req, head) { 1301 + if (req->flags & REQ_F_INFLIGHT) 1302 + return true; 1303 + } 1304 + return false; 1305 + } 1306 + 1307 + /* 1308 + * As io_match_task() but protected against racing with linked timeouts. 1309 + * User must not hold timeout_lock. 1310 + */ 1311 + static bool io_match_task_safe(struct io_kiocb *head, struct task_struct *task, 1312 + bool cancel_all) 1313 + { 1314 + bool matched; 1315 + 1316 + if (task && head->task != task) 1317 + return false; 1318 + if (cancel_all) 1319 + return true; 1320 + 1321 + if (head->flags & REQ_F_LINK_TIMEOUT) { 1322 + struct io_ring_ctx *ctx = head->ctx; 1323 + 1324 + /* protect against races with linked timeouts */ 1325 + spin_lock_irq(&ctx->timeout_lock); 1326 + matched = io_match_linked(head); 1327 + spin_unlock_irq(&ctx->timeout_lock); 1328 + } else { 1329 + matched = io_match_linked(head); 1330 + } 1331 + return matched; 1295 1332 } 1296 1333 1297 1334 static inline bool req_has_async_data(struct io_kiocb *req) ··· 4366 4327 kfree(nxt); 4367 4328 if (++i == nbufs) 4368 4329 return i; 4330 + cond_resched(); 4369 4331 } 4370 4332 i++; 4371 4333 kfree(buf); ··· 5739 5699 int posted = 0, i; 5740 5700 5741 5701 spin_lock(&ctx->completion_lock); 5742 - spin_lock_irq(&ctx->timeout_lock); 5743 5702 for (i = 0; i < (1U << ctx->cancel_hash_bits); i++) { 5744 5703 struct hlist_head *list; 5745 5704 5746 5705 list = &ctx->cancel_hash[i]; 5747 5706 hlist_for_each_entry_safe(req, tmp, list, hash_node) { 5748 - if (io_match_task(req, tsk, cancel_all)) 5707 + if (io_match_task_safe(req, tsk, cancel_all)) 5749 5708 posted += io_poll_remove_one(req); 5750 5709 } 5751 5710 } 5752 - spin_unlock_irq(&ctx->timeout_lock); 5753 5711 spin_unlock(&ctx->completion_lock); 5754 5712 5755 5713 if (posted) ··· 6195 6157 6196 6158 if (get_timespec64(&data->ts, u64_to_user_ptr(sqe->addr))) 6197 6159 return -EFAULT; 6160 + 6161 + if (data->ts.tv_sec < 0 || data->ts.tv_nsec < 0) 6162 + return -EINVAL; 6198 6163 6199 6164 data->mode = io_translate_timeout_mode(flags); 6200 6165 hrtimer_init(&data->timer, io_timeout_get_clock(data), data->mode); ··· 6923 6882 static void io_req_task_link_timeout(struct io_kiocb *req, bool *locked) 6924 6883 { 6925 6884 struct io_kiocb *prev = req->timeout.prev; 6926 - int ret; 6885 + int ret = -ENOENT; 6927 6886 6928 6887 if (prev) { 6929 - ret = io_try_cancel_userdata(req, prev->user_data); 6888 + if (!(req->task->flags & PF_EXITING)) 6889 + ret = io_try_cancel_userdata(req, prev->user_data); 6930 6890 io_req_complete_post(req, ret ?: -ETIME, 0); 6931 6891 io_put_req(prev); 6932 6892 } else { ··· 9299 9257 struct io_buffer *buf; 9300 9258 unsigned long index; 9301 9259 9302 - xa_for_each(&ctx->io_buffers, index, buf) { 9260 + xa_for_each(&ctx->io_buffers, index, buf) 9303 9261 __io_remove_buffers(ctx, buf, index, -1U); 9304 - cond_resched(); 9305 - } 9306 9262 } 9307 9263 9308 9264 static void io_req_caches_free(struct io_ring_ctx *ctx) ··· 9604 9564 { 9605 9565 struct io_kiocb *req = container_of(work, struct io_kiocb, work); 9606 9566 struct io_task_cancel *cancel = data; 9607 - bool ret; 9608 9567 9609 - if (!cancel->all && (req->flags & REQ_F_LINK_TIMEOUT)) { 9610 - struct io_ring_ctx *ctx = req->ctx; 9611 - 9612 - /* protect against races with linked timeouts */ 9613 - spin_lock_irq(&ctx->timeout_lock); 9614 - ret = io_match_task(req, cancel->task, cancel->all); 9615 - spin_unlock_irq(&ctx->timeout_lock); 9616 - } else { 9617 - ret = io_match_task(req, cancel->task, cancel->all); 9618 - } 9619 - return ret; 9568 + return io_match_task_safe(req, cancel->task, cancel->all); 9620 9569 } 9621 9570 9622 9571 static __cold bool io_cancel_defer_files(struct io_ring_ctx *ctx, ··· 9616 9587 LIST_HEAD(list); 9617 9588 9618 9589 spin_lock(&ctx->completion_lock); 9619 - spin_lock_irq(&ctx->timeout_lock); 9620 9590 list_for_each_entry_reverse(de, &ctx->defer_list, list) { 9621 - if (io_match_task(de->req, task, cancel_all)) { 9591 + if (io_match_task_safe(de->req, task, cancel_all)) { 9622 9592 list_cut_position(&list, &ctx->defer_list, &de->list); 9623 9593 break; 9624 9594 } 9625 9595 } 9626 - spin_unlock_irq(&ctx->timeout_lock); 9627 9596 spin_unlock(&ctx->completion_lock); 9628 9597 if (list_empty(&list)) 9629 9598 return false;