mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Kevin Brodsky <kevin.brodsky@arm.com>
To: linux-hardening@vger.kernel.org
Cc: "Kevin Brodsky" <kevin.brodsky@arm.com>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"Ard Biesheuvel" <ardb+git@google.com>,
	"Andy Lutomirski" <luto@kernel.org>,
	"Catalin Marinas" <catalin.marinas@arm.com>,
	"Dave Hansen" <dave.hansen@linux.intel.com>,
	"David Hildenbrand (Arm)" <david@kernel.org>,
	"Jann Horn" <jannh@google.com>, "Jeff Xu" <jeffxu@chromium.org>,
	"Joey Gouly" <joey.gouly@arm.com>, "Kees Cook" <kees@kernel.org>,
	"Linu Cherian" <linu.cherian@arm.com>,
	"Linus Walleij" <linusw@kernel.org>,
	"Marc Zyngier" <maz@kernel.org>,
	"Mark Brown" <broonie@kernel.org>,
	"Matthew Wilcox" <willy@infradead.org>,
	"Maxwell Bland" <mbland@motorola.com>,
	"Mike Rapoport (IBM)" <rppt@kernel.org>,
	"Peter Zijlstra" <peterz@infradead.org>,
	"Pierre Langlois" <pierre.langlois@arm.com>,
	"Pierre-Clément Tosi" <ptosi@google.com>,
	"Quentin Perret" <qperret@google.com>,
	"Rick Edgecombe" <rick.p.edgecombe@intel.com>,
	"Ryan Roberts" <ryan.roberts@arm.com>,
	"Vlastimil Babka" <vbabka@kernel.org>,
	"Will Deacon" <will@kernel.org>,
	"Yang Shi" <yang@os.amperecomputing.com>,
	"Yeoreum Yun" <yeoreum.yun@arm.com>,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org,
	x86@kernel.org, "Ira Weiny" <iweiny@kernel.org>,
	"Lorenzo Stoakes" <ljs@kernel.org>,
	"Thomas Gleixner" <tglx@kernel.org>
Subject: [PATCH RFC v10 14/22] mm: kpkeys: Protect vmemmap page tables
Date: Mon, 09 Nov 2026 15:58:39 +0000	[thread overview]
Message-ID: <20261109-kpkeys-v10-14-aa6c4d9603bc@arm.com> (raw)
In-Reply-To: <20261109-kpkeys-v10-0-aa6c4d9603bc@arm.com>

The kpkeys_hardened_pgtables feature automatically protect early
vmemmap page tables (covering standard boot memory) when it is
enabled.

In order to protect late vmemmap page tables  as well, allocate them
like regular page tables using pagetable_alloc().

pagetable_alloc() does the right thing to protect the backing pages
using kpkeys, but isn't NUMA-aware, so the pages may be allocated on
any node. This could potentially incur some overhead on large NUMA
systems that make heavy use of memory hotplug.

The arm64 hotplug code is also amended to use a matching
pagetable_free(), ensuring that the pkey is reset when the page
tables are freed. x86 already uses pagetable_free() on that path.

Unlike in vmemmap_alloc_block(), __GFP_RETRY_MAYFAIL is not used as
it isn't justified for allocating page tables - this disables the
OOM and we do not have a fallback if we fail to allocate page
tables. See previous discussion linked below.

Link: https://lore.kernel.org/all/38d2a358-4146-bfc9-2a4f-68ce02f75c94@suse.cz/
Signed-off-by: Kevin Brodsky <kevin.brodsky@arm.com>
---

This is a minimal patch to protect vmemmmap page tables. More work
may be needed here:

* Restoring NUMA awareness

* Moving the arm64 change to a separate commit?

* General refactoring of how these page tables are allocated: since
  we are not using the standard per-level functions (e.g.
  pmd_alloc()), we are not calling pagetable_*_ctor() or
  ptdesc_set_kernel(). I sent a separate series [1] that partially
  addresses this, but more work is still needed.

* x86 allows boot memory to be hot-removed in some circumstances.
  free_pagetable() should handle this situation by resetting the
  direct map pkey of reserved pages.

[1] https://lore.kernel.org/all/20260714-remove_pgtable_cdtor-v1-0-44be8a7685d7@arm.com/
---
 arch/arm64/mm/mmu.c |  2 +-
 mm/sparse-vmemmap.c | 23 ++++++++++++++++-------
 2 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 6a2155db3d05..a61ea65bd496 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -1496,7 +1496,7 @@ static void free_hotplug_page_range(struct page *page, size_t size,
 static void free_hotplug_pgtable_page(struct page *page)
 {
 	pagetable_dtor(page_ptdesc(page));
-	free_hotplug_page_range(page, PAGE_SIZE, NULL);
+	pagetable_free(page_ptdesc(page));
 }
 
 static bool pgtable_range_aligned(unsigned long start, unsigned long end,
diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c
index 5d7e982f94d0..c47d3a016891 100644
--- a/mm/sparse-vmemmap.c
+++ b/mm/sparse-vmemmap.c
@@ -150,13 +150,22 @@ int __meminit section_nr_vmemmap_pages(unsigned long pfn, unsigned long nr_pages
 	return 0;
 }
 
-static void * __meminit vmemmap_alloc_block_zero(unsigned long size, int node)
+static void * __meminit vmemmap_alloc_pgtable(int node)
 {
-	void *p = vmemmap_alloc_block(size, node);
+	void *p;
+
+	if (slab_is_available()) {
+		gfp_t gfp = GFP_KERNEL | __GFP_ZERO;
+		struct ptdesc *ptdesc = pagetable_alloc(gfp, 0);
+
+		return ptdesc ? ptdesc_address(ptdesc) : NULL;
+	}
+
+	p = vmemmap_alloc_block(PAGE_SIZE, node);
 
 	if (!p)
 		return NULL;
-	memset(p, 0, size);
+	memset(p, 0, PAGE_SIZE);
 
 	return p;
 }
@@ -305,7 +314,7 @@ static pmd_t * __meminit vmemmap_pmd_populate(pud_t *pud, unsigned long addr, in
 {
 	pmd_t *pmd = pmd_offset(pud, addr);
 	if (pmd_none(*pmd)) {
-		void *p = vmemmap_alloc_block_zero(PAGE_SIZE, node);
+		void *p = vmemmap_alloc_pgtable(node);
 		if (!p)
 			return NULL;
 		kernel_pte_init(p);
@@ -318,7 +327,7 @@ static pud_t * __meminit vmemmap_pud_populate(p4d_t *p4d, unsigned long addr, in
 {
 	pud_t *pud = pud_offset(p4d, addr);
 	if (pud_none(*pud)) {
-		void *p = vmemmap_alloc_block_zero(PAGE_SIZE, node);
+		void *p = vmemmap_alloc_pgtable(node);
 		if (!p)
 			return NULL;
 		pmd_init(p);
@@ -331,7 +340,7 @@ static p4d_t * __meminit vmemmap_p4d_populate(pgd_t *pgd, unsigned long addr, in
 {
 	p4d_t *p4d = p4d_offset(pgd, addr);
 	if (p4d_none(*p4d)) {
-		void *p = vmemmap_alloc_block_zero(PAGE_SIZE, node);
+		void *p = vmemmap_alloc_pgtable(node);
 		if (!p)
 			return NULL;
 		pud_init(p);
@@ -344,7 +353,7 @@ static pgd_t * __meminit vmemmap_pgd_populate(unsigned long addr, int node)
 {
 	pgd_t *pgd = pgd_offset_k(addr);
 	if (pgd_none(*pgd)) {
-		void *p = vmemmap_alloc_block_zero(PAGE_SIZE, node);
+		void *p = vmemmap_alloc_pgtable(node);
 		if (!p)
 			return NULL;
 		pgd_populate_kernel(addr, pgd, p);

-- 
2.56.0


  parent reply	other threads:[~2026-11-09 16:01 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-09 15:58 [PATCH RFC v10 00/22] pkeys-based page table hardening Kevin Brodsky
2026-11-09 15:58 ` [PATCH RFC v10 01/22] mm: Introduce kpkeys Kevin Brodsky
2026-11-09 15:58 ` [PATCH RFC v10 02/22] set_memory: Introduce set_direct_map_pkey() stub Kevin Brodsky
2026-11-09 15:58 ` [PATCH RFC v10 03/22] arm64: Introduce por_elx_set_pkey_perms() helper Kevin Brodsky
2026-11-09 15:58 ` [PATCH RFC v10 04/22] arm64: Implement asm/kpkeys.h using POE Kevin Brodsky
2026-11-09 15:58 ` [PATCH RFC v10 05/22] arm64: set_memory: Implement set_direct_map_pkey() Kevin Brodsky
2026-11-09 15:58 ` [PATCH RFC v10 06/22] arm64: Disable EL2 trapping of POR_EL1 Kevin Brodsky
2026-11-09 15:58 ` [PATCH RFC v10 07/22] arm64: Initialize POR_EL1 register on cpu_resume() Kevin Brodsky
2026-11-09 15:58 ` [PATCH RFC v10 08/22] arm64: Context-switch POR_EL1 Kevin Brodsky
2026-11-09 15:58 ` [PATCH RFC v10 09/22] arm64: mm: Enable overlays for all EL1 indirect permissions Kevin Brodsky
2026-11-09 15:58 ` [PATCH RFC v10 10/22] arm64: Enable kpkeys Kevin Brodsky
2026-11-09 15:58 ` [PATCH RFC v10 11/22] mm: kpkeys: Introduce kpkeys_hardened_pgtables feature Kevin Brodsky
2026-11-09 15:58 ` [PATCH RFC v10 12/22] mm: kpkeys: Protect regular page tables Kevin Brodsky
2026-11-09 15:58 ` [PATCH RFC v10 13/22] mm: kpkeys: Protect early kernel " Kevin Brodsky
2026-11-09 15:58 ` Kevin Brodsky [this message]
2026-11-09 15:58 ` [PATCH RFC v10 15/22] arm64: kpkeys: Implement arch_supports_kpkeys_early() Kevin Brodsky
2026-11-09 15:58 ` [PATCH RFC v10 16/22] arm64: kpkeys: Support KPKEYS_CTX_PGTABLES Kevin Brodsky
2026-11-09 15:58 ` [PATCH RFC v10 17/22] arm64: kpkeys: Ensure the linear map can be modified Kevin Brodsky
2026-11-09 15:58 ` [PATCH RFC v10 18/22] arm64: kpkeys: Guard page table writes Kevin Brodsky
2026-11-09 15:58 ` [PATCH RFC v10 19/22] arm64: kpkeys: Batch KPKEYS_CTX_PGTABLES switches Kevin Brodsky
2026-11-09 15:58 ` [PATCH RFC v10 20/22] arm64: kpkeys: Enable kpkeys_hardened_pgtables support Kevin Brodsky
2026-11-09 15:58 ` [PATCH RFC v10 21/22] arm64: mm: Map kernel image alias of init_pg_dir read-only Kevin Brodsky
2026-11-09 15:58 ` [PATCH RFC v10 22/22] mm: Add basic tests for kpkeys_hardened_pgtables Kevin Brodsky
2026-11-09 19:28   ` Mark Brown

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=20261109-kpkeys-v10-14-aa6c4d9603bc@arm.com \
    --to=kevin.brodsky@arm.com \
    --cc=akpm@linux-foundation.org \
    --cc=ardb+git@google.com \
    --cc=broonie@kernel.org \
    --cc=catalin.marinas@arm.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=david@kernel.org \
    --cc=iweiny@kernel.org \
    --cc=jannh@google.com \
    --cc=jeffxu@chromium.org \
    --cc=joey.gouly@arm.com \
    --cc=kees@kernel.org \
    --cc=linu.cherian@arm.com \
    --cc=linusw@kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-hardening@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=ljs@kernel.org \
    --cc=luto@kernel.org \
    --cc=maz@kernel.org \
    --cc=mbland@motorola.com \
    --cc=peterz@infradead.org \
    --cc=pierre.langlois@arm.com \
    --cc=ptosi@google.com \
    --cc=qperret@google.com \
    --cc=rick.p.edgecombe@intel.com \
    --cc=rppt@kernel.org \
    --cc=ryan.roberts@arm.com \
    --cc=tglx@kernel.org \
    --cc=vbabka@kernel.org \
    --cc=will@kernel.org \
    --cc=willy@infradead.org \
    --cc=x86@kernel.org \
    --cc=yang@os.amperecomputing.com \
    --cc=yeoreum.yun@arm.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

all inboxes | Powered by JetHome®