* [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®