Commit 2c4dc5d7 authored by Jens Axboe's avatar Jens Axboe Committed by Long Li
Browse files

io_uring/tctx: work around xa_store() allocation error issue

mainline inclusion
from mainline-v6.10-rc2
commit 7eb75ce7527129d7f1fee6951566af409a37a1c4
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBEAP3
CVE: CVE-2024-56584

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7eb75ce7527129d7f1fee6951566af409a37a1c4



--------------------------------

syzbot triggered the following WARN_ON:

WARNING: CPU: 0 PID: 16 at io_uring/tctx.c:51 __io_uring_free+0xfa/0x140 io_uring/tctx.c:51

which is the

WARN_ON_ONCE(!xa_empty(&tctx->xa));

sanity check in __io_uring_free() when a io_uring_task is going through
its final put. The syzbot test case includes injecting memory allocation
failures, and it very much looks like xa_store() can fail one of its
memory allocations and end up with ->head being non-NULL even though no
entries exist in the xarray.

Until this issue gets sorted out, work around it by attempting to
iterate entries in our xarray, and WARN_ON_ONCE() if one is found.

Reported-by: default avatar <syzbot+cc36d44ec9f368e443d3@syzkaller.appspotmail.com>
Link: https://lore.kernel.org/io-uring/673c1643.050a0220.87769.0066.GAE@google.com/


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
Conflicts:
	io_uring/io_uring.c
	io_uring/tctx.c
[Conflicts due to __io_uring_free() move to io_uring/tctx.c in mainline]
Signed-off-by: default avatarLong Li <leo.lilong@huawei.com>
parent 0912fd81
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -8537,8 +8537,19 @@ static int io_uring_alloc_task_context(struct task_struct *task,
void __io_uring_free(struct task_struct *tsk)
{
	struct io_uring_task *tctx = tsk->io_uring;
	struct io_tctx_node *node;
	unsigned long index;

	WARN_ON_ONCE(!xa_empty(&tctx->xa));
	/*
	 * Fault injection forcing allocation errors in the xa_store() path
	 * can lead to xa_empty() returning false, even though no actual
	 * node is stored in the xarray. Until that gets sorted out, attempt
	 * an iteration here and warn if any entries are found.
	 */
	xa_for_each(&tctx->xa, index, node) {
		WARN_ON_ONCE(1);
		break;
	}
	WARN_ON_ONCE(tctx->io_wq);
	WARN_ON_ONCE(tctx->cached_refs);