FAILED: patch "[PATCH] arm64: mm: Fix the lockless page-table walk in show_pte()" failed to apply to 6.1-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.1-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.1.y
git checkout FETCH_HEAD
git cherry-pick -x a77644d009dece1104b6fcc6e322b0e4503db0d6
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090940-catering-debug-33e5@gregkh' --subject-prefix 'PATCH 6.1.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From a77644d009dece1104b6fcc6e322b0e4503db0d6 Mon Sep 17 00:00:00 2001
From: Karl Mehltretter <[email protected]>
Date: Fri, 28 Aug 2026 19:41:31 +0200
Subject: [PATCH] arm64: mm: Fix the lockless page-table walk in show_pte()
show_pte() walks page tables locklessly and can run with interrupts enabled. A concurrent teardown can free a table page while it is being walked. It can also clear a parent entry after show_pte() checked it; the regular pXd_offset() helpers then reread the cleared entry and can derive a bogus lower-level pointer and fault again.
Use the lockless offset helpers with the saved parent entries, as gup_fast() does, and pass the saved PMD to pte_offset_map().
For task page tables, arm64 selects MMU_GATHER_RCU_TABLE_FREE. Disable local interrupts around the walk to hold off RCU-deferred table frees and block the tlb_remove_table_sync_one() IPI until the walk is finished.
Place the IRQ guard after the header print. This does not make the output a consistent snapshot, but prevents the task page-table walk from dereferencing a released table page or deriving a pointer from a different parent value.
arch/arm64/mm/fault.c +8 -4
@@ -16,6 +16,7 @@#include <linux/mm.h> #include <linux/hardirq.h> #include <linux/init.h> +#include <linux/irqflags.h> #include <linux/kasan.h> #include <linux/kprobes.h> #include <linux/uaccess.h>
@@ -154,6 +155,9 @@ static void show_pte(unsigned long addr)pr_alert ("%s pgtable: %luk pages, %llu-bit VAs, pgdp=%016lx\n" , mm == &init_mm ?"swapper" :"user" ,PAGE_SIZE /SZ_1K , vabits_actual,mm_to_pgd_phys (mm)); + +guard (irqsave)(); + pgdp =pgd_offset (mm, addr); pgd =READ_ONCE (*pgdp);pr_alert ("[%016lx] pgd=%016llx" , addr,pgd_val (pgd));
@@ -167,25 +171,25 @@ static void show_pte(unsigned long addr)if (pgd_none (pgd) ||pgd_bad (pgd))break ; - p4dp =p4d_offset (pgdp, addr); + p4dp =p4d_offset_lockless (pgdp, pgd, addr); p4d =READ_ONCE (*p4dp);pr_cont (", p4d=%016llx" ,p4d_val (p4d));if (p4d_none (p4d) ||p4d_bad (p4d))break ; - pudp =pud_offset (p4dp, addr); + pudp =pud_offset_lockless (p4dp, p4d, addr); pud =READ_ONCE (*pudp);pr_cont (", pud=%016llx" ,pud_val (pud));if (pud_none (pud) ||pud_bad (pud))break ; - pmdp =pmd_offset (pudp, addr); + pmdp =pmd_offset_lockless (pudp, pud, addr); pmd =READ_ONCE (*pmdp);pr_cont (", pmd=%016llx" ,pmd_val (pmd));if (pmd_none (pmd) ||pmd_bad (pmd))break ; - ptep =pte_offset_map (pmdp, addr); + ptep =pte_offset_map (&pmd, addr);if (!ptep)break ;
Sasha Levin
maintainerPATCH 1/2 arm64: allow pte_offset_map() to fail
From: Hugh Dickins <[email protected]>
[ Upstream commit 52924726f4c06b3f77de75fb665e6efd8e777d07 ]
In rare transient cases, not yet made possible, pte_offset_map() and pte_offset_map_lock() may not find a page table: handle appropriately.
Stable-dep-of: a77644d009de ("arm64: mm: Fix the lockless page-table walk in show_pte()")
--- arch/arm64/mm/fault.c | 3 +++ 1 file changed, 3 insertions(+)
arch/arm64/mm/fault.c +3 -0
@@ -177,6 +177,9 @@ static void show_pte(unsigned long addr)break ; ptep =pte_offset_map (pmdp, addr); +if (!ptep) +break ; + pte =READ_ONCE (*ptep);pr_cont (", pte=%016llx" ,pte_val (pte));pte_unmap (ptep);
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/2 arm64: mm: Fix the lockless page-table walk in show_pte()
From: Karl Mehltretter <[email protected]>
[ Upstream commit a77644d009dece1104b6fcc6e322b0e4503db0d6 ]
show_pte() walks page tables locklessly and can run with interrupts enabled. A concurrent teardown can free a table page while it is being walked. It can also clear a parent entry after show_pte() checked it; the regular pXd_offset() helpers then reread the cleared entry and can derive a bogus lower-level pointer and fault again.
Use the lockless offset helpers with the saved parent entries, as gup_fast() does, and pass the saved PMD to pte_offset_map().
For task page tables, arm64 selects MMU_GATHER_RCU_TABLE_FREE. Disable local interrupts around the walk to hold off RCU-deferred table frees and block the tlb_remove_table_sync_one() IPI until the walk is finished.
Place the IRQ guard after the header print. This does not make the output a consistent snapshot, but prevents the task page-table walk from dereferencing a released table page or deriving a pointer from a different parent value.
--- arch/arm64/mm/fault.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
arch/arm64/mm/fault.c +8 -4
@@ -15,6 +15,7 @@#include <linux/mm.h> #include <linux/hardirq.h> #include <linux/init.h> +#include <linux/irqflags.h> #include <linux/kasan.h> #include <linux/kprobes.h> #include <linux/uaccess.h>
@@ -145,6 +146,9 @@ static void show_pte(unsigned long addr)pr_alert ("%s pgtable: %luk pages, %llu-bit VAs, pgdp=%016lx\n" , mm == &init_mm ?"swapper" :"user" ,PAGE_SIZE /SZ_1K , vabits_actual,mm_to_pgd_phys (mm)); + +guard (irqsave)(); + pgdp =pgd_offset (mm, addr); pgd =READ_ONCE (*pgdp);pr_alert ("[%016lx] pgd=%016llx" , addr,pgd_val (pgd));
@@ -158,25 +162,25 @@ static void show_pte(unsigned long addr)if (pgd_none (pgd) ||pgd_bad (pgd))break ; - p4dp =p4d_offset (pgdp, addr); + p4dp =p4d_offset_lockless (pgdp, pgd, addr); p4d =READ_ONCE (*p4dp);pr_cont (", p4d=%016llx" ,p4d_val (p4d));if (p4d_none (p4d) ||p4d_bad (p4d))break ; - pudp =pud_offset (p4dp, addr); + pudp =pud_offset_lockless (p4dp, p4d, addr); pud =READ_ONCE (*pudp);pr_cont (", pud=%016llx" ,pud_val (pud));if (pud_none (pud) ||pud_bad (pud))break ; - pmdp =pmd_offset (pudp, addr); + pmdp =pmd_offset_lockless (pudp, pud, addr); pmd =READ_ONCE (*pmdp);pr_cont (", pmd=%016llx" ,pmd_val (pmd));if (pmd_none (pmd) ||pmd_bad (pmd))break ; - ptep =pte_offset_map (pmdp, addr); + ptep =pte_offset_map (&pmd, addr);if (!ptep)break ;
Signature · 1 line
2.53.0