From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9CD4348F857 for ; Mon, 12 Oct 2026 15:39:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791819561; cv=none; b=S5IPhxsWaLdTADbRqCbCxko1mym4xTCxMaJyIxB8SnF/1rMQv9i4aBauNy7bU4vaJCyEqVhPSMQ+Rh7HG2U2UlOtda/FeAfTfKIULBWUw3psjk7A+JstH9VxqFBJZT0JACBElNme1DV/ZFtp6nhJm9GzE97EorDqQZzdnZl4yos= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791819561; c=relaxed/simple; bh=5YEtS3492LCdo2UwWJuKXCZPUJIAtBgAYfigXEBe8og=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PCPx2X1E/Z9m7o76+DaOPbuk1ulOAvQ2QwrXac005ysRQsLlNHo6yRbcH5c1RvvsYrD441lP2vPPxPivCFi3cmlsyF7R6yEpFxnabxUYJx3YxqQcoDwwBGgyPdepg4eYaEc7tPwVU+J/NXHM6DfyGH2+SRniSET9KbPwAky5IoQ= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=eHWOV4Hv; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="eHWOV4Hv" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E96541F0089C; Mon, 12 Oct 2026 15:39:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1791819560; bh=WDCcUIepx4R27R4AlAnBk+xa8Pbx4zFzwt0wvMGxzhE=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=eHWOV4HvLD/Flpuc2g2Txo89REI64bqV4Dm12a7ymqMUX86WMpQLjZBWFhX6zPh0T AfBkt6ji3ZohUiiUhP1ORa/XOpP/zH4zvjOVZAIMUQC+Hve+sBcWm0TzkZnARBh+rC ZzGtCA4yMG7rujz4pFt58QqIy/QEXoNsy/4s+XmIHEW136haMSUyydtAKQuEE7Uqh3 9SrP3xWtSMuyvWSFh3rc/SwDx9bPUqFvZlU8ehwi9zcXkqqcCw9rsVIUIhbiheeDzO 2CRqGaFzBQgHY89LIRWlostV3BfmR5266ZXW4yJzUXxAQe7lM8Shcb/IQStdrCywDU JnRc18URiYhRA== From: Sasha Levin To: stable@vger.kernel.org Cc: Ali Ahmet Memis , Jens Axboe , Sasha Levin Subject: [PATCH 7.2.y 1/2] io_uring/memmap: account the pages a compound region really uses Date: Mon, 12 Oct 2026 11:39:17 -0400 Message-ID: <20261012153857.1014795-1-sashal@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <2026101224-backroom-send-7931@gregkh> References: <2026101224-backroom-send-7931@gregkh> Precedence: bulk X-Mailing-List: stable@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Ali Ahmet Memis [ Upstream commit f12f0234cc14886bcfd53ffb7c8df4216dad51f1 ] io_mem_alloc_compound() allocates get_order(size) pages, which rounds a region size that is not a power of two up to the next order. The pages past the region are part of the same allocation and cannot be used for anything else, but io_create_region() accounts reg->size >> PAGE_SHIFT, so they are never charged against RLIMIT_MEMLOCK. For a ring with 4096 SQ entries and the default CQ size the region is 37 pages while the allocation is 64. Account the tail pages together with the region, and fall back to the exact sized bulk allocation when they do not fit the limit, so a user close to their limit still gets the region rather than an error. io_free_region() gives the same amount back, the compound case being the one that set IO_REGION_F_SINGLE_REF. Counting how many 4096 entry rings an unprivileged user can create under a given RLIMIT_MEMLOCK, before and after: limit (pages) before after 256 2 2 300 2 2 350 3 2 400 3 3 512 5 4 Five rings under a 512 page limit really pin 640 pages. Fixes: dfbbfbf19187 ("io_uring: introduce concept of memory regions") Link: https://lore.kernel.org/all/87ik5ncj8d.fsf@mailhost.krisman.be/ Signed-off-by: Ali Ahmet Memis Link: https://patch.msgid.link/20260806180044.275543-1-ali@iusegentoo.com Signed-off-by: Jens Axboe Stable-dep-of: b59cabf9b4ac ("io_uring: do not charge the SQ/CQ rings to RLIMIT_MEMLOCK") Signed-off-by: Sasha Levin --- io_uring/memmap.c | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/io_uring/memmap.c b/io_uring/memmap.c index 23e8a85111bca..48c0eb0124123 100644 --- a/io_uring/memmap.c +++ b/io_uring/memmap.c @@ -16,8 +16,10 @@ #include "zcrx.h" static bool io_mem_alloc_compound(struct page **pages, int nr_pages, - size_t size, gfp_t gfp) + size_t size, gfp_t gfp, + struct user_struct *user) { + unsigned long nr_compound, extra; struct page *page; int i, order; @@ -27,9 +29,22 @@ static bool io_mem_alloc_compound(struct page **pages, int nr_pages, else if (order) gfp |= __GFP_COMP; + /* + * get_order() rounds a non power of two size up, so the allocation + * can hold more pages than the region exposes. Account those too, + * and leave the compound allocation alone if they do not fit. + */ + nr_compound = 1UL << order; + extra = nr_compound - nr_pages; + if (extra && user && __io_account_mem(user, extra)) + return false; + page = alloc_pages(gfp, order); - if (!page) + if (!page) { + if (extra && user) + __io_unaccount_mem(user, extra); return false; + } for (i = 0; i < nr_pages; i++) pages[i] = page + i; @@ -105,8 +120,15 @@ void io_free_region(struct user_struct *user, struct io_mapped_region *mr) } if ((mr->flags & IO_REGION_F_VMAP) && mr->ptr) vunmap(mr->ptr); - if (mr->nr_pages && user) - __io_unaccount_mem(user, mr->nr_pages); + if (mr->nr_pages && user) { + unsigned long nr_accounted = mr->nr_pages; + + /* a compound region was accounted for the whole allocation */ + if (mr->flags & IO_REGION_F_SINGLE_REF) + nr_accounted = 1UL << get_order(io_region_size(mr)); + + __io_unaccount_mem(user, nr_accounted); + } memset(mr, 0, sizeof(*mr)); } @@ -151,7 +173,8 @@ static int io_region_pin_pages(struct io_mapped_region *mr, static int io_region_allocate_pages(struct io_mapped_region *mr, struct io_uring_region_desc *reg, - unsigned long mmap_offset) + unsigned long mmap_offset, + struct user_struct *user) { gfp_t gfp = GFP_KERNEL_ACCOUNT | __GFP_ZERO | __GFP_NOWARN; size_t size = io_region_size(mr); @@ -162,7 +185,7 @@ static int io_region_allocate_pages(struct io_mapped_region *mr, if (!pages) return -ENOMEM; - if (io_mem_alloc_compound(pages, mr->nr_pages, size, gfp)) { + if (io_mem_alloc_compound(pages, mr->nr_pages, size, gfp, user)) { mr->flags |= IO_REGION_F_SINGLE_REF; goto done; } @@ -217,7 +240,7 @@ int io_create_region(struct io_ring_ctx *ctx, struct io_mapped_region *mr, if (reg->flags & IORING_MEM_REGION_TYPE_USER) ret = io_region_pin_pages(mr, reg); else - ret = io_region_allocate_pages(mr, reg, mmap_offset); + ret = io_region_allocate_pages(mr, reg, mmap_offset, ctx->user); if (ret) goto out_free; -- 2.53.0