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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.