KHO: kfence + KHO memory corruption fix
Subsystems (5)
Pasha Tatashin
maintainerv3 cover KHO: kfence + KHO memory corruption fix
This series fixes a memory corruption bug in KHO that occurs when KFENCE is enabled.
The root cause is that KHO metadata, allocated via kzalloc(), can be randomly serviced by kfence_alloc(). When a kernel boots via KHO, the early memblock allocator is restricted to a "scratch area". This forces the KFENCE pool to be allocated within this scratch area, creating a conflict. If KHO metadata is subsequently placed in this pool, it gets corrupted during the next kexec operation.
Patch 1/3 introduces a debug-only feature (CONFIG_KEXEC_HANDOVER_DEBUG) that adds checks to detect and fail any operation that attempts to place KHO metadata or preserved memory within the scratch area. This serves as a validation and diagnostic tool to confirm the problem without affecting production builds.
Patch 2/3 Increases bitmap to PAGE_SIZE, so buddy allocator can be used.
Patch 3/3 Provides the fix by modifying KHO to allocate its metadata directly from the buddy allocator instead of slab. This bypasses the KFENCE interception entirely.
Pasha Tatashin (3):
liveupdate: kho: warn and fail on metadata or preserved memory in
scratch area
liveupdate: kho: Increase metadata bitmap size to PAGE_SIZE
liveupdate: kho: allocate metadata directly from the buddy allocator
include/linux/gfp.h | 3 ++ kernel/Kconfig.kexec | 9 ++++ kernel/Makefile | 1 + kernel/kexec_handover.c | 72 ++++++++++++++++++++------------ kernel/kexec_handover_debug.c | 25 +++++++++++ kernel/kexec_handover_internal.h | 16 +++++++ 6 files changed, 100 insertions(+), 26 deletions(-) create mode 100644 kernel/kexec_handover_debug.c create mode 100644 kernel/kexec_handover_internal.h
base-commit: 6548d364a3e850326831799d7e3ea2d7bb97ba08
Signature · 1 line
2.51.0.869.ge66316f041-goog
Pasha Tatashin
maintainerPATCH v3 1/3 liveupdate: kho: warn and fail on metadata or preserved memory in scratch area
It is invalid for KHO metadata or preserved memory regions to be located within the KHO scratch area, as this area is overwritten when the next kernel is loaded, and used early in boot by the next kernel. This can lead to memory corruption.
Adds checks to kho_preserve_* and KHO's internal metadata allocators (xa_load_or_alloc, new_chunk) to verify that the physical address of the memory does not overlap with any defined scratch region. If an overlap is detected, the operation will fail and a WARN_ON is triggered. To avoid performance overhead in production kernels, these checks are enabled only when CONFIG_KEXEC_HANDOVER_DEBUG is selected.
--- kernel/Kconfig.kexec | 9 ++++++ kernel/Makefile | 1 + kernel/kexec_handover.c | 53 ++++++++++++++++++++++---------- kernel/kexec_handover_debug.c | 25 +++++++++++++++ kernel/kexec_handover_internal.h | 16 ++++++++++ 5 files changed, 87 insertions(+), 17 deletions(-) create mode 100644 kernel/kexec_handover_debug.c create mode 100644 kernel/kexec_handover_internal.h
kernel/Kconfig.kexec +9 -0
@@ -109,6 +109,15 @@ config KEXEC_HANDOVER to keep data or state alive across the kexec. For this to work, both source and target kernels need to have this option enabled. +config KEXEC_HANDOVER_DEBUG + bool "Enable Kexec Handover debug checks" + depends on KEXEC_HANDOVER_DEBUGFS + help + This option enables extra sanity checks for the Kexec Handover + subsystem. Since, KHO performance is crucial in live update + scenarios and the extra code might be adding overhead it is + only optionally enabled. + config CRASH_DUMP bool "kernel crash dumps" default ARCH_DEFAULT_CRASH_DUMP
kernel/Makefile +1 -0
@@ -83,6 +83,7 @@ obj-$(CONFIG_KEXEC) += kexec.o obj-$(CONFIG_KEXEC_FILE) += kexec_file.o obj-$(CONFIG_KEXEC_ELF) += kexec_elf.o obj-$(CONFIG_KEXEC_HANDOVER) += kexec_handover.o +obj-$(CONFIG_KEXEC_HANDOVER_DEBUG) += kexec_handover_debug.o obj-$(CONFIG_BACKTRACE_SELF_TEST) += backtracetest.o obj-$(CONFIG_COMPAT) += compat.o obj-$(CONFIG_CGROUPS) += cgroup/
kernel/kexec_handover.c +36 -17
130 lines not on this page · raw message
kernel/kexec_handover_debug.c new file +25 -0
@@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +* kexec_handover_debug.c - kexec handover optional debug functionality +* Copyright (C) 2025 Google LLC, Pasha Tatashin <[email protected]> +*/ + +#define pr_fmt (fmt) "KHO: " fmt + +#include "kexec_handover_internal.h" + +bool kho_scratch_overlap (phys_addr_t phys,size_t size) +{ +phys_addr_t scratch_start, scratch_end; +unsigned int i; + +for (i =0 ; i < kho_scratch_cnt; i++) { + scratch_start = kho_scratch[i].addr; + scratch_end = kho_scratch[i].addr + kho_scratch[i].size; + +if (phys < scratch_end && (phys + size) > scratch_start) +return true; + } + +return false; +}
kernel/kexec_handover_internal.h new file +16 -0
@@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef LINUX_KEXEC_HANDOVER_INTERNAL_H +#define LINUX_KEXEC_HANDOVER_INTERNAL_H + +#include <linux/types.h> + +#ifdef CONFIG_KEXEC_HANDOVER_DEBUG +bool kho_scratch_overlap (phys_addr_t phys,size_t size); +#else +static inline bool kho_scratch_overlap (phys_addr_t phys,size_t size) +{ +return false; +} +#endif /* CONFIG_KEXEC_HANDOVER_DEBUG */ + +#endif /* LINUX_KEXEC_HANDOVER_INTERNAL_H */
Signature · 1 line
2.51.0.869.ge66316f041-goog
Re: [PATCH v3 1/3] liveupdate: kho: warn and fail on metadata or preserved memory in scratch area
Quoted 13 lines · Pasha Tatashin
It is invalid for KHO metadata or preserved memory regions to be located within the KHO scratch area, as this area is overwritten when the next kernel is loaded, and used early in boot by the next kernel. This can lead to memory corruption.
Adds checks to kho_preserve_* and KHO's internal metadata allocators (
xa_load_or_alloc,new_chunk) to verify that the physical address of the memory does not overlap with any defined scratch region. If an overlap is detected, the operation will fail and aWARN_ONis triggered. To avoid performance overhead in production kernels, these checks are enabled only whenCONFIG_KEXEC_HANDOVER_DEBUGis selected.Signed-off-by Pasha Tatashin <[email protected]>
[...]
Quoted 25 lines
kernel/kexec_handover.c +8
-6@@ -133,26 +135,26 @@ static struct kho_out kho_out = {static void *xa_load_or_alloc (struct xarray *xa,unsigned long index,size_t sz) { -void *elm, *res; +void *res =xa_load (xa, index); - elm =xa_load (xa, index); -if (elm) -return elm; +if (res) +return res; + + void *elm __free(kfree) = kzalloc(sz, GFP_KERNEL); - elm =kzalloc (sz,GFP_KERNEL );if (!elm)return ERR_PTR (-ENOMEM ); +if (WARN_ON (kho_scratch_overlap (virt_to_phys (elm), sz))) +return ERR_PTR (-EINVAL ); + res =xa_cmpxchg (xa, index,NULL , elm,GFP_KERNEL );if (xa_is_err (res)) - res =ERR_PTR (xa_err (res));
kernel/kexec_handover.c static struct kho_out kho_out = { · line 157
Quoted 10 lines
kernel/kexec_handover.c +3
-5- -if (res) { -kfree (elm); +return ERR_PTR (xa_err (res)); + else if (res) return res; - } -return elm; + return no_free_ptr(elm);
Super small nit: there exists return_ptr(p) which is a tiny bit neater IMO but certainly not worth doing a new revision over. So,
[...]
Signature · 2 lines
Regards, Pratyush Yadav
Re: [PATCH v3 1/3] liveupdate: kho: warn and fail on metadata or preserved memory in scratch area
In reply to Pasha TatashinQuoted 6 lines · Pasha Tatashin
It is invalid for KHO metadata or preserved memory regions to be located within the KHO scratch area, as this area is overwritten when the next kernel is loaded, and used early in boot by the next kernel. This can lead to memory corruption.
Quoted 6 lines
Adds checks to kho_preserve_* and KHO's internal metadata allocators (
xa_load_or_alloc,new_chunk) to verify that the physical address of the memory does not overlap with any defined scratch region. If an overlap is detected, the operation will fail and aWARN_ONis triggered. To avoid performance overhead in production kernels, these checks are enabled only whenCONFIG_KEXEC_HANDOVER_DEBUGis selected.
How many scratch regions are there in practice? Checking unconditionally seems like a small price to pay to avoid possible memory corruption. Especially since most KHO preservation should happen while the VM is still running (so does not have to by hyper-optimized).
kernel/kexec_handover.c static struct kho_out kho_out = { · line 143
Quoted 12 lines
static void *xa_load_or_alloc(struct xarray *xa, unsigned long index,
size_tsz) {kernel/kexec_handover.c +5
-4-void *elm, *res; +void *res =xa_load (xa, index); - elm =xa_load (xa, index); -if (elm) -return elm; +if (res) +return res; + + void *elm __free(kfree) = kzalloc(sz, GFP_KERNEL);
nit: This breaks the local style of always declaring variables at the beginning of blocks.
Pasha Tatashin
maintainerRe: [PATCH v3 1/3] liveupdate: kho: warn and fail on metadata or preserved memory in scratch area
Quoted 16 lines · David Matlack
Quoted 6 lines · Pasha Tatashin
It is invalid for KHO metadata or preserved memory regions to be located within the KHO scratch area, as this area is overwritten when the next kernel is loaded, and used early in boot by the next kernel. This can lead to memory corruption.
Quoted 6 lines
Adds checks to kho_preserve_* and KHO's internal metadata allocators (
xa_load_or_alloc,new_chunk) to verify that the physical address of the memory does not overlap with any defined scratch region. If an overlap is detected, the operation will fail and aWARN_ONis triggered. To avoid performance overhead in production kernels, these checks are enabled only whenCONFIG_KEXEC_HANDOVER_DEBUGis selected.
Quoted 5 lines
How many scratch regions are there in practice? Checking unconditionally seems like a small price to pay to avoid possible memory corruption. Especially since most KHO preservation should happen while the VM is still running (so does not have to by hyper-optimized).
The debug option can be enabled on production system as well, we have some debug options enabled, but I do not see a reason to make this a fixed cost that can add up; the runtime cost scares me, as we might be using KHO preserve/unpreserve often once stateless KHO + slab preservation is implemented during some allocations paths. Let's keep it optional.
Quoted 14 lines
kernel/kexec_handover.c static struct kho_out kho_out = { · line 143
Quoted 13 lines
static void *xa_load_or_alloc(struct xarray *xa, unsigned long index,
size_tsz) {kernel/kexec_handover.c +5
-4-void *elm, *res; +void *res =xa_load (xa, index); - elm =xa_load (xa, index); -if (elm) -return elm; +if (res) +return res; + + void *elm __free(kfree) = kzalloc(sz, GFP_KERNEL);
Quoted 2 lines
nit: This breaks the local style of always declaring variables at the beginning of blocks.
I think this suggestion came from Mike, to me it looks alright, as it is only part of the clean-up path.
Pasha
Re: [PATCH v3 1/3] liveupdate: kho: warn and fail on metadata or preserved memory in scratch area
Quoted 13 lines · Pasha Tatashin
Quoted 13 lines
Quoted 12 lines
static void *xa_load_or_alloc(struct xarray *xa, unsigned long index,
size_tsz) {kernel/kexec_handover.c +5
-4-void *elm, *res; +void *res =xa_load (xa, index); - elm =xa_load (xa, index); -if (elm) -return elm; +if (res) +return res; + + void *elm __free(kfree) = kzalloc(sz, GFP_KERNEL);
Quoted 5 lines
Quoted 2 lines
nit: This breaks the local style of always declaring variables at the beginning of blocks.
I think this suggestion came from Mike, to me it looks alright, as it is only part of the clean-up path.
It is the recommended style for using cleanup.h stuff, declare and assign in one statement.
Jason
Mike Rapoport
maintainerRe: [PATCH v3 1/3] liveupdate: kho: warn and fail on metadata or preserved memory in scratch area
In reply to Pasha TatashinHi Pasha,
Quoted 28 lines · Pasha Tatashin
It is invalid for KHO metadata or preserved memory regions to be located within the KHO scratch area, as this area is overwritten when the next kernel is loaded, and used early in boot by the next kernel. This can lead to memory corruption.
Adds checks to kho_preserve_* and KHO's internal metadata allocators (
xa_load_or_alloc,new_chunk) to verify that the physical address of the memory does not overlap with any defined scratch region. If an overlap is detected, the operation will fail and aWARN_ONis triggered. To avoid performance overhead in production kernels, these checks are enabled only whenCONFIG_KEXEC_HANDOVER_DEBUGis selected.Signed-off-by Pasha Tatashin <[email protected]>--- kernel/Kconfig.kexec | 9 ++++++ kernel/Makefile | 1 + kernel/kexec_handover.c | 53 ++++++++++++++++++++++---------- kernel/kexec_handover_debug.c | 25 +++++++++++++++ kernel/kexec_handover_internal.h | 16 ++++++++++ 5 files changed, 87 insertions(+), 17 deletions(-) create mode 100644 kernel/kexec_handover_debug.c create mode 100644 kernel/kexec_handover_internal.hkernel/Kconfig.kexec +0
-0
kernel/Kconfig.kexec config KEXEC_HANDOVER · line 114
Quoted 6 lines
kernel/Kconfig.kexec +3
-0@@ -109,6 +109,15 @@ config KEXEC_HANDOVER to keep data or state alive across the kexec. For this to work, both source and target kernels need to have this option enabled. +config KEXEC_HANDOVER_DEBUG + bool "Enable Kexec Handover debug checks" + depends on KEXEC_HANDOVER_DEBUGFS
I missed that in the earlier review, should be "depends on KEXEC_HANDOVER"
@Andrew, can you please fold this into what's now commit 0e0faeffd144 ("kho: warn and fail on metadata or preserved memory in scratch area")
kernel/Kconfig.kexec +1 -1
@@ -111,7 +111,7 @@ config KEXEC_HANDOVER config KEXEC_HANDOVER_DEBUG bool "Enable Kexec Handover debug checks" - depends on KEXEC_HANDOVER_DEBUGFS + depends on KEXEC_HANDOVER help This option enables extra sanity checks for the Kexec Handover subsystem. Since, KHO performance is crucial in live update
Quoted 9 lines
kernel/Kconfig.kexec +6
-0+ help + This option enables extra sanity checks for the Kexec Handover + subsystem. Since, KHO performance is crucial in live update + scenarios and the extra code might be adding overhead it is + only optionally enabled. + config CRASH_DUMP bool "kernel crash dumps" default ARCH_DEFAULT_CRASH_DUMP
Signature · 2 lines
Sincerely yours, Mike.
Pasha Tatashin
maintainerRe: [PATCH v3 1/3] liveupdate: kho: warn and fail on metadata or preserved memory in scratch area
Hi Andrew,
Would you like me to resend the series with the "+ depends onKEXEC_HANDOVER" fix from Mike, or would you apply it into your tree directly?
Thank you,
Pasha
Quoted 71 lines · Mike Rapoport
Hi Pasha,
Quoted 28 lines · Pasha Tatashin
It is invalid for KHO metadata or preserved memory regions to be located within the KHO scratch area, as this area is overwritten when the next kernel is loaded, and used early in boot by the next kernel. This can lead to memory corruption.
Adds checks to kho_preserve_* and KHO's internal metadata allocators (
xa_load_or_alloc,new_chunk) to verify that the physical address of the memory does not overlap with any defined scratch region. If an overlap is detected, the operation will fail and aWARN_ONis triggered. To avoid performance overhead in production kernels, these checks are enabled only whenCONFIG_KEXEC_HANDOVER_DEBUGis selected.Signed-off-by Pasha Tatashin <[email protected]>--- kernel/Kconfig.kexec | 9 ++++++ kernel/Makefile | 1 + kernel/kexec_handover.c | 53 ++++++++++++++++++++++---------- kernel/kexec_handover_debug.c | 25 +++++++++++++++ kernel/kexec_handover_internal.h | 16 ++++++++++ 5 files changed, 87 insertions(+), 17 deletions(-) create mode 100644 kernel/kexec_handover_debug.c create mode 100644 kernel/kexec_handover_internal.hkernel/Kconfig.kexec +0
-0kernel/Kconfig.kexec config KEXEC_HANDOVER · line 114
Quoted 6 lines
kernel/Kconfig.kexec +3
-0@@ -109,6 +109,15 @@ config KEXEC_HANDOVER to keep data or state alive across the kexec. For this to work, both source and target kernels need to have this option enabled. +config KEXEC_HANDOVER_DEBUG + bool "Enable Kexec Handover debug checks" + depends on KEXEC_HANDOVER_DEBUGFSI missed that in the earlier review, should be "depends on
KEXEC_HANDOVER"@Andrew, can you please fold this into what's now commit
0e0faeffd144("kho: warn and fail on metadata or preserved memory in scratch area")kernel/Kconfig.kexec +1
-1@@ -111,7 +111,7 @@ config KEXEC_HANDOVER config KEXEC_HANDOVER_DEBUG bool "Enable Kexec Handover debug checks" - depends on KEXEC_HANDOVER_DEBUGFS + depends on KEXEC_HANDOVER help This option enables extra sanity checks for the Kexec Handover subsystem. Since, KHO performance is crucial in live updatekernel/Kconfig.kexec config KEXEC_HANDOVER · line 123
Quoted 10 lines
kernel/Kconfig.kexec +6
-0+ help + This option enables extra sanity checks for the Kexec Handover + subsystem. Since, KHO performance is crucial in live update + scenarios and the extra code might be adding overhead it is + only optionally enabled. + config CRASH_DUMP bool "kernel crash dumps" default ARCH_DEFAULT_CRASH_DUMP--
Sincerely yours,
Mike.
Andrew Morton
maintainerRe: [PATCH v3 1/3] liveupdate: kho: warn and fail on metadata or preserved memory in scratch area
Quoted 3 lines · On Wed, 29 Oct 2025 18:22:46 -0400 Pasha Tatashin <[email protected]>…
Would you like me to resend the series with the "+ depends on
KEXEC_HANDOVER" fix from Mike, or would you apply it into your tree directly?
Let's not be resending a patch series for a one-line fix! I'll add Mike's fix as a -fix patch.
Pasha Tatashin
maintainerPATCH v3 2/3 liveupdate: kho: Increase metadata bitmap size to PAGE_SIZE
In reply to Pasha TatashinKHO memory preservation metadata is preserved in 512 byte chunks which requires their allocation from slab allocator. Slabs are not safe to be used with KHO because of kfence, and because partial slabs may lead leaks to the next kernel. Change the size to be PAGE_SIZE.
The kfence specifically may cause memory corruption, where it randomly provides slab objects that can be within the scratch area. The reason for that is that kfence allocates its objects prior to KHO scratch is marked as CMA region.
While this change could potentially increase metadata overhead on systems with sparsely preserved memory, this is being mitigated by ongoing work to reduce sparseness during preservation via 1G guest pages. Furthermore, this change aligns with future work on a stateless KHO, which will also use page-sized bitmaps for its radix tree metadata.
--- kernel/kexec_handover.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-)
kernel/kexec_handover.c +11 -10
@@ -69,10 +69,10 @@ early_param("kho", kho_parse_enable);* Keep track of memory that is to be preserved across KHO. * * The serializing side uses two levels of xarrays to manage chunks of per-order -* 512 byte bitmaps. For instance if PAGE_SIZE = 4096, the entire 1G order of a -* 1TB system would fit inside a single 512 byte bitmap. For order 0 allocations -* each bitmap will cover 16M of address space. Thus, for 16G of memory at most -* 512K of bitmap memory will be needed for order 0. +* PAGE_SIZE byte bitmaps. For instance if PAGE_SIZE = 4096, the entire 1G order +* of a 8TB system would fit inside a single 4096 byte bitmap. For order 0 +* allocations each bitmap will cover 128M of address space. Thus, for 16G of +* memory at most 512K of bitmap memory will be needed for order 0. * * This approach is fully incremental, as the serialization progresses folios * can continue be aggregated to the tracker. The final step, immediately prior
@@ -80,12 +80,14 @@ early_param("kho", kho_parse_enable);* successor kernel to parse. */ -#define PRESERVE_BITS (512 * 8) +#define PRESERVE_BITS (PAGE_SIZE * 8)struct kho_mem_phys_bits { DECLARE_BITMAP(preserve, PRESERVE_BITS); }; +static_assert (sizeof (struct kho_mem_phys_bits ) ==PAGE_SIZE ); +struct kho_mem_phys {/* * Points to kho_mem_phys_bits, a sparse bitmap array. Each bit is sized
@@ -133,19 +135,19 @@ static struct kho_out kho_out = { .finalized = false, }; -static void *xa_load_or_alloc (struct xarray *xa,unsigned long index,size_t sz) +static void *xa_load_or_alloc (struct xarray *xa,unsigned long index) {void *res =xa_load (xa, index);if (res)return res; - void *elm __free(kfree) = kzalloc(sz, GFP_KERNEL); + void *elm __free(kfree) = kzalloc(PAGE_SIZE, GFP_KERNEL);if (!elm)return ERR_PTR (-ENOMEM ); -if (WARN_ON (kho_scratch_overlap (virt_to_phys (elm), sz))) +if (WARN_ON (kho_scratch_overlap (virt_to_phys (elm),PAGE_SIZE )))return ERR_PTR (-EINVAL ); res =xa_cmpxchg (xa, index,NULL , elm,GFP_KERNEL );
@@ -218,8 +220,7 @@ static int __kho_preserve_order(struct kho_mem_track *track, unsigned long pfn, } } - bits =xa_load_or_alloc (&physxa->phys_bits, pfn_high /PRESERVE_BITS , -sizeof (*bits)); + bits =xa_load_or_alloc (&physxa->phys_bits, pfn_high /PRESERVE_BITS );if (IS_ERR (bits))return PTR_ERR (bits);
Signature · 1 line
2.51.0.869.ge66316f041-goog
Re: [PATCH v3 2/3] liveupdate: kho: Increase metadata bitmap size to PAGE_SIZE
Quoted 10 lines · Pasha Tatashin
KHO memory preservation metadata is preserved in 512 byte chunks which requires their allocation from slab allocator. Slabs are not safe to be used with KHO because of kfence, and because partial slabs may lead leaks to the next kernel. Change the size to be
PAGE_SIZE.The kfence specifically may cause memory corruption, where it randomly provides slab objects that can be within the scratch area. The reason for that is that kfence allocates its objects prior to KHO scratch is marked as CMA region.
Quoted 7 lines
While this change could potentially increase metadata overhead on systems with sparsely preserved memory, this is being mitigated by ongoing work to reduce sparseness during preservation via 1G guest pages. Furthermore, this change aligns with future work on a stateless KHO, which will also use page-sized bitmaps for its radix tree metadata.
Signed-off-by Pasha Tatashin <[email protected]>
[...]
Signature · 2 lines
Regards, Pratyush Yadav
Re: [PATCH v3 2/3] liveupdate: kho: Increase metadata bitmap size to PAGE_SIZE
In reply to Pasha Tatashinkernel/kexec_handover.c early_param("kho", kho_parse_enable); · line 83
Quoted 8 lines · Pasha Tatashin
KHO memory preservation metadata is preserved in 512 byte chunks which requires their allocation from slab allocator. Slabs are not safe to be used with KHO because of kfence, and because partial slabs may lead leaks to the next kernel. Change the size to be
PAGE_SIZE.kernel/kexec_handover.c +1
-1-#define PRESERVE_BITS (512 * 8) +#define PRESERVE_BITS (PAGE_SIZE * 8)
nit: A comment somewhere (maybe here?) about the requirement that KHO metadata are not stored on slabs would be helpful to avoid someone "optimizing" this back to 512 in the future.
Re: [PATCH v3 2/3] liveupdate: kho: Increase metadata bitmap size to PAGE_SIZE
In reply to Pasha TatashinQuoted 7 lines · Pasha Tatashin
kernel/kexec_handover.c +1
-1-static void *xa_load_or_alloc (struct xarray *xa,unsigned long index,size_t sz) +static void *xa_load_or_alloc (struct xarray *xa,unsigned long index) {void *res =xa_load (xa, index);if (res)return res;
kernel/kexec_handover.c static struct kho_out kho_out = { · line 151
Quoted 10 lines
kernel/kexec_handover.c +2
-2- void *elm __free(kfree) = kzalloc(sz, GFP_KERNEL); + void *elm __free(kfree) = kzalloc(PAGE_SIZE, GFP_KERNEL);if (!elm)return ERR_PTR (-ENOMEM ); -if (WARN_ON (kho_scratch_overlap (virt_to_phys (elm), sz))) +if (WARN_ON (kho_scratch_overlap (virt_to_phys (elm),PAGE_SIZE )))return ERR_PTR (-EINVAL );
Reading xa_load_or_alloc() is a bit confusing now.
It seems very generic (returns a void *) but now hard-codes a size (PAGE_SIZE). You have to look at the caller to see it is allocating for a struct kho_mem_phys_bits, and then at the definition of struct kho_mem_phys_bits to see the static_assert() that this struct is always PAGE_SIZE.
I would either keep letting the caller passing in size (if you think this code is going to be re-used) or just commit to making xa_load_or_alloc() specific to kho_mem_phys_bits. e.g. Change the return type to struct kho_mem_phys_bits * and use sizeof() instead of PAGE_SIZE.
Re: [PATCH v3 2/3] liveupdate: kho: Increase metadata bitmap size to PAGE_SIZE
Quoted 30 lines · David Matlack
Quoted 7 lines · Pasha Tatashin
kernel/kexec_handover.c +1
-1-static void *xa_load_or_alloc (struct xarray *xa,unsigned long index,size_t sz) +static void *xa_load_or_alloc (struct xarray *xa,unsigned long index) {void *res =xa_load (xa, index);if (res)return res;kernel/kexec_handover.c static struct kho_out kho_out = { · line 151
Quoted 10 lines
kernel/kexec_handover.c +2
-2- void *elm __free(kfree) = kzalloc(sz, GFP_KERNEL); + void *elm __free(kfree) = kzalloc(PAGE_SIZE, GFP_KERNEL);if (!elm)return ERR_PTR (-ENOMEM ); -if (WARN_ON (kho_scratch_overlap (virt_to_phys (elm), sz))) +if (WARN_ON (kho_scratch_overlap (virt_to_phys (elm),PAGE_SIZE )))return ERR_PTR (-EINVAL );Reading
xa_load_or_alloc()is a bit confusing now.It seems very generic (returns a void *) but now hard-codes a size (
PAGE_SIZE). You have to look at the caller to see it is allocating for a structkho_mem_phys_bits, and then at the definition of structkho_mem_phys_bitsto see thestatic_assert()that this struct is alwaysPAGE_SIZE.
Quoted 5 lines
I would either keep letting the caller passing in size (if you think this code is going to be re-used) or just commit to making
xa_load_or_alloc()specific tokho_mem_phys_bits. e.g. Change the return type to structkho_mem_phys_bits* and usesizeof()instead ofPAGE_SIZE.
I see that you replace kzalloc() with get_zeroed_page() in the next patch. So the latter option is probably better, and maybe move static assert down here and use BUILD_BUG_ON()? That way readers can easily see that we are allocating for struct kho_mem_phys_bits *and* that that struct is guaranteed to be PAGE_SIZE'd.
Pasha Tatashin
maintainerRe: [PATCH v3 2/3] liveupdate: kho: Increase metadata bitmap size to PAGE_SIZE
Quoted 38 lines · David Matlack
Quoted 30 lines · David Matlack
Quoted 7 lines · Pasha Tatashin
kernel/kexec_handover.c +1
-1-static void *xa_load_or_alloc (struct xarray *xa,unsigned long index,size_t sz) +static void *xa_load_or_alloc (struct xarray *xa,unsigned long index) {void *res =xa_load (xa, index);if (res)return res;kernel/kexec_handover.c static struct kho_out kho_out = { · line 151
Quoted 10 lines
kernel/kexec_handover.c +2
-2- void *elm __free(kfree) = kzalloc(sz, GFP_KERNEL); + void *elm __free(kfree) = kzalloc(PAGE_SIZE, GFP_KERNEL);if (!elm)return ERR_PTR (-ENOMEM ); -if (WARN_ON (kho_scratch_overlap (virt_to_phys (elm), sz))) +if (WARN_ON (kho_scratch_overlap (virt_to_phys (elm),PAGE_SIZE )))return ERR_PTR (-EINVAL );Reading
xa_load_or_alloc()is a bit confusing now.It seems very generic (returns a void *) but now hard-codes a size (
PAGE_SIZE). You have to look at the caller to see it is allocating for a structkho_mem_phys_bits, and then at the definition of structkho_mem_phys_bitsto see thestatic_assert()that this struct is alwaysPAGE_SIZE.Quoted 5 lines
I would either keep letting the caller passing in size (if you think this code is going to be re-used) or just commit to making
xa_load_or_alloc()specific tokho_mem_phys_bits. e.g. Change the return type to structkho_mem_phys_bits* and usesizeof()instead ofPAGE_SIZE.
Quoted 5 lines
I see that you replace
kzalloc()withget_zeroed_page()in the next patch. So the latter option is probably better, and maybe move static assert down here and useBUILD_BUG_ON()? That way readers can easily see that we are allocating for structkho_mem_phys_bits*and* that that struct is guaranteed to be PAGE_SIZE'd.
The size is verified at build time via:
+static_assert(sizeof(struct kho_mem_phys_bits) == PAGE_SIZE);
Pasha Tatashin
maintainerPATCH v3 3/3 liveupdate: kho: allocate metadata directly from the buddy allocator
In reply to Pasha TatashinKHO allocates metadata for its preserved memory map using the slab allocator via kzalloc(). This metadata is temporary and is used by the next kernel during early boot to find preserved memory.
A problem arises when KFENCE is enabled. kzalloc() calls can be randomly intercepted by kfence_alloc(), which services the allocation from a dedicated KFENCE memory pool. This pool is allocated early in boot via memblock.
When booting via KHO, the memblock allocator is restricted to a "scratch area", forcing the KFENCE pool to be allocated within it. This creates a conflict, as the scratch area is expected to be ephemeral and overwriteable by a subsequent kexec. If KHO metadata is placed in this KFENCE pool, it leads to memory corruption when the next kernel is loaded.
To fix this, modify KHO to allocate its metadata directly from the buddy allocator instead of slab.
--- include/linux/gfp.h | 3 +++ kernel/kexec_handover.c | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-)
include/linux/gfp.h +3 -0
@@ -7,6 +7,7 @@#include <linux/mmzone.h> #include <linux/topology.h> #include <linux/alloc_tag.h> +#include <linux/cleanup.h> #include <linux/sched.h> struct vm_area_struct ;
@@ -463,4 +464,6 @@ static inline struct folio *folio_alloc_gigantic_noprof(int order, gfp_t gfp,/* This should be paired with folio_put() rather than free_contig_range(). */ #define folio_alloc_gigantic (...) alloc_hooks(folio_alloc_gigantic_noprof(__VA_ARGS__)) +DEFINE_FREE(free_page, void *, free_page((unsigned long)_T)) +#endif /* __LINUX_GFP_H */
kernel/kexec_handover.c +3 -3
@@ -142,7 +142,7 @@ static void *xa_load_or_alloc(struct xarray *xa, unsigned long index)if (res)return res; - void *elm __free(kfree) = kzalloc(PAGE_SIZE, GFP_KERNEL); + void *elm __free(free_page) = (void *)get_zeroed_page(GFP_KERNEL);if (!elm)return ERR_PTR (-ENOMEM );
@@ -348,9 +348,9 @@ static_assert(sizeof(struct khoser_mem_chunk) == PAGE_SIZE);static struct khoser_mem_chunk *new_chunk (struct khoser_mem_chunk *cur_chunk,unsigned long order) { - struct khoser_mem_chunk *chunk __free(kfree) = NULL; + struct khoser_mem_chunk *chunk __free(free_page) = NULL; - chunk =kzalloc (PAGE_SIZE ,GFP_KERNEL ); + chunk = (void *)get_zeroed_page (GFP_KERNEL );if (!chunk)return ERR_PTR (-ENOMEM );
Signature · 1 line
2.51.0.869.ge66316f041-goog
Re: [PATCH v3 3/3] liveupdate: kho: allocate metadata directly from the buddy allocator
Quoted 17 lines · Pasha Tatashin
KHO allocates metadata for its preserved memory map using the slab allocator via
kzalloc(). This metadata is temporary and is used by the next kernel during early boot to find preserved memory.A problem arises when KFENCE is enabled.
kzalloc()calls can be randomly intercepted bykfence_alloc(), which services the allocation from a dedicated KFENCE memory pool. This pool is allocated early in boot via memblock.When booting via KHO, the memblock allocator is restricted to a "scratch area", forcing the KFENCE pool to be allocated within it. This creates a conflict, as the scratch area is expected to be ephemeral and overwriteable by a subsequent kexec. If KHO metadata is placed in this KFENCE pool, it leads to memory corruption when the next kernel is loaded.
Quoted 6 lines
To fix this, modify KHO to allocate its metadata directly from the buddy allocator instead of slab.
Fixes fc33e4b44b27 ("kexec: enable KHO support for memory preservation")Signed-off-by Pasha Tatashin <[email protected]>Reviewed-by Pratyush Yadav <[email protected]>
Pasha Tatashin
maintainerRe: [PATCH v3 3/3] liveupdate: kho: allocate metadata directly from the buddy allocator
Quoted 20 lines · David Matlack
Quoted 17 lines · Pasha Tatashin
KHO allocates metadata for its preserved memory map using the slab allocator via
kzalloc(). This metadata is temporary and is used by the next kernel during early boot to find preserved memory.A problem arises when KFENCE is enabled.
kzalloc()calls can be randomly intercepted bykfence_alloc(), which services the allocation from a dedicated KFENCE memory pool. This pool is allocated early in boot via memblock.When booting via KHO, the memblock allocator is restricted to a "scratch area", forcing the KFENCE pool to be allocated within it. This creates a conflict, as the scratch area is expected to be ephemeral and overwriteable by a subsequent kexec. If KHO metadata is placed in this KFENCE pool, it leads to memory corruption when the next kernel is loaded.
Quoted 8 lines
Quoted 6 lines
To fix this, modify KHO to allocate its metadata directly from the buddy allocator instead of slab.
Fixes fc33e4b44b27 ("kexec: enable KHO support for memory preservation")Signed-off-by Pasha Tatashin <[email protected]>Reviewed-by Pratyush Yadav <[email protected]>Reviewed-by David Matlack <[email protected]>
Thank you,
Pasha
Quoted 22 lines · Pasha Tatashin
This series fixes a memory corruption bug in KHO that occurs when KFENCE is enabled.
The root cause is that KHO metadata, allocated via
kzalloc(), can be randomly serviced bykfence_alloc(). When a kernel boots via KHO, the early memblock allocator is restricted to a "scratch area". This forces the KFENCE pool to be allocated within this scratch area, creating a conflict. If KHO metadata is subsequently placed in this pool, it gets corrupted during the next kexec operation.Patch 1/3 introduces a debug-only feature (
CONFIG_KEXEC_HANDOVER_DEBUG) that adds checks to detect and fail any operation that attempts to place KHO metadata or preserved memory within the scratch area. This serves as a validation and diagnostic tool to confirm the problem without affecting production builds.Patch 2/3 Increases bitmap to
PAGE_SIZE, so buddy allocator can be used.Patch 3/3 Provides the fix by modifying KHO to allocate its metadata directly from the buddy allocator instead of slab. This bypasses the KFENCE interception entirely.
Quoted 5 lines
Pasha Tatashin (3):
liveupdate: kho: warn and fail on metadata or preserved memory in
scratch area
liveupdate: kho: Increase metadata bitmap size toPAGE_SIZE
liveupdate: kho: allocate metadata directly from the buddy allocator
With liveupdate: dropped from the subjects
Quoted 15 lines
include/linux/gfp.h | 3 ++ kernel/Kconfig.kexec | 9 ++++ kernel/Makefile | 1 + kernel/kexec_handover.c | 72 ++++++++++++++++++++------------ kernel/kexec_handover_debug.c | 25 +++++++++++ kernel/kexec_handover_internal.h | 16 +++++++ 6 files changed, 100 insertions(+), 26 deletions(-) create mode 100644 kernel/kexec_handover_debug.c create mode 100644 kernel/kexec_handover_internal.hbase-commit:
6548d364a3e850326831799d7e3ea2d7bb97ba08Signature · 1 line
2.51.0.869.ge66316f041-goog
Signature · 2 lines
Sincerely yours, Mike.
Pasha Tatashin
maintainerQuoted 24 lines · Mike Rapoport
Quoted 22 lines · Pasha Tatashin
This series fixes a memory corruption bug in KHO that occurs when KFENCE is enabled.
The root cause is that KHO metadata, allocated via
kzalloc(), can be randomly serviced bykfence_alloc(). When a kernel boots via KHO, the early memblock allocator is restricted to a "scratch area". This forces the KFENCE pool to be allocated within this scratch area, creating a conflict. If KHO metadata is subsequently placed in this pool, it gets corrupted during the next kexec operation.Patch 1/3 introduces a debug-only feature (
CONFIG_KEXEC_HANDOVER_DEBUG) that adds checks to detect and fail any operation that attempts to place KHO metadata or preserved memory within the scratch area. This serves as a validation and diagnostic tool to confirm the problem without affecting production builds.Patch 2/3 Increases bitmap to
PAGE_SIZE, so buddy allocator can be used.Patch 3/3 Provides the fix by modifying KHO to allocate its metadata directly from the buddy allocator instead of slab. This bypasses the KFENCE interception entirely.
Quoted 7 lines
Quoted 5 lines
Pasha Tatashin (3):
liveupdate: kho: warn and fail on metadata or preserved memory in
scratch area
liveupdate: kho: Increase metadata bitmap size toPAGE_SIZE
liveupdate: kho: allocate metadata directly from the buddy allocatorWith liveupdate: dropped from the subjects
I noticed "liveupdate: " subject prefix left over only after sending these patches. Andrew, would you like me to resend them, or could you remove the prefix from these patches?
Quoted 21 lines
Reviewed-by Mike Rapoport (Microsoft) <[email protected]>Quoted 11 lines
include/linux/gfp.h | 3 ++ kernel/Kconfig.kexec | 9 ++++ kernel/Makefile | 1 + kernel/kexec_handover.c | 72 ++++++++++++++++++++------------ kernel/kexec_handover_debug.c | 25 +++++++++++ kernel/kexec_handover_internal.h | 16 +++++++ 6 files changed, 100 insertions(+), 26 deletions(-) create mode 100644 kernel/kexec_handover_debug.c create mode 100644 kernel/kexec_handover_internal.hQuoted 4 lines
base-commit:
6548d364a3e850326831799d7e3ea2d7bb97ba08--
2.51.0.869.ge66316f041-goog--
Sincerely yours,
Mike.
Andrew Morton
maintainerQuoted 5 lines · On Tue, 21 Oct 2025 12:04:47 -0400 Pasha Tatashin <[email protected]>…
Quoted 1 line
With liveupdate: dropped from the subjects
I noticed "liveupdate: " subject prefix left over only after sending these patches. Andrew, would you like me to resend them, or could you remove the prefix from these patches?
No problem.
What should we do about -stable kernels?
It doesn't seem worthwhile to backport a 3-patch series for a pretty obscure bug. Perhaps we could merge a patch which disables this combination in Kconfig, as a 6.18-rcX hotfix with a cc:stable.
Then for 6.19-rc1 we add this series and a fourth patch which undoes that Kconfig change?
Pasha Tatashin
maintainerQuoted 9 lines · Andrew Morton
Quoted 5 lines · On Tue, 21 Oct 2025 12:04:47 -0400 Pasha Tatashin <[email protected]>…
Quoted 1 line
With liveupdate: dropped from the subjects
I noticed "liveupdate: " subject prefix left over only after sending these patches. Andrew, would you like me to resend them, or could you remove the prefix from these patches?
Quoted 6 lines
No problem.
What should we do about -stable kernels?
It doesn't seem worthwhile to backport a 3-patch series for a pretty obscure bug. Perhaps we could merge a patch which disables this
We are using KHO and have had obscure crashes due to this memory corruption, with stacks all over the place. I would prefer this fix to be properly backported to stable so we can also automatically consume it once we switch to the upstream KHO. I do not think disabling kfence in the Google fleet to resolve this problem would work for us, so if it is not going to be part of stable, we would have to backport it manually anyway.
Thanks,
Pasha
Quoted 4 lines
combination in
Kconfig, as a 6.18-rcX hotfix with a cc:stable.Then for 6.19-rc1 we add this series and a fourth patch which undoes that
Kconfigchange?
Mike Rapoport
maintainerQuoted 17 lines · Pasha Tatashin
Quoted 9 lines · Andrew Morton
Quoted 5 lines · On Tue, 21 Oct 2025 12:04:47 -0400 Pasha Tatashin <[email protected]>…
Quoted 1 line
With liveupdate: dropped from the subjects
I noticed "liveupdate: " subject prefix left over only after sending these patches. Andrew, would you like me to resend them, or could you remove the prefix from these patches?
Quoted 6 lines
No problem.
What should we do about -stable kernels?
It doesn't seem worthwhile to backport a 3-patch series for a pretty obscure bug. Perhaps we could merge a patch which disables this
Quoted 7 lines
We are using KHO and have had obscure crashes due to this memory corruption, with stacks all over the place. I would prefer this fix to be properly backported to stable so we can also automatically consume it once we switch to the upstream KHO. I do not think disabling kfence in the Google fleet to resolve this problem would work for us, so if it is not going to be part of stable, we would have to backport it manually anyway.
The backport to stable is only relevant to 6.17 that's going to be EOL soon anyway. Do you really think it's worth the effort?
Quoted 7 lines
Thanks,
PashaQuoted 4 lines
combination in
Kconfig, as a 6.18-rcX hotfix with a cc:stable.Then for 6.19-rc1 we add this series and a fourth patch which undoes that
Kconfigchange?
Signature · 2 lines
Sincerely yours, Mike.
Andrew Morton
maintainerQuoted 10 lines · On Wed, 22 Oct 2025 08:48:34 +0300 Mike Rapoport <[email protected]> wrote:
Quoted 7 lines
We are using KHO and have had obscure crashes due to this memory corruption, with stacks all over the place. I would prefer this fix to be properly backported to stable so we can also automatically consume it once we switch to the upstream KHO. I do not think disabling kfence in the Google fleet to resolve this problem would work for us, so if it is not going to be part of stable, we would have to backport it manually anyway.
The backport to stable is only relevant to 6.17 that's going to be EOL soon anyway. Do you really think it's worth the effort?
If some organization is basing their next kernel on 6.17 then they'd like it.
Do we assume that all organizations follow the LTS schedule? I haven't been doing that.
Andrew Morton
maintainerQuoted 14 lines · On Tue, 21 Oct 2025 20:15:04 -0400 Pasha Tatashin <[email protected]>…
Quoted 13 lines · Andrew Morton
Quoted 5 lines · On Tue, 21 Oct 2025 12:04:47 -0400 Pasha Tatashin <[email protected]>…
Quoted 1 line
With liveupdate: dropped from the subjects
I noticed "liveupdate: " subject prefix left over only after sending these patches. Andrew, would you like me to resend them, or could you remove the prefix from these patches?
No problem.
What should we do about -stable kernels?
Quoted 7 lines
Quoted 2 lines
It doesn't seem worthwhile to backport a 3-patch series for a pretty obscure bug. Perhaps we could merge a patch which disables this
We are using KHO and have had obscure crashes due to this memory corruption, with stacks all over the place. I would prefer this fix to be properly backported to stable so we can also automatically consume it once we switch to the upstream KHO.
Oh.
I added this important info to the [0/N] changelog, added
to all three and moved this into mm.git's mm-hotfixes branch.