mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v3 0/3] Address page fault in ima_restore_measurement_list()
@ 2025-12-31  6:16 Harshit Mogalapalli
  2025-12-31  6:16 ` [PATCH v3 1/3] ima: verify the previous kernel's IMA buffer lies in addressable RAM Harshit Mogalapalli
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Harshit Mogalapalli @ 2025-12-31  6:16 UTC (permalink / raw)
  To: zohar, akpm
  Cc: 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 to Yifei for finding enabling IMA_KEXEC is the cause.

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()"

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

V2 -> V3:
 Update subject of Patch 1 to more appropriate one (Suggested by Mimi
Zohar)

Thanks,
Harshit

Harshit Mogalapalli (3):
  ima: verify the previous kernel's IMA buffer lies in addressable RAM
  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] 5+ messages in thread

* [PATCH v3 1/3] ima: verify the previous kernel's IMA buffer lies in addressable RAM
  2025-12-31  6:16 [PATCH v3 0/3] Address page fault in ima_restore_measurement_list() Harshit Mogalapalli
@ 2025-12-31  6:16 ` Harshit Mogalapalli
  2026-01-02 20:30   ` Mimi Zohar
  2025-12-31  6:16 ` [PATCH v3 2/3] of/kexec: refactor ima_get_kexec_buffer() to use ima_validate_range() Harshit Mogalapalli
  2025-12-31  6:16 ` [PATCH v3 3/3] x86/kexec: Add a sanity check on previous kernel's ima kexec buffer Harshit Mogalapalli
  2 siblings, 1 reply; 5+ messages in thread
From: Harshit Mogalapalli @ 2025-12-31  6:16 UTC (permalink / raw)
  To: zohar, akpm
  Cc: 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>
---
v2->v3: Update subject to exactly describe the patch [ Suggested by Mimi
Zohar]
---
 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] 5+ messages in thread

* [PATCH v3 2/3] of/kexec: refactor ima_get_kexec_buffer() to use ima_validate_range()
  2025-12-31  6:16 [PATCH v3 0/3] Address page fault in ima_restore_measurement_list() Harshit Mogalapalli
  2025-12-31  6:16 ` [PATCH v3 1/3] ima: verify the previous kernel's IMA buffer lies in addressable RAM Harshit Mogalapalli
@ 2025-12-31  6:16 ` Harshit Mogalapalli
  2025-12-31  6:16 ` [PATCH v3 3/3] x86/kexec: Add a sanity check on previous kernel's ima kexec buffer Harshit Mogalapalli
  2 siblings, 0 replies; 5+ messages in thread
From: Harshit Mogalapalli @ 2025-12-31  6:16 UTC (permalink / raw)
  To: zohar, akpm
  Cc: 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
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
---
V2-> V3: Add RB from Mimi Zohar.
---
 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] 5+ messages in thread

* [PATCH v3 3/3] x86/kexec: Add a sanity check on previous kernel's ima kexec buffer
  2025-12-31  6:16 [PATCH v3 0/3] Address page fault in ima_restore_measurement_list() Harshit Mogalapalli
  2025-12-31  6:16 ` [PATCH v3 1/3] ima: verify the previous kernel's IMA buffer lies in addressable RAM Harshit Mogalapalli
  2025-12-31  6:16 ` [PATCH v3 2/3] of/kexec: refactor ima_get_kexec_buffer() to use ima_validate_range() Harshit Mogalapalli
@ 2025-12-31  6:16 ` Harshit Mogalapalli
  2 siblings, 0 replies; 5+ messages in thread
From: Harshit Mogalapalli @ 2025-12-31  6:16 UTC (permalink / raw)
  To: zohar, akpm
  Cc: 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>
Reviewed-by: Mimi Zohar <zohar@linux.ibm.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]

V2-> V3: Add RB from Mimi Zohar.
---
 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] 5+ messages in thread

* Re: [PATCH v3 1/3] ima: verify the previous kernel's IMA buffer lies in addressable RAM
  2025-12-31  6:16 ` [PATCH v3 1/3] ima: verify the previous kernel's IMA buffer lies in addressable RAM Harshit Mogalapalli
@ 2026-01-02 20:30   ` Mimi Zohar
  0 siblings, 0 replies; 5+ messages in thread
From: Mimi Zohar @ 2026-01-02 20:30 UTC (permalink / raw)
  To: Harshit Mogalapalli, akpm
  Cc: 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 Tue, 2025-12-30 at 22:16 -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!

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

> ---
> v2->v3: Update subject to exactly describe the patch [ Suggested by Mimi
> Zohar]
> ---
>  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;
> +}


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

end of thread, other threads:[~2026-01-02 20:31 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-12-31  6:16 [PATCH v3 0/3] Address page fault in ima_restore_measurement_list() Harshit Mogalapalli
2025-12-31  6:16 ` [PATCH v3 1/3] ima: verify the previous kernel's IMA buffer lies in addressable RAM Harshit Mogalapalli
2026-01-02 20:30   ` Mimi Zohar
2025-12-31  6:16 ` [PATCH v3 2/3] of/kexec: refactor ima_get_kexec_buffer() to use ima_validate_range() Harshit Mogalapalli
2025-12-31  6:16 ` [PATCH v3 3/3] x86/kexec: Add a sanity check on previous kernel's ima kexec buffer Harshit Mogalapalli

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®