public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] io_uring: fix resource leak issues
@ 2026-04-08  6:54 KobaK
  2026-04-08  6:54 ` [PATCH 1/3] io_uring: fix pinned pages and pages array leak in io_region_pin_pages() KobaK
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: KobaK @ 2026-04-08  6:54 UTC (permalink / raw)
  To: Jens Axboe, Pavel Begunkov
  Cc: Keith Busch, Ming Lei, io-uring, netdev, linux-kernel, Koba Ko

From: Koba Ko <kobak@nvidia.com>

Three resource leak fixes found by code audit:

1. memmap: pinned pages and pages array leak on WARN_ON path in
   io_region_pin_pages() — mr->pages is never assigned so the caller's
   cleanup is a no-op.

2. rsrc: kfree() used instead of io_cache_free() in
   io_buffer_register_bvec() error path — bypasses cache return.

3. zcrx: io_import_umem() leaves live pinned pages in a partially
   initialized struct on io_account_mem() failure, and
   io_release_area_mem() is not idempotent (missing pages = NULL),
   creating a double-free hazard.

Koba Ko (3):
  io_uring: fix pinned pages and pages array leak in
    io_region_pin_pages()
  io_uring/rsrc: use io_cache_free for node in io_buffer_register_bvec
    error path
  io_uring/zcrx: fix resource leak and double-free hazard in
    io_import_umem

 io_uring/memmap.c |  5 ++++-
 io_uring/rsrc.c   |  2 +-
 io_uring/zcrx.c   | 19 +++++++++++++------
 3 files changed, 18 insertions(+), 8 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/3] io_uring: fix pinned pages and pages array leak in io_region_pin_pages()
  2026-04-08  6:54 [PATCH 0/3] io_uring: fix resource leak issues KobaK
@ 2026-04-08  6:54 ` KobaK
  2026-04-08  8:34   ` Pavel Begunkov
  2026-04-08  6:54 ` [PATCH 2/3] io_uring/rsrc: use io_cache_free for node in io_buffer_register_bvec error path KobaK
  2026-04-08  6:54 ` [PATCH 3/3] io_uring/zcrx: fix resource leak and double-free hazard in io_import_umem KobaK
  2 siblings, 1 reply; 7+ messages in thread
From: KobaK @ 2026-04-08  6:54 UTC (permalink / raw)
  To: Jens Axboe, Pavel Begunkov
  Cc: Keith Busch, Ming Lei, io-uring, netdev, linux-kernel, Koba Ko

From: Koba Ko <kobak@nvidia.com>

When io_pin_pages() succeeds but the subsequent nr_pages sanity check
fires (WARN_ON_ONCE), the function returns -EFAULT without unpinning the
user pages or freeing the kvmalloc'd pages array. The caller's cleanup
via io_free_region() won't help either, because mr->pages was never
assigned — so the entire cleanup block is skipped.

Add unpin_user_pages() and kvfree() before the error return to prevent
the leak.

Fixes: a90558b36ccee ("io_uring/memmap: helper for pinning region pages")
Signed-off-by: Koba Ko <kobak@nvidia.com>
---
 io_uring/memmap.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/io_uring/memmap.c b/io_uring/memmap.c
index e6958968975a8..9f0d3750ce3bc 100644
--- a/io_uring/memmap.c
+++ b/io_uring/memmap.c
@@ -141,8 +141,11 @@ static int io_region_pin_pages(struct io_mapped_region *mr,
 	pages = io_pin_pages(reg->user_addr, size, &nr_pages);
 	if (IS_ERR(pages))
 		return PTR_ERR(pages);
-	if (WARN_ON_ONCE(nr_pages != mr->nr_pages))
+	if (WARN_ON_ONCE(nr_pages != mr->nr_pages)) {
+		unpin_user_pages(pages, nr_pages);
+		kvfree(pages);
 		return -EFAULT;
+	}
 
 	mr->pages = pages;
 	mr->flags |= IO_REGION_F_USER_PROVIDED;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/3] io_uring/rsrc: use io_cache_free for node in io_buffer_register_bvec error path
  2026-04-08  6:54 [PATCH 0/3] io_uring: fix resource leak issues KobaK
  2026-04-08  6:54 ` [PATCH 1/3] io_uring: fix pinned pages and pages array leak in io_region_pin_pages() KobaK
@ 2026-04-08  6:54 ` KobaK
  2026-04-08  8:35   ` Pavel Begunkov
  2026-04-08  6:54 ` [PATCH 3/3] io_uring/zcrx: fix resource leak and double-free hazard in io_import_umem KobaK
  2 siblings, 1 reply; 7+ messages in thread
From: KobaK @ 2026-04-08  6:54 UTC (permalink / raw)
  To: Jens Axboe, Pavel Begunkov
  Cc: Keith Busch, Ming Lei, io-uring, netdev, linux-kernel, Koba Ko

From: Koba Ko <kobak@nvidia.com>

io_buffer_register_bvec() allocates the rsrc node via
io_rsrc_node_alloc() which pulls from ctx->node_cache. On imu allocation
failure, the node is freed with raw kfree() instead of
io_cache_free(&ctx->node_cache, node), bypassing the cache return path
and wasting a reuse opportunity. Every other error path in this file
correctly uses io_cache_free for nodes.

Fixes: 27cb27b6d5ea4 ("io_uring: add support for kernel registered bvecs")
Signed-off-by: Koba Ko <kobak@nvidia.com>
---
 io_uring/rsrc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
index 1b96ab5e98c99..6f46cf9cd13d7 100644
--- a/io_uring/rsrc.c
+++ b/io_uring/rsrc.c
@@ -961,7 +961,7 @@ int io_buffer_register_bvec(struct io_uring_cmd *cmd, struct request *rq,
 	 */
 	imu = io_alloc_imu(ctx, blk_rq_nr_phys_segments(rq));
 	if (!imu) {
-		kfree(node);
+		io_cache_free(&ctx->node_cache, node);
 		ret = -ENOMEM;
 		goto unlock;
 	}
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/3] io_uring/zcrx: fix resource leak and double-free hazard in io_import_umem
  2026-04-08  6:54 [PATCH 0/3] io_uring: fix resource leak issues KobaK
  2026-04-08  6:54 ` [PATCH 1/3] io_uring: fix pinned pages and pages array leak in io_region_pin_pages() KobaK
  2026-04-08  6:54 ` [PATCH 2/3] io_uring/rsrc: use io_cache_free for node in io_buffer_register_bvec error path KobaK
@ 2026-04-08  6:54 ` KobaK
  2026-04-08  9:06   ` Pavel Begunkov
  2 siblings, 1 reply; 7+ messages in thread
From: KobaK @ 2026-04-08  6:54 UTC (permalink / raw)
  To: Jens Axboe, Pavel Begunkov
  Cc: Keith Busch, Ming Lei, io-uring, netdev, linux-kernel, Koba Ko

From: Koba Ko <kobak@nvidia.com>

io_import_umem() has two problems:

1. When io_account_mem() fails, the function returns an error but leaves
   live pinned pages and sg_table in the mem struct without cleaning them
   up. The caller happens to handle this today via io_zcrx_free_area() ->
   io_release_area_mem(), but the contract is fragile.

2. io_release_area_mem() doesn't NULL out mem->pages after kvfree(),
   making it unsafe to call twice. Since io_zcrx_free_area() always
   calls it during teardown, any earlier cleanup call would cause a
   double-free.

Fix both: populate mem fields before io_account_mem() so
io_release_area_mem() can do a proper cleanup on failure, and add
mem->pages = NULL in io_release_area_mem() to make it idempotent.

Fixes: 262ab205180d2 ("io_uring/zcrx: account area memory")
Signed-off-by: Koba Ko <kobak@nvidia.com>
---
 io_uring/zcrx.c | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/io_uring/zcrx.c b/io_uring/zcrx.c
index 62d693287457f..c9ed1139c7bcd 100644
--- a/io_uring/zcrx.c
+++ b/io_uring/zcrx.c
@@ -188,6 +188,8 @@ static unsigned long io_count_account_pages(struct page **pages, unsigned nr_pag
 	return res;
 }
 
+static void io_release_area_mem(struct io_zcrx_mem *mem);
+
 static int io_import_umem(struct io_zcrx_ifq *ifq,
 			  struct io_zcrx_mem *mem,
 			  struct io_uring_zcrx_area_reg *area_reg)
@@ -213,16 +215,20 @@ static int io_import_umem(struct io_zcrx_ifq *ifq,
 		return ret;
 	}
 
-	mem->account_pages = io_count_account_pages(pages, nr_pages);
-	ret = io_account_mem(ifq->user, ifq->mm_account, mem->account_pages);
-	if (ret < 0)
-		mem->account_pages = 0;
-
 	mem->sgt = &mem->page_sg_table;
 	mem->pages = pages;
 	mem->nr_folios = nr_pages;
 	mem->size = area_reg->len;
-	return ret;
+
+	mem->account_pages = io_count_account_pages(pages, nr_pages);
+	ret = io_account_mem(ifq->user, ifq->mm_account, mem->account_pages);
+	if (ret < 0) {
+		mem->account_pages = 0;
+		io_release_area_mem(mem);
+		return ret;
+	}
+
+	return 0;
 }
 
 static void io_release_area_mem(struct io_zcrx_mem *mem)
@@ -236,6 +242,7 @@ static void io_release_area_mem(struct io_zcrx_mem *mem)
 		sg_free_table(mem->sgt);
 		mem->sgt = NULL;
 		kvfree(mem->pages);
+		mem->pages = NULL;
 	}
 }
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/3] io_uring: fix pinned pages and pages array leak in io_region_pin_pages()
  2026-04-08  6:54 ` [PATCH 1/3] io_uring: fix pinned pages and pages array leak in io_region_pin_pages() KobaK
@ 2026-04-08  8:34   ` Pavel Begunkov
  0 siblings, 0 replies; 7+ messages in thread
From: Pavel Begunkov @ 2026-04-08  8:34 UTC (permalink / raw)
  To: KobaK, Jens Axboe; +Cc: Keith Busch, Ming Lei, io-uring, netdev, linux-kernel

On 4/8/26 07:54, KobaK wrote:
> From: Koba Ko <kobak@nvidia.com>
> 
> When io_pin_pages() succeeds but the subsequent nr_pages sanity check
> fires (WARN_ON_ONCE), the function returns -EFAULT without unpinning the
> user pages or freeing the kvmalloc'd pages array. The caller's cleanup
> via io_free_region() won't help either, because mr->pages was never
> assigned — so the entire cleanup block is skipped.
> 
> Add unpin_user_pages() and kvfree() before the error return to prevent
> the leak.
> 
> Fixes: a90558b36ccee ("io_uring/memmap: helper for pinning region pages")
> Signed-off-by: Koba Ko <kobak@nvidia.com>

It's a WARN path, it should never happen, but if it does, that means
io_pin_pages() is buggy, and it's better to leak rather than risk
something nastier.

> ---
>   io_uring/memmap.c | 5 ++++-
>   1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/io_uring/memmap.c b/io_uring/memmap.c
> index e6958968975a8..9f0d3750ce3bc 100644
> --- a/io_uring/memmap.c
> +++ b/io_uring/memmap.c
> @@ -141,8 +141,11 @@ static int io_region_pin_pages(struct io_mapped_region *mr,
>   	pages = io_pin_pages(reg->user_addr, size, &nr_pages);
>   	if (IS_ERR(pages))
>   		return PTR_ERR(pages);
> -	if (WARN_ON_ONCE(nr_pages != mr->nr_pages))
> +	if (WARN_ON_ONCE(nr_pages != mr->nr_pages)) {
> +		unpin_user_pages(pages, nr_pages);
> +		kvfree(pages);
>   		return -EFAULT;
> +	}
>   
>   	mr->pages = pages;
>   	mr->flags |= IO_REGION_F_USER_PROVIDED;

-- 
Pavel Begunkov


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/3] io_uring/rsrc: use io_cache_free for node in io_buffer_register_bvec error path
  2026-04-08  6:54 ` [PATCH 2/3] io_uring/rsrc: use io_cache_free for node in io_buffer_register_bvec error path KobaK
@ 2026-04-08  8:35   ` Pavel Begunkov
  0 siblings, 0 replies; 7+ messages in thread
From: Pavel Begunkov @ 2026-04-08  8:35 UTC (permalink / raw)
  To: KobaK, Jens Axboe; +Cc: Keith Busch, Ming Lei, io-uring, netdev, linux-kernel

On 4/8/26 07:54, KobaK wrote:
> From: Koba Ko <kobak@nvidia.com>
> 
> io_buffer_register_bvec() allocates the rsrc node via
> io_rsrc_node_alloc() which pulls from ctx->node_cache. On imu allocation
> failure, the node is freed with raw kfree() instead of
> io_cache_free(&ctx->node_cache, node), bypassing the cache return path
> and wasting a reuse opportunity. Every other error path in this file
> correctly uses io_cache_free for nodes.
> 
> Fixes: 27cb27b6d5ea4 ("io_uring: add support for kernel registered bvecs")
> Signed-off-by: Koba Ko <kobak@nvidia.com>
> ---
>   io_uring/rsrc.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
> index 1b96ab5e98c99..6f46cf9cd13d7 100644
> --- a/io_uring/rsrc.c
> +++ b/io_uring/rsrc.c
> @@ -961,7 +961,7 @@ int io_buffer_register_bvec(struct io_uring_cmd *cmd, struct request *rq,
>   	 */
>   	imu = io_alloc_imu(ctx, blk_rq_nr_phys_segments(rq));
>   	if (!imu) {
> -		kfree(node);
> +		io_cache_free(&ctx->node_cache, node);

Looks like it was already patched a week ago

-- 
Pavel Begunkov


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 3/3] io_uring/zcrx: fix resource leak and double-free hazard in io_import_umem
  2026-04-08  6:54 ` [PATCH 3/3] io_uring/zcrx: fix resource leak and double-free hazard in io_import_umem KobaK
@ 2026-04-08  9:06   ` Pavel Begunkov
  0 siblings, 0 replies; 7+ messages in thread
From: Pavel Begunkov @ 2026-04-08  9:06 UTC (permalink / raw)
  To: KobaK, Jens Axboe; +Cc: Keith Busch, Ming Lei, io-uring, netdev, linux-kernel

On 4/8/26 07:54, KobaK wrote:
> From: Koba Ko <kobak@nvidia.com>
> 
> io_import_umem() has two problems:
> 
> 1. When io_account_mem() fails, the function returns an error but leaves
>     live pinned pages and sg_table in the mem struct without cleaning them
>     up. The caller happens to handle this today via io_zcrx_free_area() ->
>     io_release_area_mem(), but the contract is fragile.

That was the intention for the caller to clean it up, but in either
case the function has already been rewritten. In general, it seems
you based your patches on top of an outdated tree.

> 2. io_release_area_mem() doesn't NULL out mem->pages after kvfree(),
>     making it unsafe to call twice. Since io_zcrx_free_area() always
>     calls it during teardown, any earlier cleanup call would cause a
>     double-free.
> 
> Fix both: populate mem fields before io_account_mem() so
> io_release_area_mem() can do a proper cleanup on failure, and add
> mem->pages = NULL in io_release_area_mem() to make it idempotent.
> 
> Fixes: 262ab205180d2 ("io_uring/zcrx: account area memory")
> Signed-off-by: Koba Ko <kobak@nvidia.com>
> ---
...
>   
>   static void io_release_area_mem(struct io_zcrx_mem *mem)
> @@ -236,6 +242,7 @@ static void io_release_area_mem(struct io_zcrx_mem *mem)
>   		sg_free_table(mem->sgt);
>   		mem->sgt = NULL;
>   		kvfree(mem->pages);
> +		mem->pages = NULL;

The entire struct io_zcrx_mem / area is freed right after,
calling io_zcrx_free_area() multiple times for the same area
is not allowed.

-- 
Pavel Begunkov


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-04-08  9:06 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-08  6:54 [PATCH 0/3] io_uring: fix resource leak issues KobaK
2026-04-08  6:54 ` [PATCH 1/3] io_uring: fix pinned pages and pages array leak in io_region_pin_pages() KobaK
2026-04-08  8:34   ` Pavel Begunkov
2026-04-08  6:54 ` [PATCH 2/3] io_uring/rsrc: use io_cache_free for node in io_buffer_register_bvec error path KobaK
2026-04-08  8:35   ` Pavel Begunkov
2026-04-08  6:54 ` [PATCH 3/3] io_uring/zcrx: fix resource leak and double-free hazard in io_import_umem KobaK
2026-04-08  9:06   ` Pavel Begunkov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox