Linux Modules
 help / color / mirror / Atom feed
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?
> 
>>  		}
>>  	}
> 

      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