ima_restore_measurement_list() parses the measurement list persisted across
kexec.  It computes the parse end directly from the blob:

        bufendp = buf + khdr->buffer_size;

khdr->buffer_size is a u64 read straight from the persisted buffer.  The
only length checks in the function are size >= sizeof(*khdr), version == 1
and count -- none relates buffer_size to size, the actual buffer size the
caller (ima_load_kexec_buffer()) obtained from the ima-kexec-buffer region.
ima_parse_buf() bounds every field read to bufendp, so a blob whose
internal buffer_size exceeds the real size makes the parse loop read past
the end of the buffer (CWE-125).

The buffer's memory range is validated against addressable RAM by
commit cbf9c4b9617b ("of: check previous kernel's ima-kexec-buffer
against memory bounds") and commit c5489d04337b ("x86/kexec: add a
sanity check on previous kernel's ima kexec buffer"), but the blob's
own declared size is never clamped to it.  Reject a buffer_size larger
than size before the loop.

This is on the boot-time kexec-restore path (__init) and the buffer comes
from the previous kernel, so triggering it requires control of the
persisted buffer; it is an out-of-bounds read only.

Fixes: 94c3aac567a9 ("ima: on soft reboot, restore the measurement list")
Assisted-by: copilot-cli:claude-opus-4-6 frama-c
Signed-off-by: Fabrice Derepas <[email protected]>
---
Tested under KASAN (CONFIG_KASAN_GENERIC, x86-64) with a KUnit case that calls
ima_restore_measurement_list() on a 24-byte buffer whose header declares
buffer_size = 0x1000.  On an unpatched kernel this takes a slab-out-of-bounds
read of size 4 in ima_parse_buf() from ima_restore_measurement_list(); with
this patch the buffer is rejected and the case passes with no KASAN report.
The test is not included here (there is no upstream IMA KUnit suite yet); I'm
happy to submit it separately if useful.

 security/integrity/ima/ima_template.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/security/integrity/ima/ima_template.c 
b/security/integrity/ima/ima_template.c
index 7034573..2467cae 100644
--- a/security/integrity/ima/ima_template.c
+++ b/security/integrity/ima/ima_template.c
@@ -450,6 +450,11 @@ int ima_restore_measurement_list(loff_t size, void *buf)
                return -EINVAL;
        }
 
+       if (khdr->buffer_size > size) {
+               pr_err("attempting to restore a corrupted measurement list");
+               return -EINVAL;
+       }
+
        bitmap_zero(hdr_mask, HDR__LAST);
        bitmap_set(hdr_mask, HDR_PCR, 1);
        bitmap_set(hdr_mask, HDR_DIGEST, 1);
base-commit: f5bbbfec59b4e2fb7520a91de3df8a6174325d6a
-- 
2.53.0


Reply via email to