Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] kfence: fix pool allocation failure handling
@ 2026-10-26 12:23 Jackie Liu
  2026-10-26 12:23 ` [PATCH 1/3] kfence: fix pool cleanup on metadata allocation failure Jackie Liu
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Jackie Liu @ 2026-10-26 12:23 UTC (permalink / raw)
  To: glider
  Cc: dvyukov, elver, pjw, alex, aou, linux-riscv, linux-mm, kasan-dev,
	muchun.song, liu.yun

From: Jackie Liu <liuyun01@kylinos.cn>

Fix the cleanup address and page reuse window in failed late KFENCE
initialization. Also let RISC-V boot if the early pool reservation fails.

Patch 2 depends on patch 1. Patch 3 can be applied independently.

Validation: source review, git diff --check, and checkpatch.pl --strict.
OpenAI Codex assisted with review, adaptation, and commit wording.

Jackie Liu (3):
  kfence: fix pool cleanup on metadata allocation failure
  kfence: clear the pool pointer before freeing pages
  riscv: keep booting if KFENCE pool reservation fails

 arch/riscv/include/asm/kfence.h |  4 +++-
 arch/riscv/mm/init.c            | 19 +++++++++++++++----
 mm/kfence/core.c                |  6 ++++--
 3 files changed, 22 insertions(+), 7 deletions(-)


base-commit: 7be4bc52fd9e0e55dc9a2e0232b89427d2c4b614
-- 
2.56.0



^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/3] kfence: fix pool cleanup on metadata allocation failure
  2026-10-26 12:23 [PATCH 0/3] kfence: fix pool allocation failure handling Jackie Liu
@ 2026-10-26 12:23 ` Jackie Liu
  2026-10-26 13:08   ` Marco Elver
  2026-10-26 12:23 ` [PATCH 2/3] kfence: clear the pool pointer before freeing pages Jackie Liu
  2026-10-26 12:23 ` [PATCH 3/3] riscv: keep booting if KFENCE pool reservation fails Jackie Liu
  2 siblings, 1 reply; 7+ messages in thread
From: Jackie Liu @ 2026-10-26 12:23 UTC (permalink / raw)
  To: glider
  Cc: dvyukov, elver, pjw, alex, aou, linux-riscv, linux-mm, kasan-dev,
	muchun.song, liu.yun

From: Jackie Liu <liuyun01@kylinos.cn>

kfence_init_late() saves __kfence_pool in addr before allocating the pool,
so addr is still NULL if metadata allocation fails. The error path then
tries to free pages using that address.

Set addr after pool allocation so cleanup frees the allocated pool.

Fixes: cabdf74e6b31 ("mm: kfence: allocate kfence_metadata at runtime")
Cc: stable@vger.kernel.org
Signed-off-by: Jackie Liu <liuyun01@kylinos.cn>
---
 mm/kfence/core.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/mm/kfence/core.c b/mm/kfence/core.c
index 90925c646c4c..6e3d01bccdf1 100644
--- a/mm/kfence/core.c
+++ b/mm/kfence/core.c
@@ -999,7 +999,7 @@ static int kfence_init_late(void)
 {
 	const unsigned long nr_pages_pool = KFENCE_POOL_SIZE / PAGE_SIZE;
 	const unsigned long nr_pages_meta = KFENCE_METADATA_SIZE / PAGE_SIZE;
-	unsigned long addr = (unsigned long)__kfence_pool;
+	unsigned long addr;
 	unsigned long free_size = KFENCE_POOL_SIZE;
 	int err = -ENOMEM;
 
@@ -1032,6 +1032,7 @@ static int kfence_init_late(void)
 						 GFP_KERNEL | __GFP_SKIP_KASAN);
 #endif
 
+	addr = (unsigned long)__kfence_pool;
 	if (!kfence_metadata_init)
 		goto free_pool;
 
-- 
2.56.0



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/3] kfence: clear the pool pointer before freeing pages
  2026-10-26 12:23 [PATCH 0/3] kfence: fix pool allocation failure handling Jackie Liu
  2026-10-26 12:23 ` [PATCH 1/3] kfence: fix pool cleanup on metadata allocation failure Jackie Liu
@ 2026-10-26 12:23 ` Jackie Liu
  2026-10-26 13:10   ` Marco Elver
  2026-10-26 12:23 ` [PATCH 3/3] riscv: keep booting if KFENCE pool reservation fails Jackie Liu
  2 siblings, 1 reply; 7+ messages in thread
From: Jackie Liu @ 2026-10-26 12:23 UTC (permalink / raw)
  To: glider
  Cc: dvyukov, elver, pjw, alex, aou, linux-riscv, linux-mm, kasan-dev,
	muchun.song, liu.yun

From: Jackie Liu <liuyun01@kylinos.cn>

Late initialization frees a failed pool before clearing __kfence_pool.
Slab allocations can reuse those pages in between and be mistaken for
KFENCE objects by is_kfence_address(), even though KFENCE is not enabled.

Clear __kfence_pool before freeing the pages, and use the saved address
for cleanup.

Fixes: b33f778bba5e ("kfence: alloc kfence_pool after system startup")
Cc: stable@vger.kernel.org
Signed-off-by: Jackie Liu <liuyun01@kylinos.cn>
---
 mm/kfence/core.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/mm/kfence/core.c b/mm/kfence/core.c
index 6e3d01bccdf1..434df6cef7f2 100644
--- a/mm/kfence/core.c
+++ b/mm/kfence/core.c
@@ -1052,16 +1052,17 @@ static int kfence_init_late(void)
 	free_contig_range(page_to_pfn(virt_to_page((void *)kfence_metadata_init)),
 			  nr_pages_meta);
 free_pool:
+	WRITE_ONCE(__kfence_pool, NULL);
 	free_contig_range(page_to_pfn(virt_to_page((void *)addr)),
 			  free_size / PAGE_SIZE);
 #else
 	free_pages_exact((void *)kfence_metadata_init, KFENCE_METADATA_SIZE);
 free_pool:
+	WRITE_ONCE(__kfence_pool, NULL);
 	free_pages_exact((void *)addr, free_size);
 #endif
 
 	kfence_metadata_init = NULL;
-	__kfence_pool = NULL;
 	return err;
 }
 
-- 
2.56.0



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/3] riscv: keep booting if KFENCE pool reservation fails
  2026-10-26 12:23 [PATCH 0/3] kfence: fix pool allocation failure handling Jackie Liu
  2026-10-26 12:23 ` [PATCH 1/3] kfence: fix pool cleanup on metadata allocation failure Jackie Liu
  2026-10-26 12:23 ` [PATCH 2/3] kfence: clear the pool pointer before freeing pages Jackie Liu
@ 2026-10-26 12:23 ` Jackie Liu
  2026-10-27 12:23   ` sashiko-bot
  2 siblings, 1 reply; 7+ messages in thread
From: Jackie Liu @ 2026-10-26 12:23 UTC (permalink / raw)
  To: glider
  Cc: dvyukov, elver, pjw, alex, aou, linux-riscv, linux-mm, kasan-dev,
	muchun.song, liu.yun

From: Jackie Liu <liuyun01@kylinos.cn>

A failed KFENCE pool reservation hits BUG_ON() and stops boot. Continue
building the linear map and disable KFENCE if the reservation fails.

Reject later pool initialization as well, since a replacement pool may
have huge-page mappings that kfence_protect_page() cannot handle.

Fixes: 25abe0db9243 ("riscv: Fix kfence now that the linear mapping can be backed by PUD/P4D/PGD")
Cc: stable@vger.kernel.org
Signed-off-by: Jackie Liu <liuyun01@kylinos.cn>
---
 arch/riscv/include/asm/kfence.h |  4 +++-
 arch/riscv/mm/init.c            | 19 +++++++++++++++----
 2 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/arch/riscv/include/asm/kfence.h b/arch/riscv/include/asm/kfence.h
index 29cb3a6ee113..57e57426a7d6 100644
--- a/arch/riscv/include/asm/kfence.h
+++ b/arch/riscv/include/asm/kfence.h
@@ -9,9 +9,11 @@
 #include <asm/cacheflush.h>
 #include <asm/pgtable.h>
 
+extern bool kfence_disabled;
+
 static inline bool arch_kfence_init_pool(void)
 {
-	return true;
+	return !kfence_disabled;
 }
 
 static inline bool kfence_protect_page(unsigned long addr, bool protect)
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index fb37b0b67efe..393106cd25ba 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -27,6 +27,7 @@
 #include <asm/fixmap.h>
 #include <asm/io.h>
 #include <asm/kasan.h>
+#include <asm/kfence.h>
 #include <asm/module.h>
 #include <asm/numa.h>
 #include <asm/pgtable.h>
@@ -44,6 +45,10 @@ DECLARE_BITMAP(new_valid_map_cpus, NR_CPUS);
 struct kernel_mapping kernel_map __ro_after_init;
 EXPORT_SYMBOL(kernel_map);
 
+#ifdef CONFIG_KFENCE
+bool kfence_disabled __ro_after_init;
+#endif
+
 #ifdef CONFIG_64BIT
 u64 satp_mode __ro_after_init = SATP_MODE_57;
 #else
@@ -1229,10 +1234,13 @@ static void __init create_linear_mapping_page_table(void)
 	 *  for this region.
 	 */
 	kfence_pool = memblock_phys_alloc(KFENCE_POOL_SIZE, PAGE_SIZE);
-	BUG_ON(!kfence_pool);
-
-	memblock_mark_nomap(kfence_pool, KFENCE_POOL_SIZE);
-	__kfence_pool = __va(kfence_pool);
+	if (kfence_pool) {
+		memblock_mark_nomap(kfence_pool, KFENCE_POOL_SIZE);
+		__kfence_pool = __va(kfence_pool);
+	} else {
+		pr_err("failed to allocate kfence pool\n");
+		kfence_disabled = true;
+	}
 #endif
 
 	/* Map all memory banks in the linear mapping */
@@ -1253,6 +1261,9 @@ static void __init create_linear_mapping_page_table(void)
 #endif
 
 #ifdef CONFIG_KFENCE
+	if (!kfence_pool)
+		return;
+
 	create_linear_mapping_range(kfence_pool, kfence_pool + KFENCE_POOL_SIZE, PAGE_SIZE, NULL);
 
 	memblock_clear_nomap(kfence_pool, KFENCE_POOL_SIZE);
-- 
2.56.0



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/3] kfence: fix pool cleanup on metadata allocation failure
  2026-10-26 12:23 ` [PATCH 1/3] kfence: fix pool cleanup on metadata allocation failure Jackie Liu
@ 2026-10-26 13:08   ` Marco Elver
  0 siblings, 0 replies; 7+ messages in thread
From: Marco Elver @ 2026-10-26 13:08 UTC (permalink / raw)
  To: Jackie Liu
  Cc: glider, dvyukov, pjw, alex, aou, linux-riscv, linux-mm, kasan-dev,
	muchun.song

On Mon, 26 Oct 2026 at 13:23, Jackie Liu <liu.yun@linux.dev> wrote:
>
> From: Jackie Liu <liuyun01@kylinos.cn>
>
> kfence_init_late() saves __kfence_pool in addr before allocating the pool,
> so addr is still NULL if metadata allocation fails. The error path then
> tries to free pages using that address.
>
> Set addr after pool allocation so cleanup frees the allocated pool.
>
> Fixes: cabdf74e6b31 ("mm: kfence: allocate kfence_metadata at runtime")
> Cc: stable@vger.kernel.org
> Signed-off-by: Jackie Liu <liuyun01@kylinos.cn>

Reviewed-by: Marco Elver <elver@google.com>

> ---
>  mm/kfence/core.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/mm/kfence/core.c b/mm/kfence/core.c
> index 90925c646c4c..6e3d01bccdf1 100644
> --- a/mm/kfence/core.c
> +++ b/mm/kfence/core.c
> @@ -999,7 +999,7 @@ static int kfence_init_late(void)
>  {
>         const unsigned long nr_pages_pool = KFENCE_POOL_SIZE / PAGE_SIZE;
>         const unsigned long nr_pages_meta = KFENCE_METADATA_SIZE / PAGE_SIZE;
> -       unsigned long addr = (unsigned long)__kfence_pool;
> +       unsigned long addr;
>         unsigned long free_size = KFENCE_POOL_SIZE;
>         int err = -ENOMEM;
>
> @@ -1032,6 +1032,7 @@ static int kfence_init_late(void)
>                                                  GFP_KERNEL | __GFP_SKIP_KASAN);
>  #endif
>
> +       addr = (unsigned long)__kfence_pool;
>         if (!kfence_metadata_init)
>                 goto free_pool;
>
> --
> 2.56.0
>


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/3] kfence: clear the pool pointer before freeing pages
  2026-10-26 12:23 ` [PATCH 2/3] kfence: clear the pool pointer before freeing pages Jackie Liu
@ 2026-10-26 13:10   ` Marco Elver
  0 siblings, 0 replies; 7+ messages in thread
From: Marco Elver @ 2026-10-26 13:10 UTC (permalink / raw)
  To: Jackie Liu
  Cc: glider, dvyukov, pjw, alex, aou, linux-riscv, linux-mm, kasan-dev,
	muchun.song

On Mon, 26 Oct 2026 at 13:23, Jackie Liu <liu.yun@linux.dev> wrote:
>
> From: Jackie Liu <liuyun01@kylinos.cn>
>
> Late initialization frees a failed pool before clearing __kfence_pool.
> Slab allocations can reuse those pages in between and be mistaken for
> KFENCE objects by is_kfence_address(), even though KFENCE is not enabled.
>
> Clear __kfence_pool before freeing the pages, and use the saved address
> for cleanup.
>
> Fixes: b33f778bba5e ("kfence: alloc kfence_pool after system startup")
> Cc: stable@vger.kernel.org
> Signed-off-by: Jackie Liu <liuyun01@kylinos.cn>

Reviewed-by: Marco Elver <elver@google.com>

> ---
>  mm/kfence/core.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/mm/kfence/core.c b/mm/kfence/core.c
> index 6e3d01bccdf1..434df6cef7f2 100644
> --- a/mm/kfence/core.c
> +++ b/mm/kfence/core.c
> @@ -1052,16 +1052,17 @@ static int kfence_init_late(void)
>         free_contig_range(page_to_pfn(virt_to_page((void *)kfence_metadata_init)),
>                           nr_pages_meta);
>  free_pool:
> +       WRITE_ONCE(__kfence_pool, NULL);
>         free_contig_range(page_to_pfn(virt_to_page((void *)addr)),
>                           free_size / PAGE_SIZE);
>  #else
>         free_pages_exact((void *)kfence_metadata_init, KFENCE_METADATA_SIZE);
>  free_pool:
> +       WRITE_ONCE(__kfence_pool, NULL);
>         free_pages_exact((void *)addr, free_size);
>  #endif
>
>         kfence_metadata_init = NULL;
> -       __kfence_pool = NULL;
>         return err;
>  }
>
> --
> 2.56.0
>


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 3/3] riscv: keep booting if KFENCE pool reservation fails
  2026-10-26 12:23 ` [PATCH 3/3] riscv: keep booting if KFENCE pool reservation fails Jackie Liu
@ 2026-10-27 12:23   ` sashiko-bot
  0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-10-27 12:23 UTC (permalink / raw)
  To: Jackie Liu, glider
  Cc: dvyukov, elver, pjw, alex, aou, linux-mm, kasan-dev, muchun.song

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] riscv: build failure on 32-bit and NOMMU from including asm/kfence.h
--

commit d964a4c4107a3db6e2c99928c0888060598196ba
Author: Jackie Liu <liuyun01@kylinos.cn>

riscv: keep booting if KFENCE pool reservation fails

This commit avoids hitting BUG_ON() when the early KFENCE pool reservation
fails in create_linear_mapping_page_table(), disabling KFENCE instead so the
kernel can continue booting.

> diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
> index fb37b0b67efec..393106cd25ba0 100644
> --- a/arch/riscv/mm/init.c
> +++ b/arch/riscv/mm/init.c
> @@ -27,6 +27,7 @@
>  #include <asm/fixmap.h>
>  #include <asm/io.h>
>  #include <asm/kasan.h>
> +#include <asm/kfence.h>

[Severity: Low]
Does including asm/kfence.h unconditionally in arch/riscv/mm/init.c break
32-bit (CONFIG_32BIT=y) and NOMMU (CONFIG_MMU=n) RISC-V builds?

arch/riscv/mm/init.c is built unconditionally for all RISC-V configurations,
whereas HAVE_ARCH_KFENCE is only selected when MMU && 64BIT. In
arch/riscv/include/asm/kfence.h, kfence_protect_page() is defined outside of
any CONFIG_KFENCE guard:

arch/riscv/include/asm/kfence.h:
static inline bool kfence_protect_page(unsigned long addr, bool protect)
{
	pte_t *pte = virt_to_kpte(addr);

	if (protect) {
		set_pte(pte, __pte(pte_val(ptep_get(pte)) & ~_PAGE_PRESENT));
	} else {
		set_pte(pte, __pte(pte_val(ptep_get(pte)) | _PAGE_PRESENT));
		mark_new_valid_map();
	}

	preempt_disable();
	local_flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
	preempt_enable();

	return true;
}

On 32-bit builds, mark_new_valid_map() is not declared because
arch/riscv/include/asm/cacheflush.h guards it under
#if defined(CONFIG_64BIT) && defined(CONFIG_MMU) with no fallback stub.

On NOMMU builds, virt_to_kpte() in include/linux/pgtable.h,
set_pte() / __pte() / pte_val() / ptep_get() in
arch/riscv/include/asm/pgtable.h, mark_new_valid_map() in
arch/riscv/include/asm/cacheflush.h, and local_flush_tlb_kernel_range() in
arch/riscv/include/asm/tlbflush.h are all guarded by #ifdef CONFIG_MMU and
are undeclared when compiling kfence_protect_page().

Should the include in arch/riscv/mm/init.c or the contents of
arch/riscv/include/asm/kfence.h be guarded by #ifdef CONFIG_KFENCE?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1793017073.git.liuyun01@kylinos.cn?part=3


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-10-27 12:23 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-26 12:23 [PATCH 0/3] kfence: fix pool allocation failure handling Jackie Liu
2026-10-26 12:23 ` [PATCH 1/3] kfence: fix pool cleanup on metadata allocation failure Jackie Liu
2026-10-26 13:08   ` Marco Elver
2026-10-26 12:23 ` [PATCH 2/3] kfence: clear the pool pointer before freeing pages Jackie Liu
2026-10-26 13:10   ` Marco Elver
2026-10-26 12:23 ` [PATCH 3/3] riscv: keep booting if KFENCE pool reservation fails Jackie Liu
2026-10-27 12:23   ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox