From ceb24c7052cc4649e3b52a51a7cca7dfe4896cec Mon Sep 17 00:00:00 2001 From: Fabrice Derepas Date: Wed, 12 Aug 2026 16:18:40 +0200 Subject: [PATCH] ima: reject a kexec buffer whose declared size exceeds the buffer 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 Signed-off-by: Mimi Zohar --- 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 daa897ccaf58..16154078fd70 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);