From: Hao Ge <hao.ge@linux.dev>
To: Suren Baghdasaryan <surenb@google.com>,
Andrew Morton <akpm@linux-foundation.org>,
Petr Pavlu <petr.pavlu@suse.com>
Cc: linux-modules@vger.kernel.org, sashiko-reviews@lists.linux.dev
Subject: Re: [PATCH v8 4/4] alloc_tag: release the reservation when populate fails
Date: Mon, 7 Sep 2026 17:27:39 +0800 [thread overview]
Message-ID: <6cb23255-cf0f-41af-a097-d969e659e2f8@linux.dev> (raw)
In-Reply-To: <20260907064336.E33BE1F00A3A@smtp.kernel.org>
On 2026/9/7 14:43, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
>
> New issues:
> - [Critical] The patch introduces a kernel crash by freeing the maple tree entry without rolling back module_tags.size on failure.
>
> Pre-existing issues:
> - [High] vmap_pages_range() failure in vm_module_tags_populate() leaves physical pages mapped while freeing them, leading to Use-After-Free.
> - [High] AB-BA Deadlock between procfs read and module loading via shutdown_mem_profiling().
> - [Medium] Memory leak of percpu counters when module falls back to standard section allocation.
> --
>
> commit 09d0b9820f6ab861e4c9680b44a685c8658fb571
> Author: Hao Ge <hao.ge@linux.dev>
>
> alloc_tag: release the reservation when populate fails
>
> vm_module_tags_populate() can fail after a reservation is stored in the
> maple tree. The error return previously leaked the entry because a failed
> load never unloads the module. This patch calls release_module_tags()
> on failure to free the reservation.
>
>> diff --git a/mm/alloc_tag.c b/mm/alloc_tag.c
>> index 112a014d4b890..c11813cd9e153 100644
>> --- a/mm/alloc_tag.c
>> +++ b/mm/alloc_tag.c
>> @@ -963,6 +963,7 @@ static void *reserve_module_tags(struct module *mod, unsigned long size,
>> shutdown_mem_profiling(true);
>
> [Severity: High]
> This isn't a bug introduced by this patch, but could calling
> shutdown_mem_profiling(true) here risk an AB-BA deadlock?
>
> A read to /proc/allocinfo enters proc_reg_read_iter(), taking an 'in_use'
> reference on the proc entry, then calls allocinfo_start() which waits for
> down_read(&alloc_tag_cttype->mod_lock).
>
> Concurrently, module loading calls codetag_alloc_module_section(), holding
> down_write(&alloc_tag_cttype->mod_lock).
>
> If reserve_module_tags() encounters an error, it calls
> shutdown_mem_profiling(true), which invokes remove_proc_entry().
>
> Since remove_proc_entry() blocks waiting for the 'in_use' reference count
> to drop to zero, and the procfs reader blocks on the mod_lock held by the
> writer, doesn't this create a system hang during a module load failure?
>
>> pr_err("Failed to allocate memory for allocation tags in the module %s. Memory allocation profiling is disabled!\n",
>> mod->name);
>> + release_module_tags(mod, false);
>
> [Severity: Critical]
> Will this new call to release_module_tags() cause a kernel crash on a
> subsequent module load?
>
> In reserve_module_tags(), module_tags.size is optimistically updated
> (module_tags.size = offset + size;) before attempting to allocate physical
> memory via vm_module_tags_populate().
>
> If population fails, this patch frees the maple tree entry, but
> module_tags.size is left artificially inflated.
>
> A subsequent module load will search the maple tree and reuse this freed gap.
> Because module_tags.size is already inflated, the allocation check bypasses
> vm_module_tags_populate(), returning an unmapped virtual address. Can copying
> section data into this address then trigger a fatal page fault?
>
I see.
No, not for a subsequent load. The failure path shuts profiling
down before returning:
grow_res = vm_module_tags_populate();
if (grow_res) {
shutdown_mem_profiling(true); /* mem_profiling_support = false */
...
release_module_tags(mod, false);
return ERR_PTR(grow_res);
}
and any later load bails out in needs_section_mem() long before it
reaches reserve_module_tags():
if (!mem_profiling_support)
return false;
so no new reservation is made and the unmapped address is never
handed out.
But this reminds me of another race condition:
CPU0: failing load CPU1: concurrent load
---------------------- ---------------------------
needs_section_mem(): true needs_section_mem(): true
reserve_module_tags(): reserve the gap,
module_tags.size = end
populate() fails, gap released
reserve_module_tags(): reuse the gap,
end <= size -> skip populate
memcpy() -> page fault
I have a fix for this, but I'd like to wait for Petr and Suren to review the
remaining parts before sending it out.
Thanks
Best Regards
Hao
> [Severity: Medium]
> This is a pre-existing issue, but might the use of release_module_tags()
> when falling back to a standard section allocation leak percpu counters?
>
> If tags are not addressable, reserve_module_tags() calls
> release_module_tags(mod, false) to remove the module from the maple tree
> and returns -EAGAIN.
>
> The module loader catches -EAGAIN and falls back to a normal section
> allocation. Later, load_module() successfully allocates percpu counters for
> the tags.
>
> On unload, release_module_tags(mod, true) is called to free the counters.
> However, because the module is no longer in the maple tree, the search fails
> and exits early:
>
> mm/alloc_tag.c:release_module_tags() {
> ...
> if (!val) /* module not found */
> goto out;
> ...
> }
>
> Are the percpu counters allocated during load_module() permanently leaked
> in this scenario?
>
>> return ERR_PTR(grow_res);
>
> [Severity: High]
> This is a pre-existing issue, but is there a risk that the failure path of
> vm_module_tags_populate() leaves dangling PTEs causing a Use-After-Free?
>
> In vm_module_tags_populate(), vmap_pages_range() maps allocated pages into
> the kernel virtual address space.
>
> If it fails, it returns an error but may leave successfully mapped PTEs
> active in the page tables. The error path calls release_pages() to free the
> physical pages back to the allocator, but fails to call vunmap_range():
>
> mm/alloc_tag.c:vm_module_tags_populate() {
> ...
> if (nr < more_pages || vmap_pages_range(...) < 0) {
> release_pages(arg, nr);
> return -ENOMEM;
> }
> ...
> }
>
> Could this leave dangling PTEs with PAGE_KERNEL permissions pointing to
> freed pages, risking data corruption when the pages are reallocated?
>
>> }
>> }
>
prev parent reply other threads:[~2026-09-07 9:26 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-07 6:24 [PATCH v8 0/4] alloc_tag and module codetag section fixes Hao Ge
2026-09-07 6:24 ` [PATCH v8 1/4] alloc_tag: move release_module_tags() above reserve_module_tags() Hao Ge
2026-09-07 6:24 ` [PATCH v8 2/4] module: introduce SH_ENTSIZE_STANDALONE for separately allocated sections Hao Ge
2026-09-07 6:24 ` [PATCH v8 3/4] module: allocate codetag sections before the regular module layout Hao Ge
2026-09-07 6:47 ` sashiko-bot
2026-09-07 6:24 ` [PATCH v8 4/4] alloc_tag: release the reservation when populate fails Hao Ge
2026-09-07 6:43 ` sashiko-bot
2026-09-07 9:27 ` Hao Ge [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=6cb23255-cf0f-41af-a097-d969e659e2f8@linux.dev \
--to=hao.ge@linux.dev \
--cc=akpm@linux-foundation.org \
--cc=linux-modules@vger.kernel.org \
--cc=petr.pavlu@suse.com \
--cc=sashiko-reviews@lists.linux.dev \
--cc=surenb@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox