public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC 0/5] liveupdate: validate restored LUO metadata
@ 2026-05-01  9:46 Cris Jacob Maamor
  2026-05-01  9:46 ` [PATCH RFC 1/5] kexec: handover: add helper to check preserved page ranges Cris Jacob Maamor
                   ` (5 more replies)
  0 siblings, 6 replies; 18+ messages in thread
From: Cris Jacob Maamor @ 2026-05-01  9:46 UTC (permalink / raw)
  To: Mike Rapoport, Pasha Tatashin, Pratyush Yadav
  Cc: Alexander Graf, Andrew Morton, Dan Carpenter, Greg Kroah-Hartman,
	kexec, linux-mm, linux-kernel

LUO restores metadata from KHO/FDT during liveupdate. The restored
metadata contains physical addresses and count fields used to access and
walk preserved session, file-set, and FLB arrays.

This series adds a non-consuming KHO preserved-range check and uses it
before phys_to_virt() on restored metadata addresses. It also rejects
restored counts above LUO_SESSION_MAX, LUO_FILE_MAX, and LUO_FLB_MAX
before traversal.

As far as I can tell, this is root/admin-only; I do not have evidence
that a normal unprivileged user can trigger it directly.

I have not reproduced this in a VM yet, so I may be missing a KHO
invariant or a preferred restore helper pattern. Feedback on the helper
semantics is welcome.

Cris Jacob Maamor (5):
  kexec: handover: add helper to check preserved page ranges
  liveupdate: validate restored LUO FDT before use
  liveupdate: validate restored LUO session metadata
  liveupdate: validate restored LUO file-set metadata
  liveupdate: validate restored LUO FLB metadata

 include/linux/kexec_handover.h     |  6 +++++
 kernel/liveupdate/kexec_handover.c | 35 ++++++++++++++++++++++++++++++
 kernel/liveupdate/luo_core.c       | 10 ++++++++-
 kernel/liveupdate/luo_file.c       | 14 ++++++++++--
 kernel/liveupdate/luo_flb.c        | 23 +++++++++++++++++++-
 kernel/liveupdate/luo_session.c    | 22 +++++++++++++++++--
 6 files changed, 104 insertions(+), 6 deletions(-)

-- 
2.53.0


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

* [PATCH RFC 1/5] kexec: handover: add helper to check preserved page ranges
  2026-05-01  9:46 [PATCH RFC 0/5] liveupdate: validate restored LUO metadata Cris Jacob Maamor
@ 2026-05-01  9:46 ` Cris Jacob Maamor
  2026-05-01 10:11   ` Greg Kroah-Hartman
  2026-05-01  9:46 ` [PATCH RFC 2/5] liveupdate: validate restored LUO FDT before use Cris Jacob Maamor
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 18+ messages in thread
From: Cris Jacob Maamor @ 2026-05-01  9:46 UTC (permalink / raw)
  To: Mike Rapoport, Pasha Tatashin, Pratyush Yadav
  Cc: Alexander Graf, Andrew Morton, Dan Carpenter, Greg Kroah-Hartman,
	kexec, linux-mm, linux-kernel

Signed-off-by: Cris Jacob Maamor <crisjacobmaamor@gmail.com>
---
 include/linux/kexec_handover.h     |  6 +++++
 kernel/liveupdate/kexec_handover.c | 35 ++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+)

diff --git a/include/linux/kexec_handover.h b/include/linux/kexec_handover.h
index 8968c56d2d73..fb09943ab232 100644
--- a/include/linux/kexec_handover.h
+++ b/include/linux/kexec_handover.h
@@ -19,6 +19,7 @@ struct page;
 #ifdef CONFIG_KEXEC_HANDOVER
 bool kho_is_enabled(void);
 bool is_kho_boot(void);
+bool kho_is_preserved(phys_addr_t phys, unsigned long nr_pages);
 
 int kho_preserve_folio(struct folio *folio);
 void kho_unpreserve_folio(struct folio *folio);
@@ -51,6 +52,11 @@ static inline bool is_kho_boot(void)
 	return false;
 }
 
+static inline bool kho_is_preserved(phys_addr_t phys, unsigned long nr_pages)
+{
+	return false;
+}
+
 static inline int kho_preserve_folio(struct folio *folio)
 {
 	return -EOPNOTSUPP;
diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
index 94762de1fe5f..fe9f11190705 100644
--- a/kernel/liveupdate/kexec_handover.c
+++ b/kernel/liveupdate/kexec_handover.c
@@ -10,6 +10,7 @@
 
 #define pr_fmt(fmt) "KHO: " fmt
 
+#include <linux/bits.h>
 #include <linux/cleanup.h>
 #include <linux/cma.h>
 #include <linux/kmemleak.h>
@@ -429,6 +430,40 @@ static struct page *kho_restore_page(phys_addr_t phys, bool is_folio)
 	return page;
 }
 
+/**
+ * kho_is_preserved - Verify that a physical page range belongs to KHO.
+ * @phys: physical address of the first page in the range.
+ * @nr_pages: number of pages that the caller expects to access.
+ *
+ * Use this before phys_to_virt() when a physical address comes from restored
+ * metadata. It checks that @phys starts a KHO-preserved allocation large
+ * enough to cover @nr_pages.
+ *
+ * This only checks the KHO marker. It does not restore, free, or take
+ * ownership of the pages.
+ *
+ * Return: true if @phys starts a preserved KHO allocation large enough to cover
+ * @nr_pages, false otherwise.
+ */
+bool kho_is_preserved(phys_addr_t phys, unsigned long nr_pages)
+{
+	struct page *page;
+	union kho_page_info info;
+
+	if (!nr_pages || !IS_ALIGNED(phys, PAGE_SIZE))
+		return false;
+
+	page = pfn_to_online_page(PHYS_PFN(phys));
+	if (!page)
+		return false;
+
+	info.page_private = page->private;
+	if (info.magic != KHO_PAGE_MAGIC || info.order >= BITS_PER_LONG)
+		return false;
+
+	return nr_pages <= BIT(info.order);
+}
+
 /**
  * kho_restore_folio - recreates the folio from the preserved memory.
  * @phys: physical address of the folio.
-- 
2.53.0


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

* [PATCH RFC 2/5] liveupdate: validate restored LUO FDT before use
  2026-05-01  9:46 [PATCH RFC 0/5] liveupdate: validate restored LUO metadata Cris Jacob Maamor
  2026-05-01  9:46 ` [PATCH RFC 1/5] kexec: handover: add helper to check preserved page ranges Cris Jacob Maamor
@ 2026-05-01  9:46 ` Cris Jacob Maamor
  2026-05-01  9:46 ` [PATCH RFC 3/5] liveupdate: validate restored LUO session metadata Cris Jacob Maamor
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 18+ messages in thread
From: Cris Jacob Maamor @ 2026-05-01  9:46 UTC (permalink / raw)
  To: Mike Rapoport, Pasha Tatashin, Pratyush Yadav
  Cc: Alexander Graf, Andrew Morton, Dan Carpenter, Greg Kroah-Hartman,
	kexec, linux-mm, linux-kernel

Signed-off-by: Cris Jacob Maamor <crisjacobmaamor@gmail.com>
---
 kernel/liveupdate/luo_core.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/kernel/liveupdate/luo_core.c b/kernel/liveupdate/luo_core.c
index 803f51c84275..633a16434164 100644
--- a/kernel/liveupdate/luo_core.c
+++ b/kernel/liveupdate/luo_core.c
@@ -82,6 +82,7 @@ early_param("liveupdate", early_liveupdate_param);
 
 static int __init luo_early_startup(void)
 {
+	size_t fdt_size;
 	phys_addr_t fdt_phys;
 	int err, ln_size;
 	const void *ptr;
@@ -94,7 +95,8 @@ static int __init luo_early_startup(void)
 	}
 
 	/* Retrieve LUO subtree, and verify its format. */
-	err = kho_retrieve_subtree(LUO_FDT_KHO_ENTRY_NAME, &fdt_phys, NULL);
+	err = kho_retrieve_subtree(LUO_FDT_KHO_ENTRY_NAME, &fdt_phys,
+				   &fdt_size);
 	if (err) {
 		if (err != -ENOENT) {
 			pr_err("failed to retrieve FDT '%s' from KHO: %pe\n",
@@ -105,6 +107,12 @@ static int __init luo_early_startup(void)
 		return 0;
 	}
 
+	if (!fdt_size || fdt_size > LUO_FDT_SIZE ||
+	    !kho_is_preserved(fdt_phys, DIV_ROUND_UP(fdt_size, PAGE_SIZE))) {
+		pr_err("Invalid LUO FDT from KHO\n");
+		return -EINVAL;
+	}
+
 	luo_global.fdt_in = phys_to_virt(fdt_phys);
 	err = fdt_node_check_compatible(luo_global.fdt_in, 0,
 					LUO_FDT_COMPATIBLE);
-- 
2.53.0


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

* [PATCH RFC 3/5] liveupdate: validate restored LUO session metadata
  2026-05-01  9:46 [PATCH RFC 0/5] liveupdate: validate restored LUO metadata Cris Jacob Maamor
  2026-05-01  9:46 ` [PATCH RFC 1/5] kexec: handover: add helper to check preserved page ranges Cris Jacob Maamor
  2026-05-01  9:46 ` [PATCH RFC 2/5] liveupdate: validate restored LUO FDT before use Cris Jacob Maamor
@ 2026-05-01  9:46 ` Cris Jacob Maamor
  2026-05-01  9:46 ` [PATCH RFC 4/5] liveupdate: validate restored LUO file-set metadata Cris Jacob Maamor
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 18+ messages in thread
From: Cris Jacob Maamor @ 2026-05-01  9:46 UTC (permalink / raw)
  To: Mike Rapoport, Pasha Tatashin, Pratyush Yadav
  Cc: Alexander Graf, Andrew Morton, Dan Carpenter, Greg Kroah-Hartman,
	kexec, linux-mm, linux-kernel

Signed-off-by: Cris Jacob Maamor <crisjacobmaamor@gmail.com>
---
 kernel/liveupdate/luo_session.c | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/kernel/liveupdate/luo_session.c b/kernel/liveupdate/luo_session.c
index a3327a28fc1f..0244c071936d 100644
--- a/kernel/liveupdate/luo_session.c
+++ b/kernel/liveupdate/luo_session.c
@@ -501,7 +501,18 @@ int __init luo_session_setup_incoming(void *fdt_in)
 	}
 
 	header_ser_pa = get_unaligned((u64 *)ptr);
+	if (!kho_is_preserved(header_ser_pa, LUO_SESSION_PGCNT)) {
+		pr_err("Session header is not KHO preserved: %#llx\n",
+		       (unsigned long long)header_ser_pa);
+		return -EINVAL;
+	}
+
 	header_ser = phys_to_virt(header_ser_pa);
+	if (header_ser->count > LUO_SESSION_MAX) {
+		pr_err("Invalid session count: %llu\n",
+		       (unsigned long long)header_ser->count);
+		return -EINVAL;
+	}
 
 	luo_session_global.incoming.header_ser = header_ser;
 	luo_session_global.incoming.ser = (void *)(header_ser + 1);
@@ -515,6 +526,7 @@ int luo_session_deserialize(void)
 	struct luo_session_header *sh = &luo_session_global.incoming;
 	static bool is_deserialized;
 	static int err;
+	u64 count;
 
 	/* If has been deserialized, always return the same error code */
 	if (is_deserialized)
@@ -524,6 +536,13 @@ int luo_session_deserialize(void)
 	if (!sh->active)
 		return 0;
 
+	count = sh->header_ser->count;
+	if (count > LUO_SESSION_MAX) {
+		pr_err("Invalid session count: %llu\n",
+		       (unsigned long long)count);
+		return -EINVAL;
+	}
+
 	/*
 	 * Note on error handling:
 	 *
@@ -539,7 +558,7 @@ int luo_session_deserialize(void)
 	 * userspace to detect the failure and trigger a reboot, which will
 	 * reliably reset devices and reclaim memory.
 	 */
-	for (int i = 0; i < sh->header_ser->count; i++) {
+	for (u64 i = 0; i < count; i++) {
 		struct luo_session *session;
 
 		session = luo_session_alloc(sh->ser[i].name);
@@ -606,4 +625,3 @@ int luo_session_serialize(void)
 
 	return err;
 }
-
-- 
2.53.0


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

* [PATCH RFC 4/5] liveupdate: validate restored LUO file-set metadata
  2026-05-01  9:46 [PATCH RFC 0/5] liveupdate: validate restored LUO metadata Cris Jacob Maamor
                   ` (2 preceding siblings ...)
  2026-05-01  9:46 ` [PATCH RFC 3/5] liveupdate: validate restored LUO session metadata Cris Jacob Maamor
@ 2026-05-01  9:46 ` Cris Jacob Maamor
  2026-05-01  9:46 ` [PATCH RFC 5/5] liveupdate: validate restored LUO FLB metadata Cris Jacob Maamor
  2026-05-01 17:30 ` [PATCH v2 0/5] liveupdate: validate restored LUO metadata Cris Jacob Maamor
  5 siblings, 0 replies; 18+ messages in thread
From: Cris Jacob Maamor @ 2026-05-01  9:46 UTC (permalink / raw)
  To: Mike Rapoport, Pasha Tatashin, Pratyush Yadav
  Cc: Alexander Graf, Andrew Morton, Dan Carpenter, Greg Kroah-Hartman,
	kexec, linux-mm, linux-kernel

Signed-off-by: Cris Jacob Maamor <crisjacobmaamor@gmail.com>
---
 kernel/liveupdate/luo_file.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/kernel/liveupdate/luo_file.c b/kernel/liveupdate/luo_file.c
index a0a419085e28..cde43d822f8f 100644
--- a/kernel/liveupdate/luo_file.c
+++ b/kernel/liveupdate/luo_file.c
@@ -783,11 +783,21 @@ int luo_file_deserialize(struct luo_file_set *file_set,
 	struct luo_file_ser *file_ser;
 	u64 i;
 
-	if (!file_set_ser->files) {
-		WARN_ON(file_set_ser->count);
+	if (!file_set_ser->count) {
+		if (file_set_ser->files)
+			return -EINVAL;
 		return 0;
 	}
 
+	if (file_set_ser->count > LUO_FILE_MAX)
+		return -EINVAL;
+
+	if (!file_set_ser->files)
+		return -EINVAL;
+
+	if (!kho_is_preserved(file_set_ser->files, LUO_FILE_PGCNT))
+		return -EINVAL;
+
 	file_set->count = file_set_ser->count;
 	file_set->files = phys_to_virt(file_set_ser->files);
 
-- 
2.53.0


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

* [PATCH RFC 5/5] liveupdate: validate restored LUO FLB metadata
  2026-05-01  9:46 [PATCH RFC 0/5] liveupdate: validate restored LUO metadata Cris Jacob Maamor
                   ` (3 preceding siblings ...)
  2026-05-01  9:46 ` [PATCH RFC 4/5] liveupdate: validate restored LUO file-set metadata Cris Jacob Maamor
@ 2026-05-01  9:46 ` Cris Jacob Maamor
  2026-05-01 17:30 ` [PATCH v2 0/5] liveupdate: validate restored LUO metadata Cris Jacob Maamor
  5 siblings, 0 replies; 18+ messages in thread
From: Cris Jacob Maamor @ 2026-05-01  9:46 UTC (permalink / raw)
  To: Mike Rapoport, Pasha Tatashin, Pratyush Yadav
  Cc: Alexander Graf, Andrew Morton, Dan Carpenter, Greg Kroah-Hartman,
	kexec, linux-mm, linux-kernel

Signed-off-by: Cris Jacob Maamor <crisjacobmaamor@gmail.com>
---
 kernel/liveupdate/luo_flb.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/kernel/liveupdate/luo_flb.c b/kernel/liveupdate/luo_flb.c
index 00f5494812c4..e80032669cea 100644
--- a/kernel/liveupdate/luo_flb.c
+++ b/kernel/liveupdate/luo_flb.c
@@ -162,6 +162,7 @@ static int luo_flb_retrieve_one(struct liveupdate_flb *flb)
 	struct luo_flb_header *fh = &luo_flb_global.incoming;
 	struct liveupdate_flb_op_args args = {0};
 	bool found = false;
+	u64 count;
 	int err;
 
 	guard(mutex)(&private->incoming.lock);
@@ -175,7 +176,14 @@ static int luo_flb_retrieve_one(struct liveupdate_flb *flb)
 	if (!fh->active)
 		return -ENODATA;
 
-	for (int i = 0; i < fh->header_ser->count; i++) {
+	count = fh->header_ser->count;
+	if (count > LUO_FLB_MAX) {
+		pr_err("Invalid FLB count: %llu\n",
+		       (unsigned long long)count);
+		return -EINVAL;
+	}
+
+	for (u64 i = 0; i < count; i++) {
 		if (!strcmp(fh->ser[i].name, flb->compatible)) {
 			private->incoming.data = fh->ser[i].data;
 			private->incoming.count = fh->ser[i].count;
@@ -620,7 +628,20 @@ int __init luo_flb_setup_incoming(void *fdt_in)
 	}
 
 	header_ser_pa = get_unaligned((u64 *)ptr);
+	if (!kho_is_preserved(header_ser_pa, LUO_FLB_PGCNT)) {
+		pr_err("FLB header is not KHO preserved: %#llx\n",
+		       (unsigned long long)header_ser_pa);
+		return -EINVAL;
+	}
+
 	header_ser = phys_to_virt(header_ser_pa);
+	if (header_ser->pgcnt != LUO_FLB_PGCNT ||
+	    header_ser->count > LUO_FLB_MAX) {
+		pr_err("Invalid FLB header: pgcnt %llu count %llu\n",
+		       (unsigned long long)header_ser->pgcnt,
+		       (unsigned long long)header_ser->count);
+		return -EINVAL;
+	}
 
 	luo_flb_global.incoming.header_ser = header_ser;
 	luo_flb_global.incoming.ser = (void *)(header_ser + 1);
-- 
2.53.0


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

* Re: [PATCH RFC 1/5] kexec: handover: add helper to check preserved page ranges
  2026-05-01  9:46 ` [PATCH RFC 1/5] kexec: handover: add helper to check preserved page ranges Cris Jacob Maamor
@ 2026-05-01 10:11   ` Greg Kroah-Hartman
  0 siblings, 0 replies; 18+ messages in thread
From: Greg Kroah-Hartman @ 2026-05-01 10:11 UTC (permalink / raw)
  To: Cris Jacob Maamor
  Cc: Mike Rapoport, Pasha Tatashin, Pratyush Yadav, Alexander Graf,
	Andrew Morton, Dan Carpenter, kexec, linux-mm, linux-kernel

On Fri, May 01, 2026 at 05:46:33PM +0800, Cris Jacob Maamor wrote:
> Signed-off-by: Cris Jacob Maamor <crisjacobmaamor@gmail.com>

For obvious reasons, we can't take patches without any changelog text
(nor do you want us to.)

And when a pathc is "RFC", what specific comments are you asking for?
Why don't you feel this is good enough to take now?

thanks,

greg k-h

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

* [PATCH v2 0/5] liveupdate: validate restored LUO metadata
  2026-05-01  9:46 [PATCH RFC 0/5] liveupdate: validate restored LUO metadata Cris Jacob Maamor
                   ` (4 preceding siblings ...)
  2026-05-01  9:46 ` [PATCH RFC 5/5] liveupdate: validate restored LUO FLB metadata Cris Jacob Maamor
@ 2026-05-01 17:30 ` Cris Jacob Maamor
  2026-05-01 17:30   ` [PATCH v2 1/5] kexec: handover: add helper to check preserved page ranges Cris Jacob Maamor
                     ` (5 more replies)
  5 siblings, 6 replies; 18+ messages in thread
From: Cris Jacob Maamor @ 2026-05-01 17:30 UTC (permalink / raw)
  To: Mike Rapoport, Pasha Tatashin, Pratyush Yadav
  Cc: Alexander Graf, Andrew Morton, Greg Kroah-Hartman, kexec,
	linux-mm, linux-kernel

LUO restores metadata from KHO/FDT during liveupdate. The restored
metadata contains physical addresses and count fields used to access and
walk preserved session, file set, and FLB arrays.

This series adds a non-consuming KHO preserved-range check and uses it
before phys_to_virt() on restored metadata addresses. It also rejects
restored counts above LUO_SESSION_MAX, LUO_FILE_MAX, and LUO_FLB_MAX
before traversal.

As far as I can tell, this is root/admin-only; I do not have evidence
that a normal unprivileged user can trigger it directly.

Changes since v1:
- Dropped RFC marking.
- Added changelog text to each patch.
- No code changes.

Cris Jacob Maamor (5):
  kexec: handover: add helper to check preserved page ranges
  liveupdate: validate LUO FDT physical address before mapping
  liveupdate: validate restored LUO session metadata
  liveupdate: validate restored LUO file set metadata
  liveupdate: validate restored LUO FLB metadata

 include/linux/kexec_handover.h     |  6 +++++
 kernel/liveupdate/kexec_handover.c | 35 ++++++++++++++++++++++++++++++
 kernel/liveupdate/luo_core.c       | 10 ++++++++-
 kernel/liveupdate/luo_file.c       | 14 ++++++++++--
 kernel/liveupdate/luo_flb.c        | 23 +++++++++++++++++++-
 kernel/liveupdate/luo_session.c    | 22 +++++++++++++++++--
 6 files changed, 104 insertions(+), 6 deletions(-)

-- 
2.53.0


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

* [PATCH v2 1/5] kexec: handover: add helper to check preserved page ranges
  2026-05-01 17:30 ` [PATCH v2 0/5] liveupdate: validate restored LUO metadata Cris Jacob Maamor
@ 2026-05-01 17:30   ` Cris Jacob Maamor
  2026-05-01 17:30   ` [PATCH v2 2/5] liveupdate: validate LUO FDT physical address before mapping Cris Jacob Maamor
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 18+ messages in thread
From: Cris Jacob Maamor @ 2026-05-01 17:30 UTC (permalink / raw)
  To: Mike Rapoport, Pasha Tatashin, Pratyush Yadav
  Cc: Alexander Graf, Andrew Morton, Greg Kroah-Hartman, kexec,
	linux-mm, linux-kernel

Restore code should not use phys_to_virt() on physical addresses from
restored metadata until it verifies that the range was preserved by KHO.

Add kho_is_preserved() so callers can check a preserved page range without
restoring, freeing, or taking ownership of the pages.

Signed-off-by: Cris Jacob Maamor <crisjacobmaamor@gmail.com>
---
 include/linux/kexec_handover.h     |  6 +++++
 kernel/liveupdate/kexec_handover.c | 35 ++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+)

diff --git a/include/linux/kexec_handover.h b/include/linux/kexec_handover.h
index 8968c56d2d73..fb09943ab232 100644
--- a/include/linux/kexec_handover.h
+++ b/include/linux/kexec_handover.h
@@ -19,6 +19,7 @@ struct page;
 #ifdef CONFIG_KEXEC_HANDOVER
 bool kho_is_enabled(void);
 bool is_kho_boot(void);
+bool kho_is_preserved(phys_addr_t phys, unsigned long nr_pages);
 
 int kho_preserve_folio(struct folio *folio);
 void kho_unpreserve_folio(struct folio *folio);
@@ -51,6 +52,11 @@ static inline bool is_kho_boot(void)
 	return false;
 }
 
+static inline bool kho_is_preserved(phys_addr_t phys, unsigned long nr_pages)
+{
+	return false;
+}
+
 static inline int kho_preserve_folio(struct folio *folio)
 {
 	return -EOPNOTSUPP;
diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
index 94762de1fe5f..fe9f11190705 100644
--- a/kernel/liveupdate/kexec_handover.c
+++ b/kernel/liveupdate/kexec_handover.c
@@ -10,6 +10,7 @@
 
 #define pr_fmt(fmt) "KHO: " fmt
 
+#include <linux/bits.h>
 #include <linux/cleanup.h>
 #include <linux/cma.h>
 #include <linux/kmemleak.h>
@@ -429,6 +430,40 @@ static struct page *kho_restore_page(phys_addr_t phys, bool is_folio)
 	return page;
 }
 
+/**
+ * kho_is_preserved - Verify that a physical page range belongs to KHO.
+ * @phys: physical address of the first page in the range.
+ * @nr_pages: number of pages that the caller expects to access.
+ *
+ * Use this before phys_to_virt() when a physical address comes from restored
+ * metadata. It checks that @phys starts a KHO-preserved allocation large
+ * enough to cover @nr_pages.
+ *
+ * This only checks the KHO marker. It does not restore, free, or take
+ * ownership of the pages.
+ *
+ * Return: true if @phys starts a preserved KHO allocation large enough to cover
+ * @nr_pages, false otherwise.
+ */
+bool kho_is_preserved(phys_addr_t phys, unsigned long nr_pages)
+{
+	struct page *page;
+	union kho_page_info info;
+
+	if (!nr_pages || !IS_ALIGNED(phys, PAGE_SIZE))
+		return false;
+
+	page = pfn_to_online_page(PHYS_PFN(phys));
+	if (!page)
+		return false;
+
+	info.page_private = page->private;
+	if (info.magic != KHO_PAGE_MAGIC || info.order >= BITS_PER_LONG)
+		return false;
+
+	return nr_pages <= BIT(info.order);
+}
+
 /**
  * kho_restore_folio - recreates the folio from the preserved memory.
  * @phys: physical address of the folio.
-- 
2.53.0


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

* [PATCH v2 2/5] liveupdate: validate LUO FDT physical address before mapping
  2026-05-01 17:30 ` [PATCH v2 0/5] liveupdate: validate restored LUO metadata Cris Jacob Maamor
  2026-05-01 17:30   ` [PATCH v2 1/5] kexec: handover: add helper to check preserved page ranges Cris Jacob Maamor
@ 2026-05-01 17:30   ` Cris Jacob Maamor
  2026-05-01 17:30   ` [PATCH v2 3/5] liveupdate: validate restored LUO session metadata Cris Jacob Maamor
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 18+ messages in thread
From: Cris Jacob Maamor @ 2026-05-01 17:30 UTC (permalink / raw)
  To: Mike Rapoport, Pasha Tatashin, Pratyush Yadav
  Cc: Alexander Graf, Andrew Morton, Greg Kroah-Hartman, kexec,
	linux-mm, linux-kernel

LUO gets the restored FDT address from KHO and maps it with phys_to_virt().

Check the FDT size and make sure the address range is KHO-preserved before
mapping it. Reject empty or oversized FDT metadata.

Signed-off-by: Cris Jacob Maamor <crisjacobmaamor@gmail.com>
---
 kernel/liveupdate/luo_core.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/kernel/liveupdate/luo_core.c b/kernel/liveupdate/luo_core.c
index 803f51c84275..633a16434164 100644
--- a/kernel/liveupdate/luo_core.c
+++ b/kernel/liveupdate/luo_core.c
@@ -82,6 +82,7 @@ early_param("liveupdate", early_liveupdate_param);
 
 static int __init luo_early_startup(void)
 {
+	size_t fdt_size;
 	phys_addr_t fdt_phys;
 	int err, ln_size;
 	const void *ptr;
@@ -94,7 +95,8 @@ static int __init luo_early_startup(void)
 	}
 
 	/* Retrieve LUO subtree, and verify its format. */
-	err = kho_retrieve_subtree(LUO_FDT_KHO_ENTRY_NAME, &fdt_phys, NULL);
+	err = kho_retrieve_subtree(LUO_FDT_KHO_ENTRY_NAME, &fdt_phys,
+				   &fdt_size);
 	if (err) {
 		if (err != -ENOENT) {
 			pr_err("failed to retrieve FDT '%s' from KHO: %pe\n",
@@ -105,6 +107,12 @@ static int __init luo_early_startup(void)
 		return 0;
 	}
 
+	if (!fdt_size || fdt_size > LUO_FDT_SIZE ||
+	    !kho_is_preserved(fdt_phys, DIV_ROUND_UP(fdt_size, PAGE_SIZE))) {
+		pr_err("Invalid LUO FDT from KHO\n");
+		return -EINVAL;
+	}
+
 	luo_global.fdt_in = phys_to_virt(fdt_phys);
 	err = fdt_node_check_compatible(luo_global.fdt_in, 0,
 					LUO_FDT_COMPATIBLE);
-- 
2.53.0


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

* [PATCH v2 3/5] liveupdate: validate restored LUO session metadata
  2026-05-01 17:30 ` [PATCH v2 0/5] liveupdate: validate restored LUO metadata Cris Jacob Maamor
  2026-05-01 17:30   ` [PATCH v2 1/5] kexec: handover: add helper to check preserved page ranges Cris Jacob Maamor
  2026-05-01 17:30   ` [PATCH v2 2/5] liveupdate: validate LUO FDT physical address before mapping Cris Jacob Maamor
@ 2026-05-01 17:30   ` Cris Jacob Maamor
  2026-05-01 17:30   ` [PATCH v2 4/5] liveupdate: validate restored LUO file set metadata Cris Jacob Maamor
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 18+ messages in thread
From: Cris Jacob Maamor @ 2026-05-01 17:30 UTC (permalink / raw)
  To: Mike Rapoport, Pasha Tatashin, Pratyush Yadav
  Cc: Alexander Graf, Andrew Morton, Greg Kroah-Hartman, kexec,
	linux-mm, linux-kernel

The restored FDT contains the physical address of the LUO session header,
which LUO maps before reading session metadata. Check that physical range
against KHO-preserved memory before calling phys_to_virt(), and abort the
restore if the physical range is not covered.

The session header has a count that controls how far LUO walks the
serialized session array. Check that count against LUO_SESSION_MAX before
deserialization, and abort the restore if the value is out of range.

Signed-off-by: Cris Jacob Maamor <crisjacobmaamor@gmail.com>
---
 kernel/liveupdate/luo_session.c | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/kernel/liveupdate/luo_session.c b/kernel/liveupdate/luo_session.c
index a3327a28fc1f..0244c071936d 100644
--- a/kernel/liveupdate/luo_session.c
+++ b/kernel/liveupdate/luo_session.c
@@ -501,7 +501,18 @@ int __init luo_session_setup_incoming(void *fdt_in)
 	}
 
 	header_ser_pa = get_unaligned((u64 *)ptr);
+	if (!kho_is_preserved(header_ser_pa, LUO_SESSION_PGCNT)) {
+		pr_err("Session header is not KHO preserved: %#llx\n",
+		       (unsigned long long)header_ser_pa);
+		return -EINVAL;
+	}
+
 	header_ser = phys_to_virt(header_ser_pa);
+	if (header_ser->count > LUO_SESSION_MAX) {
+		pr_err("Invalid session count: %llu\n",
+		       (unsigned long long)header_ser->count);
+		return -EINVAL;
+	}
 
 	luo_session_global.incoming.header_ser = header_ser;
 	luo_session_global.incoming.ser = (void *)(header_ser + 1);
@@ -515,6 +526,7 @@ int luo_session_deserialize(void)
 	struct luo_session_header *sh = &luo_session_global.incoming;
 	static bool is_deserialized;
 	static int err;
+	u64 count;
 
 	/* If has been deserialized, always return the same error code */
 	if (is_deserialized)
@@ -524,6 +536,13 @@ int luo_session_deserialize(void)
 	if (!sh->active)
 		return 0;
 
+	count = sh->header_ser->count;
+	if (count > LUO_SESSION_MAX) {
+		pr_err("Invalid session count: %llu\n",
+		       (unsigned long long)count);
+		return -EINVAL;
+	}
+
 	/*
 	 * Note on error handling:
 	 *
@@ -539,7 +558,7 @@ int luo_session_deserialize(void)
 	 * userspace to detect the failure and trigger a reboot, which will
 	 * reliably reset devices and reclaim memory.
 	 */
-	for (int i = 0; i < sh->header_ser->count; i++) {
+	for (u64 i = 0; i < count; i++) {
 		struct luo_session *session;
 
 		session = luo_session_alloc(sh->ser[i].name);
@@ -606,4 +625,3 @@ int luo_session_serialize(void)
 
 	return err;
 }
-
-- 
2.53.0


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

* [PATCH v2 4/5] liveupdate: validate restored LUO file set metadata
  2026-05-01 17:30 ` [PATCH v2 0/5] liveupdate: validate restored LUO metadata Cris Jacob Maamor
                     ` (2 preceding siblings ...)
  2026-05-01 17:30   ` [PATCH v2 3/5] liveupdate: validate restored LUO session metadata Cris Jacob Maamor
@ 2026-05-01 17:30   ` Cris Jacob Maamor
  2026-05-01 17:30   ` [PATCH v2 5/5] liveupdate: validate restored LUO FLB metadata Cris Jacob Maamor
  2026-05-01 19:34   ` [PATCH v2 0/5] liveupdate: validate restored LUO metadata Pasha Tatashin
  5 siblings, 0 replies; 18+ messages in thread
From: Cris Jacob Maamor @ 2026-05-01 17:30 UTC (permalink / raw)
  To: Mike Rapoport, Pasha Tatashin, Pratyush Yadav
  Cc: Alexander Graf, Andrew Morton, Greg Kroah-Hartman, kexec,
	linux-mm, linux-kernel

The restored session metadata provides the LUO file set address and count.
LUO maps that address with phys_to_virt() and uses the restored count to
walk the serialized file array.

Reject invalid empty file set metadata, reject counts above LUO_FILE_MAX,
and check that the physical range is KHO-preserved before mapping it.

Signed-off-by: Cris Jacob Maamor <crisjacobmaamor@gmail.com>
---
 kernel/liveupdate/luo_file.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/kernel/liveupdate/luo_file.c b/kernel/liveupdate/luo_file.c
index a0a419085e28..cde43d822f8f 100644
--- a/kernel/liveupdate/luo_file.c
+++ b/kernel/liveupdate/luo_file.c
@@ -783,11 +783,21 @@ int luo_file_deserialize(struct luo_file_set *file_set,
 	struct luo_file_ser *file_ser;
 	u64 i;
 
-	if (!file_set_ser->files) {
-		WARN_ON(file_set_ser->count);
+	if (!file_set_ser->count) {
+		if (file_set_ser->files)
+			return -EINVAL;
 		return 0;
 	}
 
+	if (file_set_ser->count > LUO_FILE_MAX)
+		return -EINVAL;
+
+	if (!file_set_ser->files)
+		return -EINVAL;
+
+	if (!kho_is_preserved(file_set_ser->files, LUO_FILE_PGCNT))
+		return -EINVAL;
+
 	file_set->count = file_set_ser->count;
 	file_set->files = phys_to_virt(file_set_ser->files);
 
-- 
2.53.0


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

* [PATCH v2 5/5] liveupdate: validate restored LUO FLB metadata
  2026-05-01 17:30 ` [PATCH v2 0/5] liveupdate: validate restored LUO metadata Cris Jacob Maamor
                     ` (3 preceding siblings ...)
  2026-05-01 17:30   ` [PATCH v2 4/5] liveupdate: validate restored LUO file set metadata Cris Jacob Maamor
@ 2026-05-01 17:30   ` Cris Jacob Maamor
  2026-05-01 19:34   ` [PATCH v2 0/5] liveupdate: validate restored LUO metadata Pasha Tatashin
  5 siblings, 0 replies; 18+ messages in thread
From: Cris Jacob Maamor @ 2026-05-01 17:30 UTC (permalink / raw)
  To: Mike Rapoport, Pasha Tatashin, Pratyush Yadav
  Cc: Alexander Graf, Andrew Morton, Greg Kroah-Hartman, kexec,
	linux-mm, linux-kernel

The restored FDT contains the physical address of the LUO FLB header, which
LUO maps before using the restored FLB metadata.

Check that the FLB header range is KHO-preserved before calling
phys_to_virt(). Reject invalid page counts and counts above LUO_FLB_MAX
before walking the restored FLB array.

Signed-off-by: Cris Jacob Maamor <crisjacobmaamor@gmail.com>
---
 kernel/liveupdate/luo_flb.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/kernel/liveupdate/luo_flb.c b/kernel/liveupdate/luo_flb.c
index 00f5494812c4..e80032669cea 100644
--- a/kernel/liveupdate/luo_flb.c
+++ b/kernel/liveupdate/luo_flb.c
@@ -162,6 +162,7 @@ static int luo_flb_retrieve_one(struct liveupdate_flb *flb)
 	struct luo_flb_header *fh = &luo_flb_global.incoming;
 	struct liveupdate_flb_op_args args = {0};
 	bool found = false;
+	u64 count;
 	int err;
 
 	guard(mutex)(&private->incoming.lock);
@@ -175,7 +176,14 @@ static int luo_flb_retrieve_one(struct liveupdate_flb *flb)
 	if (!fh->active)
 		return -ENODATA;
 
-	for (int i = 0; i < fh->header_ser->count; i++) {
+	count = fh->header_ser->count;
+	if (count > LUO_FLB_MAX) {
+		pr_err("Invalid FLB count: %llu\n",
+		       (unsigned long long)count);
+		return -EINVAL;
+	}
+
+	for (u64 i = 0; i < count; i++) {
 		if (!strcmp(fh->ser[i].name, flb->compatible)) {
 			private->incoming.data = fh->ser[i].data;
 			private->incoming.count = fh->ser[i].count;
@@ -620,7 +628,20 @@ int __init luo_flb_setup_incoming(void *fdt_in)
 	}
 
 	header_ser_pa = get_unaligned((u64 *)ptr);
+	if (!kho_is_preserved(header_ser_pa, LUO_FLB_PGCNT)) {
+		pr_err("FLB header is not KHO preserved: %#llx\n",
+		       (unsigned long long)header_ser_pa);
+		return -EINVAL;
+	}
+
 	header_ser = phys_to_virt(header_ser_pa);
+	if (header_ser->pgcnt != LUO_FLB_PGCNT ||
+	    header_ser->count > LUO_FLB_MAX) {
+		pr_err("Invalid FLB header: pgcnt %llu count %llu\n",
+		       (unsigned long long)header_ser->pgcnt,
+		       (unsigned long long)header_ser->count);
+		return -EINVAL;
+	}
 
 	luo_flb_global.incoming.header_ser = header_ser;
 	luo_flb_global.incoming.ser = (void *)(header_ser + 1);
-- 
2.53.0


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

* Re: [PATCH v2 0/5] liveupdate: validate restored LUO metadata
  2026-05-01 17:30 ` [PATCH v2 0/5] liveupdate: validate restored LUO metadata Cris Jacob Maamor
                     ` (4 preceding siblings ...)
  2026-05-01 17:30   ` [PATCH v2 5/5] liveupdate: validate restored LUO FLB metadata Cris Jacob Maamor
@ 2026-05-01 19:34   ` Pasha Tatashin
  2026-05-06  9:02     ` Pratyush Yadav
  5 siblings, 1 reply; 18+ messages in thread
From: Pasha Tatashin @ 2026-05-01 19:34 UTC (permalink / raw)
  To: Cris Jacob Maamor
  Cc: Mike Rapoport, Pasha Tatashin, Pratyush Yadav, Alexander Graf,
	Andrew Morton, Greg Kroah-Hartman, kexec, linux-mm, linux-kernel

On 05-02 01:30, Cris Jacob Maamor wrote:
> LUO restores metadata from KHO/FDT during liveupdate. The restored
> metadata contains physical addresses and count fields used to access and
> walk preserved session, file set, and FLB arrays.
> 
> This series adds a non-consuming KHO preserved-range check and uses it
> before phys_to_virt() on restored metadata addresses. It also rejects
> restored counts above LUO_SESSION_MAX, LUO_FILE_MAX, and LUO_FLB_MAX
> before traversal.
> 
> As far as I can tell, this is root/admin-only; I do not have evidence
> that a normal unprivileged user can trigger it directly.
> 
> Changes since v1:
> - Dropped RFC marking.
> - Added changelog text to each patch.
> - No code changes.
> 
> Cris Jacob Maamor (5):
>   kexec: handover: add helper to check preserved page ranges
>   liveupdate: validate LUO FDT physical address before mapping
>   liveupdate: validate restored LUO session metadata
>   liveupdate: validate restored LUO file set metadata
>   liveupdate: validate restored LUO FLB metadata

I have replied separately in the security report to clarify that this is 
not a bug. The behavior follows the ABI specification exactly: we use 
the PA addresses and ranges provided by the KHO FDT tree.

NAK

> 
>  include/linux/kexec_handover.h     |  6 +++++
>  kernel/liveupdate/kexec_handover.c | 35 ++++++++++++++++++++++++++++++
>  kernel/liveupdate/luo_core.c       | 10 ++++++++-
>  kernel/liveupdate/luo_file.c       | 14 ++++++++++--
>  kernel/liveupdate/luo_flb.c        | 23 +++++++++++++++++++-
>  kernel/liveupdate/luo_session.c    | 22 +++++++++++++++++--
>  6 files changed, 104 insertions(+), 6 deletions(-)
> 
> -- 
> 2.53.0
> 

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

* Re: [PATCH v2 0/5] liveupdate: validate restored LUO metadata
  2026-05-01 19:34   ` [PATCH v2 0/5] liveupdate: validate restored LUO metadata Pasha Tatashin
@ 2026-05-06  9:02     ` Pratyush Yadav
  2026-05-06 15:05       ` Pasha Tatashin
  0 siblings, 1 reply; 18+ messages in thread
From: Pratyush Yadav @ 2026-05-06  9:02 UTC (permalink / raw)
  To: Pasha Tatashin
  Cc: Cris Jacob Maamor, Mike Rapoport, Pratyush Yadav, Alexander Graf,
	Andrew Morton, Greg Kroah-Hartman, kexec, linux-mm, linux-kernel

Hi Pasha,

On Fri, May 01 2026, Pasha Tatashin wrote:

> On 05-02 01:30, Cris Jacob Maamor wrote:
>> LUO restores metadata from KHO/FDT during liveupdate. The restored
>> metadata contains physical addresses and count fields used to access and
>> walk preserved session, file set, and FLB arrays.
>> 
>> This series adds a non-consuming KHO preserved-range check and uses it
>> before phys_to_virt() on restored metadata addresses. It also rejects
>> restored counts above LUO_SESSION_MAX, LUO_FILE_MAX, and LUO_FLB_MAX
>> before traversal.
>> 
>> As far as I can tell, this is root/admin-only; I do not have evidence
>> that a normal unprivileged user can trigger it directly.
>> 
>> Changes since v1:
>> - Dropped RFC marking.
>> - Added changelog text to each patch.
>> - No code changes.
>> 
>> Cris Jacob Maamor (5):
>>   kexec: handover: add helper to check preserved page ranges
>>   liveupdate: validate LUO FDT physical address before mapping
>>   liveupdate: validate restored LUO session metadata
>>   liveupdate: validate restored LUO file set metadata
>>   liveupdate: validate restored LUO FLB metadata
>
> I have replied separately in the security report to clarify that this is 
> not a bug. The behavior follows the ABI specification exactly: we use 
> the PA addresses and ranges provided by the KHO FDT tree.
>
> NAK

I really do think we should do a restore-only variant for the
kho_alloc_preserve() family of allocators and use it everywhere. It
would prevent problems in the future. Not because the previous kernel is
malicious, but because we might have bugs and the KHO page magic sanity
check acts as a defense in depth.

For example, I am currently looking at a LUO bug where LUO does not
track if a session is outgoing or incoming. So you can do a retrieve()
or finish() on an outgoing session. A lot of nastiness is saved because
of the page magic check. Things like kho_restore_vmalloc() or
kho_restore_folio() fail early and loudly.

If we want to squeeze out more performance later down the line we can
move it behind a debug config, but having this usage pattern of always
restoring before using is going to be a lot more sane than just using
physical addresses willy nilly.

The approach this series takes with kho_is_preserved() is the wrong
design. But a kho_restore() or something similar (maybe we can find a
better name?) is really where we should be going.

-- 
Regards,
Pratyush Yadav

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

* Re: [PATCH v2 0/5] liveupdate: validate restored LUO metadata
  2026-05-06  9:02     ` Pratyush Yadav
@ 2026-05-06 15:05       ` Pasha Tatashin
  2026-05-06 16:15         ` Pratyush Yadav
  0 siblings, 1 reply; 18+ messages in thread
From: Pasha Tatashin @ 2026-05-06 15:05 UTC (permalink / raw)
  To: Pratyush Yadav
  Cc: Pasha Tatashin, Cris Jacob Maamor, Mike Rapoport, Alexander Graf,
	Andrew Morton, Greg Kroah-Hartman, kexec, linux-mm, linux-kernel

On 05-06 11:02, Pratyush Yadav wrote:
> Hi Pasha,
> 
> On Fri, May 01 2026, Pasha Tatashin wrote:
> 
> > On 05-02 01:30, Cris Jacob Maamor wrote:
> >> LUO restores metadata from KHO/FDT during liveupdate. The restored
> >> metadata contains physical addresses and count fields used to access and
> >> walk preserved session, file set, and FLB arrays.
> >> 
> >> This series adds a non-consuming KHO preserved-range check and uses it
> >> before phys_to_virt() on restored metadata addresses. It also rejects
> >> restored counts above LUO_SESSION_MAX, LUO_FILE_MAX, and LUO_FLB_MAX
> >> before traversal.
> >> 
> >> As far as I can tell, this is root/admin-only; I do not have evidence
> >> that a normal unprivileged user can trigger it directly.
> >> 
> >> Changes since v1:
> >> - Dropped RFC marking.
> >> - Added changelog text to each patch.
> >> - No code changes.
> >> 
> >> Cris Jacob Maamor (5):
> >>   kexec: handover: add helper to check preserved page ranges
> >>   liveupdate: validate LUO FDT physical address before mapping
> >>   liveupdate: validate restored LUO session metadata
> >>   liveupdate: validate restored LUO file set metadata
> >>   liveupdate: validate restored LUO FLB metadata
> >
> > I have replied separately in the security report to clarify that this is 
> > not a bug. The behavior follows the ABI specification exactly: we use 
> > the PA addresses and ranges provided by the KHO FDT tree.
> >
> > NAK
> 
> I really do think we should do a restore-only variant for the
> kho_alloc_preserve() family of allocators and use it everywhere. It

That is unrelated to the provided patch series. The author of this 
series reported this as a security issue to the Linux security ML, and 
submitted this series at their request.

This is not a security issue, and in fact, it is not an issue at all. A 
restore-only variant can be added, but I do not see a reason for LUO to 
use it.

> would prevent problems in the future. Not because the previous kernel is
> malicious, but because we might have bugs and the KHO page magic sanity
> check acts as a defense in depth.
> 
> For example, I am currently looking at a LUO bug where LUO does not
> track if a session is outgoing or incoming. So you can do a retrieve()
> or finish() on an outgoing session. A lot of nastiness is saved because
> of the page magic check. Things like kho_restore_vmalloc() or
> kho_restore_folio() fail early and loudly.

I am not sure what bug you are looking at (please share the details!), 
but the fix absolutely should be to use outgoing/incoming sessions 
properly, and if we mixed them up somewhere, THAT should be fixed. Using 
KHO restore is not going to help much; however, I agree it can add 
some extra scrutiny (i.e., similar to an ASSERT), but it is not really 
something that would help improve correctness in any meaningful way. The 
correctness should lie in the LUO logic using incoming as incoming, and 
outgoing as outgoing.

> 
> If we want to squeeze out more performance later down the line we can
> move it behind a debug config, but having this usage pattern of always
> restoring before using is going to be a lot more sane than just using
> physical addresses willy nilly.
> 
> The approach this series takes with kho_is_preserved() is the wrong
> design. But a kho_restore() or something similar (maybe we can find a
> better name?) is really where we should be going.
> 
> -- 
> Regards,
> Pratyush Yadav

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

* Re: [PATCH v2 0/5] liveupdate: validate restored LUO metadata
  2026-05-06 15:05       ` Pasha Tatashin
@ 2026-05-06 16:15         ` Pratyush Yadav
  2026-05-06 16:34           ` Pasha Tatashin
  0 siblings, 1 reply; 18+ messages in thread
From: Pratyush Yadav @ 2026-05-06 16:15 UTC (permalink / raw)
  To: Pasha Tatashin
  Cc: Pratyush Yadav, Cris Jacob Maamor, Mike Rapoport, Alexander Graf,
	Andrew Morton, Greg Kroah-Hartman, kexec, linux-mm, linux-kernel

On Wed, May 06 2026, Pasha Tatashin wrote:

> On 05-06 11:02, Pratyush Yadav wrote:
>> Hi Pasha,
>> 
>> On Fri, May 01 2026, Pasha Tatashin wrote:
>> 
>> > On 05-02 01:30, Cris Jacob Maamor wrote:
>> >> LUO restores metadata from KHO/FDT during liveupdate. The restored
>> >> metadata contains physical addresses and count fields used to access and
>> >> walk preserved session, file set, and FLB arrays.
>> >> 
>> >> This series adds a non-consuming KHO preserved-range check and uses it
>> >> before phys_to_virt() on restored metadata addresses. It also rejects
>> >> restored counts above LUO_SESSION_MAX, LUO_FILE_MAX, and LUO_FLB_MAX
>> >> before traversal.
>> >> 
>> >> As far as I can tell, this is root/admin-only; I do not have evidence
>> >> that a normal unprivileged user can trigger it directly.
>> >> 
>> >> Changes since v1:
>> >> - Dropped RFC marking.
>> >> - Added changelog text to each patch.
>> >> - No code changes.
>> >> 
>> >> Cris Jacob Maamor (5):
>> >>   kexec: handover: add helper to check preserved page ranges
>> >>   liveupdate: validate LUO FDT physical address before mapping
>> >>   liveupdate: validate restored LUO session metadata
>> >>   liveupdate: validate restored LUO file set metadata
>> >>   liveupdate: validate restored LUO FLB metadata
>> >
>> > I have replied separately in the security report to clarify that this is 
>> > not a bug. The behavior follows the ABI specification exactly: we use 
>> > the PA addresses and ranges provided by the KHO FDT tree.
>> >
>> > NAK
>> 
>> I really do think we should do a restore-only variant for the
>> kho_alloc_preserve() family of allocators and use it everywhere. It
>
> That is unrelated to the provided patch series. The author of this 
> series reported this as a security issue to the Linux security ML, and 
> submitted this series at their request.

Oh yes, sure. I am not arguing for taking this series. I just figured
this would be a good point to have this discussion.

>
> This is not a security issue, and in fact, it is not an issue at all. A 
> restore-only variant can be added, but I do not see a reason for LUO to 
> use it.
>
>> would prevent problems in the future. Not because the previous kernel is
>> malicious, but because we might have bugs and the KHO page magic sanity
>> check acts as a defense in depth.
>> 
>> For example, I am currently looking at a LUO bug where LUO does not
>> track if a session is outgoing or incoming. So you can do a retrieve()
>> or finish() on an outgoing session. A lot of nastiness is saved because
>> of the page magic check. Things like kho_restore_vmalloc() or
>> kho_restore_folio() fail early and loudly.
>
> I am not sure what bug you are looking at (please share the details!), 

I was looking at LUO code and realized that we do not separate outgoing
and incoming sessions when dealing with preserve/retrieve/finish ioctls.
So you can create a session, preserve a FD, and then immediately call
finish or retrieve without doing a kexec. Of course, LUO file handlers
aren't able to cope with it.

So for example, you can preserve a memfd and then immediately call
finish. This will call memfd_luo_finish(), where it will try to
kho_restore_vmalloc(). That fails with a bit WARN splat. And then later
it calls kho_restore_free() which also fails in a similar fashion.

You can do the same thing with retrieve(), but that also fails early and
loudly and does not cause any problems.

I am working on a fix for it. Should have something out shortly.

> but the fix absolutely should be to use outgoing/incoming sessions 
> properly, and if we mixed them up somewhere, THAT should be fixed. Using 
> KHO restore is not going to help much; however, I agree it can add 
> some extra scrutiny (i.e., similar to an ASSERT), but it is not really 
> something that would help improve correctness in any meaningful way. The 
> correctness should lie in the LUO logic using incoming as incoming, and 
> outgoing as outgoing.

I am not arguing that we shouldn't fix the logic bugs. Of course we
should.

My point is that this sanity check acts as another layer of defence.
Bugs happen, but the earlier we catch them the better and this sanity
check helps us do exactly that.

For example, if we did not have these sanity checks, the loud errors I
described above would be replaced by silent use-after-free, double-free,
struct page corruption, or other problems.

So I would like to understand why you _don't_ want to have this line of
defence. What's the problem? If you are worried about performance, we
can go and measure it. If the overhead is too high this can be behind a
debug config.

>
>> 
>> If we want to squeeze out more performance later down the line we can
>> move it behind a debug config, but having this usage pattern of always
>> restoring before using is going to be a lot more sane than just using
>> physical addresses willy nilly.
>> 
>> The approach this series takes with kho_is_preserved() is the wrong
>> design. But a kho_restore() or something similar (maybe we can find a
>> better name?) is really where we should be going.
>> 
>> -- 
>> Regards,
>> Pratyush Yadav

-- 
Regards,
Pratyush Yadav

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

* Re: [PATCH v2 0/5] liveupdate: validate restored LUO metadata
  2026-05-06 16:15         ` Pratyush Yadav
@ 2026-05-06 16:34           ` Pasha Tatashin
  0 siblings, 0 replies; 18+ messages in thread
From: Pasha Tatashin @ 2026-05-06 16:34 UTC (permalink / raw)
  To: Pratyush Yadav
  Cc: Pasha Tatashin, Cris Jacob Maamor, Mike Rapoport, Alexander Graf,
	Andrew Morton, Greg Kroah-Hartman, kexec, linux-mm, linux-kernel

On 05-06 18:15, Pratyush Yadav wrote:
> On Wed, May 06 2026, Pasha Tatashin wrote:
> 
> > On 05-06 11:02, Pratyush Yadav wrote:
> >> Hi Pasha,
> >> 
> >> On Fri, May 01 2026, Pasha Tatashin wrote:
> >> 
> >> > On 05-02 01:30, Cris Jacob Maamor wrote:
> >> >> LUO restores metadata from KHO/FDT during liveupdate. The restored
> >> >> metadata contains physical addresses and count fields used to access and
> >> >> walk preserved session, file set, and FLB arrays.
> >> >> 
> >> >> This series adds a non-consuming KHO preserved-range check and uses it
> >> >> before phys_to_virt() on restored metadata addresses. It also rejects
> >> >> restored counts above LUO_SESSION_MAX, LUO_FILE_MAX, and LUO_FLB_MAX
> >> >> before traversal.
> >> >> 
> >> >> As far as I can tell, this is root/admin-only; I do not have evidence
> >> >> that a normal unprivileged user can trigger it directly.
> >> >> 
> >> >> Changes since v1:
> >> >> - Dropped RFC marking.
> >> >> - Added changelog text to each patch.
> >> >> - No code changes.
> >> >> 
> >> >> Cris Jacob Maamor (5):
> >> >>   kexec: handover: add helper to check preserved page ranges
> >> >>   liveupdate: validate LUO FDT physical address before mapping
> >> >>   liveupdate: validate restored LUO session metadata
> >> >>   liveupdate: validate restored LUO file set metadata
> >> >>   liveupdate: validate restored LUO FLB metadata
> >> >
> >> > I have replied separately in the security report to clarify that this is 
> >> > not a bug. The behavior follows the ABI specification exactly: we use 
> >> > the PA addresses and ranges provided by the KHO FDT tree.
> >> >
> >> > NAK
> >> 
> >> I really do think we should do a restore-only variant for the
> >> kho_alloc_preserve() family of allocators and use it everywhere. It
> >
> > That is unrelated to the provided patch series. The author of this 
> > series reported this as a security issue to the Linux security ML, and 
> > submitted this series at their request.
> 
> Oh yes, sure. I am not arguing for taking this series. I just figured
> this would be a good point to have this discussion.
> 
> >
> > This is not a security issue, and in fact, it is not an issue at all. A 
> > restore-only variant can be added, but I do not see a reason for LUO to 
> > use it.
> >
> >> would prevent problems in the future. Not because the previous kernel is
> >> malicious, but because we might have bugs and the KHO page magic sanity
> >> check acts as a defense in depth.
> >> 
> >> For example, I am currently looking at a LUO bug where LUO does not
> >> track if a session is outgoing or incoming. So you can do a retrieve()
> >> or finish() on an outgoing session. A lot of nastiness is saved because
> >> of the page magic check. Things like kho_restore_vmalloc() or
> >> kho_restore_folio() fail early and loudly.
> >
> > I am not sure what bug you are looking at (please share the details!), 
> 
> I was looking at LUO code and realized that we do not separate outgoing
> and incoming sessions when dealing with preserve/retrieve/finish ioctls.
> So you can create a session, preserve a FD, and then immediately call
> finish or retrieve without doing a kexec. Of course, LUO file handlers
> aren't able to cope with it.

Oh, this makes sense, please add a self-test for that as well :-)

> 
> So for example, you can preserve a memfd and then immediately call
> finish. This will call memfd_luo_finish(), where it will try to
> kho_restore_vmalloc(). That fails with a bit WARN splat. And then later
> it calls kho_restore_free() which also fails in a similar fashion.
> 
> You can do the same thing with retrieve(), but that also fails early and
> loudly and does not cause any problems.
> 
> I am working on a fix for it. Should have something out shortly.
> 
> > but the fix absolutely should be to use outgoing/incoming sessions 
> > properly, and if we mixed them up somewhere, THAT should be fixed. Using 
> > KHO restore is not going to help much; however, I agree it can add 
> > some extra scrutiny (i.e., similar to an ASSERT), but it is not really 
> > something that would help improve correctness in any meaningful way. The 
> > correctness should lie in the LUO logic using incoming as incoming, and 
> > outgoing as outgoing.
> 
> I am not arguing that we shouldn't fix the logic bugs. Of course we
> should.
> 
> My point is that this sanity check acts as another layer of defence.
> Bugs happen, but the earlier we catch them the better and this sanity
> check helps us do exactly that.
> 
> For example, if we did not have these sanity checks, the loud errors I
> described above would be replaced by silent use-after-free, double-free,
> struct page corruption, or other problems.
> 
> So I would like to understand why you _don't_ want to have this line of
> defence. What's the problem? If you are worried about performance, we
> can go and measure it. If the overhead is too high this can be behind a
> debug config.

Most likely, there is no performance cost, because when we free 
preserved memory, we still need to do a KHO restore. The only difference 
is that it may occur after a blackout not during blackout. Anyway, if 
you would like to add this sanity check, please send it out, and we can 
review and discuss how it looks.

> 
> >
> >> 
> >> If we want to squeeze out more performance later down the line we can
> >> move it behind a debug config, but having this usage pattern of always
> >> restoring before using is going to be a lot more sane than just using
> >> physical addresses willy nilly.
> >> 
> >> The approach this series takes with kho_is_preserved() is the wrong
> >> design. But a kho_restore() or something similar (maybe we can find a
> >> better name?) is really where we should be going.
> >> 
> >> -- 
> >> Regards,
> >> Pratyush Yadav
> 
> -- 
> Regards,
> Pratyush Yadav

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

end of thread, other threads:[~2026-05-06 16:34 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-01  9:46 [PATCH RFC 0/5] liveupdate: validate restored LUO metadata Cris Jacob Maamor
2026-05-01  9:46 ` [PATCH RFC 1/5] kexec: handover: add helper to check preserved page ranges Cris Jacob Maamor
2026-05-01 10:11   ` Greg Kroah-Hartman
2026-05-01  9:46 ` [PATCH RFC 2/5] liveupdate: validate restored LUO FDT before use Cris Jacob Maamor
2026-05-01  9:46 ` [PATCH RFC 3/5] liveupdate: validate restored LUO session metadata Cris Jacob Maamor
2026-05-01  9:46 ` [PATCH RFC 4/5] liveupdate: validate restored LUO file-set metadata Cris Jacob Maamor
2026-05-01  9:46 ` [PATCH RFC 5/5] liveupdate: validate restored LUO FLB metadata Cris Jacob Maamor
2026-05-01 17:30 ` [PATCH v2 0/5] liveupdate: validate restored LUO metadata Cris Jacob Maamor
2026-05-01 17:30   ` [PATCH v2 1/5] kexec: handover: add helper to check preserved page ranges Cris Jacob Maamor
2026-05-01 17:30   ` [PATCH v2 2/5] liveupdate: validate LUO FDT physical address before mapping Cris Jacob Maamor
2026-05-01 17:30   ` [PATCH v2 3/5] liveupdate: validate restored LUO session metadata Cris Jacob Maamor
2026-05-01 17:30   ` [PATCH v2 4/5] liveupdate: validate restored LUO file set metadata Cris Jacob Maamor
2026-05-01 17:30   ` [PATCH v2 5/5] liveupdate: validate restored LUO FLB metadata Cris Jacob Maamor
2026-05-01 19:34   ` [PATCH v2 0/5] liveupdate: validate restored LUO metadata Pasha Tatashin
2026-05-06  9:02     ` Pratyush Yadav
2026-05-06 15:05       ` Pasha Tatashin
2026-05-06 16:15         ` Pratyush Yadav
2026-05-06 16:34           ` Pasha Tatashin

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