[PATCH mm-hotfixes v6 0/5] mm: fix UAF caused by race between ptdump and vmap pgtable freeing

Andrew Morton akpm at linux-foundation.org
Thu Jul 23 16:26:46 PDT 2026


On Thu, 23 Jul 2026 16:16:30 +0100 "Lorenzo Stoakes (ARM)" <ljs at kernel.org> wrote:

> Kernel page table walkers fall into two broad categories - those ranges
> where no exclusion is required via walk_kernel_page_table_range_lockless()
> and those where exclusion is required via walk_kernel_page_table_range()
> or walk_page_range_debug().
> 
> ...
>
> This series works around this by #ifndef CONFIG_ARM64'ing the mmap read
> lock in vmap logic, then partially reverting commit fa93b45fd397 ("arm64:
> Enable vmalloc-huge with ptdump"), keeping the enablement of huge vmap
> support, and removing the ifdeffery with the partial revert patch.
>
> ...
>

Thanks, I updated the mm-hotfixes-unstable branch to this version.

> ---
> v6:
> * Rebased on latest master of Linus's tree.
> * Updated: 3/5 to drop the init_mm lock over page table allocation in order
>   to avoid deadlocks due to init_mm -> ... -> fs_reclaim -> init_mm
>   dependency cycles, as reported by Chaitanya with thanks!
> * Small cover letter typo fixes.

Here's how v6 altered mm.git:


 arch/x86/mm/pat/set_memory.c |    9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

--- a/arch/x86/mm/pat/set_memory.c~b
+++ a/arch/x86/mm/pat/set_memory.c
@@ -50,7 +50,8 @@ struct cpa_data {
 	unsigned int	flags;
 	unsigned int	force_split		: 1,
 			force_static_prot	: 1,
-			force_flush_all		: 1;
+			force_flush_all		: 1,
+			init_mm_read_locked	: 1;
 	struct page	**pages;
 };
 
@@ -1250,7 +1251,11 @@ static int split_large_page(struct cpa_d
 
 	if (!debug_pagealloc_enabled())
 		spin_unlock(&cpa_lock);
+	if (cpa->init_mm_read_locked)
+		mmap_read_unlock(&init_mm);
 	ptdesc = pagetable_alloc(GFP_KERNEL, 0);
+	if (cpa->init_mm_read_locked)
+		mmap_read_lock(&init_mm);
 	if (!debug_pagealloc_enabled())
 		spin_lock(&cpa_lock);
 	if (!ptdesc)
@@ -2123,8 +2128,10 @@ static int change_page_attr_set_clr(unsi
 	cpa.force_split = force_split;
 
 	/* Avoid race with concurrent CPA collapse. */
+	cpa.init_mm_read_locked = true;
 	scoped_guard(mmap_read_lock, &init_mm)
 		ret = __change_page_attr_set_clr(&cpa, 1);
+	cpa.init_mm_read_locked = false;
 
 	/*
 	 * Check whether we really changed something:
_




More information about the linux-arm-kernel mailing list