All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mike Rapoport <rppt@kernel.org>
To: Will Deacon <will@kernel.org>
Cc: Lorenzo Stoakes <ljs@kernel.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	Suren Baghdasaryan <surenb@google.com>,
	"Liam R. Howlett" <liam@infradead.org>,
	Vlastimil Babka <vbabka@kernel.org>,
	Shakeel Butt <shakeel.butt@linux.dev>,
	David Hildenbrand <david@kernel.org>,
	Michal Hocko <mhocko@suse.com>,
	Uladzislau Rezki <urezki@gmail.com>,
	Toshi Kani <toshi.kani@hpe.com>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	Andy Lutomirski <luto@kernel.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Thomas Gleixner <tglx@kernel.org>, Ingo Molnar <mingo@redhat.com>,
	Borislav Petkov <bp@alien8.de>,
	x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>,
	Kiryl Shutsemau <kas@kernel.org>,
	Catalin Marinas <catalin.marinas@arm.com>,
	Dev Jain <dev.jain@arm.com>, Ryan Roberts <ryan.roberts@arm.com>,
	David Carlier <devnexen@gmail.com>,
	linux-mm@kvack.org, linux-kernel@vger.kernel.org,
	bpf@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	stable@vger.kernel.org, abarnas@google.com
Subject: Re: [PATCH mm-hotfixes v3 2/4] x86/mm/pat: acquire mmap lock on page table free to avoid ptdump UAF
Date: Wed, 15 Jul 2026 18:49:30 +0300	[thread overview]
Message-ID: <alesCtwXdIqH6bOP@kernel.org> (raw)
In-Reply-To: <alemS7vxeRB7NcBO@willie-the-truck>

Hi Will,

On Wed, Jul 15, 2026 at 04:24:59PM +0100, Will Deacon wrote:
> Hi Lorenzo,
> 
> I'm certainly no x86 expert (quite the opposite!), but I was looking at
> this with Adrian and got myself confused. See below.
> 
> On Tue, Jul 14, 2026 at 06:24:24PM +0100, Lorenzo Stoakes wrote:
> > x86 implements page attribute modification using its Change Page
> > Attributes (CPA) mechanism.
> > 
> > This tracks properties of ranges such as cache mode through x86 page
> > attributes, and as part of that logic manipulates kernel page tables.
> > 
> > Since commit 41d88484c71c ("x86/mm/pat: restore large ROX pages after
> > fragmentation") ranges of kernel page table entries can be collapsed into
> > huge page table entries as part of this logic.
> > 
> > As part of this collapse, it frees the page tables which the collapsed
> > entries previously pointed to, and it does so without any relevant locks
> > being held to preclude concurrent kernel page table walkers.
> > 
> > The only way this code can be reached is if CPA_COLLAPSE is specified, and
> > this is only set in set_memory_rox() via:
> > 
> > set_memory_rox()
> > -> change_page_attr_set_clr()
> > -> cpa_flush()
> > -> cpa_collapse_large_pages()
> > 
> > Notable users of this are execmem and bpf when manipulating executable
> > mappings.
> > 
> > However, this is problematic for ptdump as it walks ranges it does not own
> > and thus runs the risk of a use-after-free on page tables freed underneath
> > it.
> > 
> > Resolve the issue by acquiring the mmap read lock on init_mm which prevents
> > a concurrent ptdump as it acquires the write lock.
> > 
> > It is safe to acquire a sleeping lock as all the callers invoke
> > set_memory_rox() from process context and in any case,
> > change_page_attr_set_clr() calls vm_unmap_alias() which ultimately takes a
> > mutex, disallowing atomic context here.
> > 
> > Fixes: 41d88484c71c ("x86/mm/pat: restore large ROX pages after fragmentation")
> > Cc: stable@vger.kernel.org
> > Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
> > Reviewed-by: Kiryl Shutsemau (Meta) <kas@kernel.org>
> > Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> > ---
> >  arch/x86/mm/pat/set_memory.c | 14 +++++++++++---
> >  1 file changed, 11 insertions(+), 3 deletions(-)
> > 
> > diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
> > index d023a40a1e03..4c4b8244502f 100644
> > --- a/arch/x86/mm/pat/set_memory.c
> > +++ b/arch/x86/mm/pat/set_memory.c
> > @@ -22,6 +22,7 @@
> >  #include <linux/cc_platform.h>
> >  #include <linux/set_memory.h>
> >  #include <linux/memregion.h>
> > +#include <linux/cleanup.h>
> >  
> >  #include <asm/e820/api.h>
> >  #include <asm/processor.h>
> > @@ -436,9 +437,16 @@ static void cpa_collapse_large_pages(struct cpa_data *cpa)
> >  
> >  	flush_tlb_all();
> >  
> > -	list_for_each_entry_safe(ptdesc, tmp, &pgtables, pt_list) {
> > -		list_del(&ptdesc->pt_list);
> > -		pagetable_free(ptdesc);
> > +	/*
> > +	 * ptdump might read these page tables, so avoid a use-after-free by
> > +	 * acquiring the mmap read lock on init_mm (ptdump acquires the mmap
> > +	 * write lock).
> > +	 */
> > +	scoped_guard(mmap_read_lock, &init_mm) {
> > +		list_for_each_entry_safe(ptdesc, tmp, &pgtables, pt_list) {
> > +			list_del(&ptdesc->pt_list);
> > +			pagetable_free(ptdesc);
> > +		}
> 
> As I understand it, the argument for taking the read lock is that we're
> operating on a region that we "wholly own" and therefore we can happily
> run concurrently with CPUs walking distinct parts of the page-table.
> However, from what I can tell, the CPA collapse logic will operate on
> regions outside of the address range being manipulated by its caller
> because it rounds up to the PMD size.
> 
> As a made-up example, imagine I have a 2MiB aligned region where the
> first 1MiB is read-only and the second 1MiB is in the default r/w state.
> If one CPU calls set_memory_rw() on the first 1MiB while another CPU is
> walking the second 1MiB (via some other API that doesn't take cpa_lock),
> it looks to me like the first CPU can collapse the page-table and free
> the unused pages under the feet of the other CPU. What prevents that
> from happening?

Nothing, and there's a patch to fix that that synchronizes
cpa_collapse_large_pages() using cpa_lock:

https://lore.kernel.org/all/20260626163213.2284080-1-den@openvz.org

This still won't be enough to sync with ptdump though.
 
> If all concurrent walkers have interrupts disabled, I guess the TLB
> invalidation logic would do it, but it would be good to call this out in
> the commit message because it's not clear to me why the read_lock is
> sufficient for the collapsing case.
> 
> Cheers,
> 
> Will

-- 
Sincerely yours,
Mike.

  reply	other threads:[~2026-07-15 15:49 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-14 17:24 [PATCH mm-hotfixes v3 0/4] mm: fix UAF caused by race between ptdump and vmap pgtable freeing Lorenzo Stoakes
2026-07-14 17:24 ` [PATCH mm-hotfixes v3 1/4] mm/vmalloc: acquire init_mm lock on huge vmap to avoid ptdump UAF Lorenzo Stoakes
2026-07-14 17:40   ` sashiko-bot
2026-07-15 10:34   ` Kiryl Shutsemau
2026-07-15 14:16     ` Lorenzo Stoakes (ARM)
2026-07-15 19:14       ` Andrew Morton
2026-07-14 17:24 ` [PATCH mm-hotfixes v3 2/4] x86/mm/pat: acquire mmap lock on page table free " Lorenzo Stoakes
2026-07-14 17:29   ` Dave Hansen
2026-07-15  8:49     ` Lorenzo Stoakes (ARM)
2026-07-15 15:24   ` Will Deacon
2026-07-15 15:49     ` Mike Rapoport [this message]
2026-07-14 17:24 ` [PATCH mm-hotfixes v3 3/4] mm/ptdump: always stabilise against page table freeing using init_mm Lorenzo Stoakes
2026-07-15 10:36   ` Kiryl Shutsemau
2026-07-14 17:24 ` [PATCH mm-hotfixes v3 4/4] arm64: remove redundant concurrent ptdump UAF mitigation Lorenzo Stoakes
2026-07-14 17:31 ` [PATCH mm-hotfixes v3 0/4] mm: fix UAF caused by race between ptdump and vmap pgtable freeing Dave Hansen
2026-07-15  7:28   ` Lorenzo Stoakes (ARM)
2026-07-14 19:11 ` Andrew Morton
2026-07-15  8:31   ` Lorenzo Stoakes (ARM)

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=alesCtwXdIqH6bOP@kernel.org \
    --to=rppt@kernel.org \
    --cc=abarnas@google.com \
    --cc=akpm@linux-foundation.org \
    --cc=bp@alien8.de \
    --cc=bpf@vger.kernel.org \
    --cc=catalin.marinas@arm.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=david@kernel.org \
    --cc=dev.jain@arm.com \
    --cc=devnexen@gmail.com \
    --cc=hpa@zytor.com \
    --cc=kas@kernel.org \
    --cc=liam@infradead.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=ljs@kernel.org \
    --cc=luto@kernel.org \
    --cc=mhocko@suse.com \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=ryan.roberts@arm.com \
    --cc=shakeel.butt@linux.dev \
    --cc=stable@vger.kernel.org \
    --cc=surenb@google.com \
    --cc=tglx@kernel.org \
    --cc=toshi.kani@hpe.com \
    --cc=urezki@gmail.com \
    --cc=vbabka@kernel.org \
    --cc=will@kernel.org \
    --cc=x86@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.