mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/3] Address page fault in ima_restore_measurement_list()
@ 2025-12-29  8:15 Harshit Mogalapalli
  2025-12-29  8:15 ` [PATCH v2 1/3] ima: Add ima_validate_range() for previous kernel IMA buffer Harshit Mogalapalli
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Harshit Mogalapalli @ 2025-12-29  8:15 UTC (permalink / raw)
  To: zohar
  Cc: akpm, ardb, bp, dave.hansen, graf, guoweikang.kernel,
	harshit.m.mogalapalli, henry.willard, hpa, jbohac, joel.granados,
	linux-kernel, mingo, noodles, paul.x.webb, rppt, sohil.mehta,
	sourabhjain, stable, tglx, x86, yifei.l.liu

On x86_64:
When the second-stage kernel is booted via kexec with a limiting command
line such as "mem=<size>" we observe a pafe fault that happens.

    BUG: unable to handle page fault for address: ffff97793ff47000
    RIP: ima_restore_measurement_list+0xdc/0x45a
    #PF: error_code(0x0000) – not-present page

This happens on x86_64 only, as this is already fixed in aarch64 in
commit: cbf9c4b9617b ("of: check previous kernel's ima-kexec-buffer
against memory bounds")

V1: https://lore.kernel.org/all/20251112193005.3772542-1-harshit.m.mogalapalli@oracle.com/

V1 attempted to do a similar sanity check in x86_64. Borislav suggested
to add a generic helper ima_validate_range() which could then be used
for both OF based and x86_64.

Testing information:
--------------------
On x86_64: With latest 6.19-rc2 based, we could reproduce the issue, and
patched kernel works fine. (with mem=8G on a 16G memory machine)

Thanks for the reviews on V1.

V1 -> V2: 
 - Patch 1: Add a generic helper "ima_validate_range()"
 - Patch 2: Use this new helper in drivers/of/kexec.c -> No functional
   change.
 - Patch 3: Fix the page fault by doing sanity check with
   "ima_validate_range()"

Thanks,
Harshit

Harshit Mogalapalli (3):
  ima: Add ima_validate_range() for previous kernel IMA buffer
  of/kexec: refactor ima_get_kexec_buffer() to use ima_validate_range()
  x86/kexec: Add a sanity check on previous kernel's ima kexec buffer

 arch/x86/kernel/setup.c            |  6 +++++
 drivers/of/kexec.c                 | 15 +++----------
 include/linux/ima.h                |  1 +
 security/integrity/ima/ima_kexec.c | 35 ++++++++++++++++++++++++++++++
 4 files changed, 45 insertions(+), 12 deletions(-)

-- 
2.50.1


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

* [PATCH v2 1/3] ima: Add ima_validate_range() for previous kernel IMA buffer
  2025-12-29  8:15 [PATCH v2 0/3] Address page fault in ima_restore_measurement_list() Harshit Mogalapalli
@ 2025-12-29  8:15 ` Harshit Mogalapalli
  2025-12-30 20:35   ` Mimi Zohar
  2025-12-29  8:15 ` [PATCH v2 2/3] of/kexec: refactor ima_get_kexec_buffer() to use ima_validate_range() Harshit Mogalapalli
  2025-12-29  8:15 ` [PATCH v2 3/3] x86/kexec: Add a sanity check on previous kernel's ima kexec buffer Harshit Mogalapalli
  2 siblings, 1 reply; 8+ messages in thread
From: Harshit Mogalapalli @ 2025-12-29  8:15 UTC (permalink / raw)
  To: zohar
  Cc: akpm, ardb, bp, dave.hansen, graf, guoweikang.kernel,
	harshit.m.mogalapalli, henry.willard, hpa, jbohac, joel.granados,
	linux-kernel, mingo, noodles, paul.x.webb, rppt, sohil.mehta,
	sourabhjain, stable, tglx, x86, yifei.l.liu

When the second-stage kernel is booted with a limiting command line
(e.g. "mem=<size>"), the IMA measurement buffer handed over from the
previous kernel may fall outside the addressable RAM of the new kernel.
Accessing such a buffer can fault during early restore.

Introduce a small generic helper, ima_validate_range(), which verifies
that a physical [start, end] range for the previous-kernel IMA buffer
lies within addressable memory:
	- On x86, use pfn_range_is_mapped().
	- On OF based architectures, use page_is_ram().

Cc: stable@vger.kernel.org
Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
---
 include/linux/ima.h                |  1 +
 security/integrity/ima/ima_kexec.c | 35 ++++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/include/linux/ima.h b/include/linux/ima.h
index 8e29cb4e6a01..abf8923f8fc5 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -69,6 +69,7 @@ static inline int ima_measure_critical_data(const char *event_label,
 #ifdef CONFIG_HAVE_IMA_KEXEC
 int __init ima_free_kexec_buffer(void);
 int __init ima_get_kexec_buffer(void **addr, size_t *size);
+int ima_validate_range(phys_addr_t phys, size_t size);
 #endif
 
 #ifdef CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
index 7362f68f2d8b..8b24e3312ea0 100644
--- a/security/integrity/ima/ima_kexec.c
+++ b/security/integrity/ima/ima_kexec.c
@@ -12,6 +12,8 @@
 #include <linux/kexec.h>
 #include <linux/of.h>
 #include <linux/ima.h>
+#include <linux/mm.h>
+#include <linux/overflow.h>
 #include <linux/reboot.h>
 #include <asm/page.h>
 #include "ima.h"
@@ -296,3 +298,36 @@ void __init ima_load_kexec_buffer(void)
 		pr_debug("Error restoring the measurement list: %d\n", rc);
 	}
 }
+
+/*
+ * ima_validate_range - verify a physical buffer lies in addressable RAM
+ * @phys: physical start address of the buffer from previous kernel
+ * @size: size of the buffer
+ *
+ * On success return 0. On failure returns -EINVAL so callers can skip
+ * restoring.
+ */
+int ima_validate_range(phys_addr_t phys, size_t size)
+{
+	unsigned long start_pfn, end_pfn;
+	phys_addr_t end_phys;
+
+	if (check_add_overflow(phys, (phys_addr_t)size - 1, &end_phys))
+		return -EINVAL;
+
+	start_pfn = PHYS_PFN(phys);
+	end_pfn = PHYS_PFN(end_phys);
+
+#ifdef CONFIG_X86
+	if (!pfn_range_is_mapped(start_pfn, end_pfn))
+#else
+	if (!page_is_ram(start_pfn) || !page_is_ram(end_pfn))
+#endif
+	{
+		pr_warn("IMA: previous kernel measurement buffer %pa (size 0x%zx) lies outside available memory\n",
+			&phys, size);
+		return -EINVAL;
+	}
+
+	return 0;
+}
-- 
2.50.1


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

* [PATCH v2 2/3] of/kexec: refactor ima_get_kexec_buffer() to use ima_validate_range()
  2025-12-29  8:15 [PATCH v2 0/3] Address page fault in ima_restore_measurement_list() Harshit Mogalapalli
  2025-12-29  8:15 ` [PATCH v2 1/3] ima: Add ima_validate_range() for previous kernel IMA buffer Harshit Mogalapalli
@ 2025-12-29  8:15 ` Harshit Mogalapalli
  2025-12-30 23:45   ` Mimi Zohar
  2025-12-29  8:15 ` [PATCH v2 3/3] x86/kexec: Add a sanity check on previous kernel's ima kexec buffer Harshit Mogalapalli
  2 siblings, 1 reply; 8+ messages in thread
From: Harshit Mogalapalli @ 2025-12-29  8:15 UTC (permalink / raw)
  To: zohar
  Cc: akpm, ardb, bp, dave.hansen, graf, guoweikang.kernel,
	harshit.m.mogalapalli, henry.willard, hpa, jbohac, joel.granados,
	linux-kernel, mingo, noodles, paul.x.webb, rppt, sohil.mehta,
	sourabhjain, stable, tglx, x86, yifei.l.liu

Refactor the OF/DT ima_get_kexec_buffer() to use a generic helper to
validate the address range. No functional change intended.

Cc: stable@vger.kernel.org
Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
---
 drivers/of/kexec.c | 15 +++------------
 1 file changed, 3 insertions(+), 12 deletions(-)

diff --git a/drivers/of/kexec.c b/drivers/of/kexec.c
index 1ee2d31816ae..c4cf3552c018 100644
--- a/drivers/of/kexec.c
+++ b/drivers/of/kexec.c
@@ -128,7 +128,6 @@ int __init ima_get_kexec_buffer(void **addr, size_t *size)
 {
 	int ret, len;
 	unsigned long tmp_addr;
-	unsigned long start_pfn, end_pfn;
 	size_t tmp_size;
 	const void *prop;
 
@@ -144,17 +143,9 @@ int __init ima_get_kexec_buffer(void **addr, size_t *size)
 	if (!tmp_size)
 		return -ENOENT;
 
-	/*
-	 * Calculate the PFNs for the buffer and ensure
-	 * they are with in addressable memory.
-	 */
-	start_pfn = PHYS_PFN(tmp_addr);
-	end_pfn = PHYS_PFN(tmp_addr + tmp_size - 1);
-	if (!page_is_ram(start_pfn) || !page_is_ram(end_pfn)) {
-		pr_warn("IMA buffer at 0x%lx, size = 0x%zx beyond memory\n",
-			tmp_addr, tmp_size);
-		return -EINVAL;
-	}
+	ret = ima_validate_range(tmp_addr, tmp_size);
+	if (ret)
+		return ret;
 
 	*addr = __va(tmp_addr);
 	*size = tmp_size;
-- 
2.50.1


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

* [PATCH v2 3/3] x86/kexec: Add a sanity check on previous kernel's ima kexec buffer
  2025-12-29  8:15 [PATCH v2 0/3] Address page fault in ima_restore_measurement_list() Harshit Mogalapalli
  2025-12-29  8:15 ` [PATCH v2 1/3] ima: Add ima_validate_range() for previous kernel IMA buffer Harshit Mogalapalli
  2025-12-29  8:15 ` [PATCH v2 2/3] of/kexec: refactor ima_get_kexec_buffer() to use ima_validate_range() Harshit Mogalapalli
@ 2025-12-29  8:15 ` Harshit Mogalapalli
  2025-12-30 23:45   ` Mimi Zohar
  2 siblings, 1 reply; 8+ messages in thread
From: Harshit Mogalapalli @ 2025-12-29  8:15 UTC (permalink / raw)
  To: zohar
  Cc: akpm, ardb, bp, dave.hansen, graf, guoweikang.kernel,
	harshit.m.mogalapalli, henry.willard, hpa, jbohac, joel.granados,
	linux-kernel, mingo, noodles, paul.x.webb, rppt, sohil.mehta,
	sourabhjain, stable, tglx, x86, yifei.l.liu

When the second-stage kernel is booted via kexec with a limiting command
line such as "mem=<size>", the physical range that contains the carried
over IMA measurement list may fall outside the truncated RAM leading to
a kernel panic.

    BUG: unable to handle page fault for address: ffff97793ff47000
    RIP: ima_restore_measurement_list+0xdc/0x45a
    #PF: error_code(0x0000) – not-present page

Other architectures already validate the range with page_is_ram(), as
done in commit cbf9c4b9617b ("of: check previous kernel's
ima-kexec-buffer against memory bounds") do a similar check on x86.

Without carrying the measurement list across kexec, the attestation
would fail.

Cc: stable@vger.kernel.org
Fixes: b69a2afd5afc ("x86/kexec: Carry forward IMA measurement log on kexec")
Reported-by: Paul Webb <paul.x.webb@oracle.com>
Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
---
V1-> V2: Added a line about carrying measure list across kexec based on
suggestion from Mimi Zohar. Made use to the new generic helper
[Suggestion from Borislav]
---
 arch/x86/kernel/setup.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 1b2edd07a3e1..383d4a4784f5 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -439,9 +439,15 @@ int __init ima_free_kexec_buffer(void)
 
 int __init ima_get_kexec_buffer(void **addr, size_t *size)
 {
+	int ret;
+
 	if (!ima_kexec_buffer_size)
 		return -ENOENT;
 
+	ret = ima_validate_range(ima_kexec_buffer_phys, ima_kexec_buffer_size);
+	if (ret)
+		return ret;
+
 	*addr = __va(ima_kexec_buffer_phys);
 	*size = ima_kexec_buffer_size;
 
-- 
2.50.1


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

* Re: [PATCH v2 1/3] ima: Add ima_validate_range() for previous kernel IMA buffer
  2025-12-29  8:15 ` [PATCH v2 1/3] ima: Add ima_validate_range() for previous kernel IMA buffer Harshit Mogalapalli
@ 2025-12-30 20:35   ` Mimi Zohar
  2025-12-31  5:59     ` Harshit Mogalapalli
  0 siblings, 1 reply; 8+ messages in thread
From: Mimi Zohar @ 2025-12-30 20:35 UTC (permalink / raw)
  To: Harshit Mogalapalli
  Cc: akpm, ardb, bp, dave.hansen, graf, guoweikang.kernel,
	henry.willard, hpa, jbohac, joel.granados, linux-kernel, mingo,
	noodles, paul.x.webb, rppt, sohil.mehta, sourabhjain, stable,
	tglx, x86, yifei.l.liu

Hi Harshit,

The subject line could be written at a higher level.  Perhaps base it on the
ima_validate_range() function comment "verify a physical buffer lies in
addressable RAM" (e.g. ima: verify the previous kernel's IMA buffer lies in
addressable RAM). 

On Mon, 2025-12-29 at 00:15 -0800, Harshit Mogalapalli wrote:
> When the second-stage kernel is booted with a limiting command line
> (e.g. "mem=<size>"), the IMA measurement buffer handed over from the
> previous kernel may fall outside the addressable RAM of the new kernel.
> Accessing such a buffer can fault during early restore.
> 
> Introduce a small generic helper, ima_validate_range(), which verifies
> that a physical [start, end] range for the previous-kernel IMA buffer
> lies within addressable memory:
> 	- On x86, use pfn_range_is_mapped().
> 	- On OF based architectures, use page_is_ram().
> 
> Cc: stable@vger.kernel.org
> Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>

-- 
thanks,

Mimi

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

* Re: [PATCH v2 3/3] x86/kexec: Add a sanity check on previous kernel's ima kexec buffer
  2025-12-29  8:15 ` [PATCH v2 3/3] x86/kexec: Add a sanity check on previous kernel's ima kexec buffer Harshit Mogalapalli
@ 2025-12-30 23:45   ` Mimi Zohar
  0 siblings, 0 replies; 8+ messages in thread
From: Mimi Zohar @ 2025-12-30 23:45 UTC (permalink / raw)
  To: Harshit Mogalapalli
  Cc: akpm, ardb, bp, dave.hansen, graf, guoweikang.kernel,
	henry.willard, hpa, jbohac, joel.granados, linux-kernel, mingo,
	noodles, paul.x.webb, rppt, sohil.mehta, sourabhjain, stable,
	tglx, x86, yifei.l.liu

On Mon, 2025-12-29 at 00:15 -0800, Harshit Mogalapalli wrote:
> When the second-stage kernel is booted via kexec with a limiting command
> line such as "mem=<size>", the physical range that contains the carried
> over IMA measurement list may fall outside the truncated RAM leading to
> a kernel panic.
> 
>     BUG: unable to handle page fault for address: ffff97793ff47000
>     RIP: ima_restore_measurement_list+0xdc/0x45a
>     #PF: error_code(0x0000) – not-present page
> 
> Other architectures already validate the range with page_is_ram(), as
> done in commit cbf9c4b9617b ("of: check previous kernel's
> ima-kexec-buffer against memory bounds") do a similar check on x86.
> 
> Without carrying the measurement list across kexec, the attestation
> would fail.
> 
> Cc: stable@vger.kernel.org
> Fixes: b69a2afd5afc ("x86/kexec: Carry forward IMA measurement log on kexec")
> Reported-by: Paul Webb <paul.x.webb@oracle.com>
> Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
> ---
> V1-> V2: Added a line about carrying measure list across kexec based on
> suggestion from Mimi Zohar. Made use to the new generic helper
> [Suggestion from Borislav]

Thanks, Harshit.

Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>


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

* Re: [PATCH v2 2/3] of/kexec: refactor ima_get_kexec_buffer() to use ima_validate_range()
  2025-12-29  8:15 ` [PATCH v2 2/3] of/kexec: refactor ima_get_kexec_buffer() to use ima_validate_range() Harshit Mogalapalli
@ 2025-12-30 23:45   ` Mimi Zohar
  0 siblings, 0 replies; 8+ messages in thread
From: Mimi Zohar @ 2025-12-30 23:45 UTC (permalink / raw)
  To: Harshit Mogalapalli
  Cc: akpm, ardb, bp, dave.hansen, graf, guoweikang.kernel,
	henry.willard, hpa, jbohac, joel.granados, linux-kernel, mingo,
	noodles, paul.x.webb, rppt, sohil.mehta, sourabhjain, stable,
	tglx, x86, yifei.l.liu

On Mon, 2025-12-29 at 00:15 -0800, Harshit Mogalapalli wrote:
> Refactor the OF/DT ima_get_kexec_buffer() to use a generic helper to
> validate the address range. No functional change intended.
> 
> Cc: stable@vger.kernel.org
> Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>

Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>

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

* Re: [PATCH v2 1/3] ima: Add ima_validate_range() for previous kernel IMA buffer
  2025-12-30 20:35   ` Mimi Zohar
@ 2025-12-31  5:59     ` Harshit Mogalapalli
  0 siblings, 0 replies; 8+ messages in thread
From: Harshit Mogalapalli @ 2025-12-31  5:59 UTC (permalink / raw)
  To: Mimi Zohar
  Cc: akpm, ardb, bp, dave.hansen, graf, guoweikang.kernel,
	henry.willard, hpa, jbohac, joel.granados, linux-kernel, mingo,
	noodles, paul.x.webb, rppt, sohil.mehta, sourabhjain, stable,
	tglx, x86, yifei.l.liu

Hi Mimi,

On 31/12/25 02:05, Mimi Zohar wrote:
> Hi Harshit,
> 

Thanks for reviewing.

> The subject line could be written at a higher level.  Perhaps base it on the
> ima_validate_range() function comment "verify a physical buffer lies in
> addressable RAM" (e.g. ima: verify the previous kernel's IMA buffer lies in
> addressable RAM).
>

Sure, will do. Thanks for the suggestion.

Regards,
Harshit

> On Mon, 2025-12-29 at 00:15 -0800, Harshit Mogalapalli wrote:
>> When the second-stage kernel is booted with a limiting command line
>> (e.g. "mem=<size>"), the IMA measurement buffer handed over from the
>> previous kernel may fall outside the addressable RAM of the new kernel.
>> Accessing such a buffer can fault during early restore.
>>
>> Introduce a small generic helper, ima_validate_range(), which verifies
>> that a physical [start, end] range for the previous-kernel IMA buffer
>> lies within addressable memory:
>> 	- On x86, use pfn_range_is_mapped().
>> 	- On OF based architectures, use page_is_ram().
>>
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
> 


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

end of thread, other threads:[~2025-12-31  6:00 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-12-29  8:15 [PATCH v2 0/3] Address page fault in ima_restore_measurement_list() Harshit Mogalapalli
2025-12-29  8:15 ` [PATCH v2 1/3] ima: Add ima_validate_range() for previous kernel IMA buffer Harshit Mogalapalli
2025-12-30 20:35   ` Mimi Zohar
2025-12-31  5:59     ` Harshit Mogalapalli
2025-12-29  8:15 ` [PATCH v2 2/3] of/kexec: refactor ima_get_kexec_buffer() to use ima_validate_range() Harshit Mogalapalli
2025-12-30 23:45   ` Mimi Zohar
2025-12-29  8:15 ` [PATCH v2 3/3] x86/kexec: Add a sanity check on previous kernel's ima kexec buffer Harshit Mogalapalli
2025-12-30 23:45   ` Mimi Zohar

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

all inboxes | Powered by JetHome®