Skip to content

Commit 53fd75f

Browse files
isilencegregkh
authored andcommitted
io_uring/rsrc: fix folio unpinning
Commit 5afb4bf upstream. syzbot complains about an unmapping failure: [ 108.070381][ T14] kernel BUG at mm/gup.c:71! [ 108.070502][ T14] Internal error: Oops - BUG: 00000000f2000800 [#1] SMP [ 108.123672][ T14] Hardware name: QEMU KVM Virtual Machine, BIOS edk2-20250221-8.fc42 02/21/2025 [ 108.127458][ T14] Workqueue: iou_exit io_ring_exit_work [ 108.174205][ T14] Call trace: [ 108.175649][ T14] sanity_check_pinned_pages+0x7cc/0x7d0 (P) [ 108.178138][ T14] unpin_user_page+0x80/0x10c [ 108.180189][ T14] io_release_ubuf+0x84/0xf8 [ 108.182196][ T14] io_free_rsrc_node+0x250/0x57c [ 108.184345][ T14] io_rsrc_data_free+0x148/0x298 [ 108.186493][ T14] io_sqe_buffers_unregister+0x84/0xa0 [ 108.188991][ T14] io_ring_ctx_free+0x48/0x480 [ 108.191057][ T14] io_ring_exit_work+0x764/0x7d8 [ 108.193207][ T14] process_one_work+0x7e8/0x155c [ 108.195431][ T14] worker_thread+0x958/0xed8 [ 108.197561][ T14] kthread+0x5fc/0x75c [ 108.199362][ T14] ret_from_fork+0x10/0x20 We can pin a tail page of a folio, but then io_uring will try to unpin the head page of the folio. While it should be fine in terms of keeping the page actually alive, mm folks say it's wrong and triggers a debug warning. Use unpin_user_folio() instead of unpin_user_page*. Cc: [email protected] Debugged-by: David Hildenbrand <[email protected]> Reported-by: [email protected] Closes: https://lkml.kernel.org/r/[email protected] Fixes: a8edbb4 ("io_uring/rsrc: enable multi-hugepage buffer coalescing") Signed-off-by: Pavel Begunkov <[email protected]> Link: https://lore.kernel.org/io-uring/a28b0f87339ac2acf14a645dad1e95bbcbf18acd.1750771718.git.asml.silence@gmail.com/ [axboe: adapt to current tree, massage commit message] Signed-off-by: Jens Axboe <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 8b8a366 commit 53fd75f

File tree

1 file changed

+9
-4
lines changed

1 file changed

+9
-4
lines changed

io_uring/rsrc.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,11 @@ static void io_buffer_unmap(struct io_ring_ctx *ctx, struct io_mapped_ubuf **slo
119119
if (imu != &dummy_ubuf) {
120120
if (!refcount_dec_and_test(&imu->refs))
121121
return;
122-
for (i = 0; i < imu->nr_bvecs; i++)
123-
unpin_user_page(imu->bvec[i].bv_page);
122+
for (i = 0; i < imu->nr_bvecs; i++) {
123+
struct folio *folio = page_folio(imu->bvec[i].bv_page);
124+
125+
unpin_user_folio(folio, 1);
126+
}
124127
if (imu->acct_pages)
125128
io_unaccount_mem(ctx, imu->acct_pages);
126129
kvfree(imu);
@@ -1010,8 +1013,10 @@ static int io_sqe_buffer_register(struct io_ring_ctx *ctx, struct iovec *iov,
10101013
done:
10111014
if (ret) {
10121015
kvfree(imu);
1013-
if (pages)
1014-
unpin_user_pages(pages, nr_pages);
1016+
if (pages) {
1017+
for (i = 0; i < nr_pages; i++)
1018+
unpin_user_folio(page_folio(pages[i]), 1);
1019+
}
10151020
}
10161021
kvfree(pages);
10171022
return ret;

0 commit comments

Comments
 (0)