All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mike Rapoport <rppt@kernel.org>
To: Arnav Kansal <rnv@google.com>
Cc: Andrew Morton <akpm@linux-foundation.org>,
	Luis Chamberlain <mcgrof@kernel.org>,
	linux-mm@kvack.org, linux-kernel@vger.kernel.org,
	stable@vger.kernel.org, Rohan Kumar <rohakum@google.com>
Subject: Re: [PATCH] mm/execmem: only free ROX cache vm_struct when fully unused
Date: Thu, 15 Oct 2026 11:10:05 +0300	[thread overview]
Message-ID: <atCKXeWnVAWvhSn0@kernel.org> (raw)
In-Reply-To: <20261014233058.1410692-1-rnv@google.com>

On Wed, Oct 14, 2026 at 04:30:58PM -0700, Arnav Kansal wrote:
> execmem_cache_clean() currently uses:
> 
>     IS_ALIGNED(size, PMD_SIZE) && IS_ALIGNED(mas.index, PMD_SIZE)

This is not the case anymore:

https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git/commit/mm/execmem.c?id=569db54d8b7a4ec463a62c444de0d6f5f10e9dc1
 
> as a proxy to determine whether a free range in execmem_cache.free_areas
> spans an entire unused vm_struct that can be returned to vmalloc.
> 
> This heuristic is broken in both directions:
> 
> 1. Premature vfree() of multi-PMD vm_structs (Use-After-Free):
>    When execmem_cache_populate_alloc() services a request larger than
>    PMD_SIZE (for example, a module with > 6 MiB of .text),
>    alloc_size = round_up(size, PMD_SIZE) creates a single multi-PMD
>    vm_struct (e.g., 8 MiB) whose remaining tail space is handed out to
>    subsequent module allocations (e.g., kvm.ko). When a module inside
>    that vm_struct unloads and leaves a PMD_SIZE-aligned free sub-range
>    (such as a 2 MiB or 4 MiB chunk at the start of the 8 MiB vm_struct),
>    execmem_cache_clean() passes the IS_ALIGNED() check and calls
>    vfree(area), which unmaps and frees the entire enclosing multi-PMD
>    vm_struct while sibling modules are still live:
> 
>      BUG: unable to handle page fault for address: ffffffffc07dc030
>      #PF: supervisor instruction fetch in kernel mode
>      #PF: error_code(0x0010) - not-present page
>      PGD 2c33067 P4D 2c33067 PUD 2c35067 PMD 0
>      Oops: Oops: 0010 [#1] SMP NOPTI
>      RIP: 0010:dummy_exit+0x0/0xfd0 [tailm]
> 
> 2. Failure to reclaim fallback vm_structs:
>    After commit 3bd4e0ac61b2 ("execmem: add fallback for failures in
>    vmalloc(VM_ALLOW_HUGE_VMAP)") and commit 4afb85f5e359 ("mm: remove
>    PMD alignment constraint in execmem_vmalloc()"), ROX cache vm_structs
>    allocated via the base-page or exact-size fallback paths are only
>    PAGE_SIZE-aligned in address and/or size, so they never satisfy the
>    PMD_SIZE alignment check even when completely unused.
> 
> Because vmalloc allocations include a trailing guard page, separate
> vm_struct allocations can never coalesce into a single contiguous entry
> in execmem_cache.free_areas. Replace the PMD_SIZE alignment check with
> an explicit check that the free range starts at vm->addr and spans the
> entire get_vm_area_size(vm).
> 
> Fixes: 2e45474ab14f ("execmem: add support for cache of large ROX pages")
> Cc: stable@vger.kernel.org
> Assisted-by: LLM
> Co-developed-by: Rohan Kumar <rohakum@google.com>
> Signed-off-by: Rohan Kumar <rohakum@google.com>
> Signed-off-by: Arnav Kansal <rnv@google.com>
> ---
>  mm/execmem.c | 6 ++----
>  1 file changed, 2 insertions(+), 4 deletions(-)
> 
> diff --git a/mm/execmem.c b/mm/execmem.c
> index 74a178a87e75..3a1da0498fe2 100644
> --- a/mm/execmem.c
> +++ b/mm/execmem.c
> @@ -166,11 +166,9 @@ static void execmem_cache_clean(struct work_struct *work)
>  	mutex_lock(mutex);
>  	mas_for_each(&mas, area, ULONG_MAX) {
>  		size_t size = mas_range_len(&mas);
> +		struct vm_struct *vm = find_vm_area(area);
>  
> -		if (IS_ALIGNED(size, PMD_SIZE) &&
> -		    IS_ALIGNED(mas.index, PMD_SIZE)) {
> -			struct vm_struct *vm = find_vm_area(area);
> -
> +		if (vm->addr == area && get_vm_area_size(vm) == size) {
>  			execmem_set_direct_map_valid(vm, true);
>  			mas_store_gfp(&mas, NULL, GFP_KERNEL);
>  			vfree(area);
> -- 
> 2.47.0

-- 
Sincerely yours,
Mike.


  reply	other threads:[~2026-10-15  8:10 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-14 23:30 [PATCH] mm/execmem: only free ROX cache vm_struct when fully unused Arnav Kansal
2026-10-15  8:10 ` Mike Rapoport [this message]
2026-10-15 13:37   ` Arnav Kansal

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=atCKXeWnVAWvhSn0@kernel.org \
    --to=rppt@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=mcgrof@kernel.org \
    --cc=rnv@google.com \
    --cc=rohakum@google.com \
    --cc=stable@vger.kernel.org \
    /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.