mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Mike Rapoport <rppt@kernel.org>
To: "Jérémy Jean" <Jeremy.Jean@oss.cyber.gouv.fr>
Cc: Andrew Morton <akpm@linux-foundation.org>,
	Baoquan He <baoquan.he@linux.dev>,
	Pasha Tatashin <pasha.tatashin@soleen.com>,
	Pratyush Yadav <pratyush@kernel.org>,
	Mimi Zohar <zohar@linux.ibm.com>,
	Roberto Sassu <roberto.sassu@huawei.com>,
	Dmitry Kasatkin <dmitry.kasatkin@gmail.com>,
	Eric Snowberg <eric.snowberg@oracle.com>,
	linux-integrity@vger.kernel.org,
	linux-security-module@vger.kernel.org,
	linux-kernel@vger.kernel.org, kexec@lists.infradead.org,
	stable@vger.kernel.org
Subject: Re: [PATCH] ima: fix kexec measurement buffer overflow after failed loads
Date: Tue, 10 Nov 2026 22:07:35 +0200	[thread overview]
Message-ID: <avN5hyR2V9C_4GPR@kernel.org> (raw)
In-Reply-To: <20261108190404.1397829-2-Jeremy.Jean@oss.cyber.gouv.fr>

On Sun, Nov 08, 2026 at 07:04:04PM +0000, Jérémy Jean wrote:
> When kexec_file_load() fails to install a new image, it can leave the
> global IMA scratch buffer larger than the IMA segment of the current
> image. When that image is executed, ima_update_kexec_buffer() copies
> the larger log past the end of its reserved segment. In a test, KASAN
> reports it as:

...

> Limit the dump to the smaller value between the scratch size and the
> installed image segment size. Update the IMA mapping only after
> machine_kexec_post_load() succeeds.

These are two different bugs and the changelog only explains the first.
The second one is that if machine_kexec_post_load() fails (e.g. -ENOMEM
in trans_pgd on arm64), ima_kexec_buffer is already switched to the
segment of the image that is about to be freed, so the installed image
loses the IMA update and kexec -e writes into freed pages.
Please spell this out, or better split it into a separate patch.

> diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
> --- a/kernel/kexec_file.c
> +++ b/kernel/kexec_file.c
> @@ -206,11 +206,13 @@ kimage_validate_signature(struct kimage *image)
>  
>  static int kexec_post_load(struct kimage *image, unsigned long flags)
>  {
> +	int ret = machine_kexec_post_load(image);
> +
>  #ifdef CONFIG_IMA_KEXEC
> -	if (!(flags & KEXEC_FILE_ON_CRASH))
> +	if (!ret && !(flags & KEXEC_FILE_ON_CRASH))
>  		ima_kexec_post_load(image);
>  #endif
> -	return machine_kexec_post_load(image);
> +	return ret;

Nit: an early "if (ret) return ret;" reads better than folding the error
into the IMA condition.

> diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
> --- a/security/integrity/ima/ima_kexec.c
> +++ b/security/integrity/ima/ima_kexec.c
> @@ -98,12 +97,14 @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
> +	/* A failed replacement load may have resized the scratch buffer. */
> +	ima_kexec_file.size = min_t(size_t, ima_kexec_file.size, segment_size);

This prevents the overflow, but it treats the symptom at execute time.
The actual problem is that ima_add_kexec_buffer() updates global state
(ima_kexec_file and kexec_segment_size) for an image that may never be
installed.

When the failed load had a smaller measurement list (with staging the
list can shrink), the dump is still truncated to the failed image's
size and the next kernel gets an incomplete log. kexec_segment_size
reported in the "kexec_execute" event is also the failed image's one.

With the first hunk ima_kexec_post_load() runs only for an image that
is going to be installed, so wouldn't it be cleaner to (re)size the
scratch buffer and kexec_segment_size there, from image->ima_buffer_size?
Then the comment you removed would actually become true.

> @@ -239,7 +240,8 @@ static int ima_update_kexec_buffer(struct notifier_block *self,
> -	ret = ima_dump_measurement_list(&buf_size, &buf, kexec_segment_size);
> +	ret = ima_dump_measurement_list(&buf_size, &buf,
> +					kexec_image->ima_buffer_size);

ima_kexec_buffer is not tied to kexec_image. After a successful
kexec_file_load() followed by KEXEC_FILE_UNLOAD or by a successful
kexec_load(), the old image is freed but ima_kexec_buffer still maps its
pages. kexec_image->ima_buffer_size is 0 for a kexec_load() image, so
with this patch the dump fails, but buf_size is still the header size
and memcpy() writes it into freed pages.

That's pre-existing and not a reason to hold this patch, but it's the
same class of bug and I think IMA should check that ima_kexec_buffer
belongs to kexec_image (or drop the mapping when the image is replaced)
rather than rely on sizes matching.

--
Sincerely yours,
Mike.


      reply	other threads:[~2026-11-10 20:07 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-08 19:04 Jérémy Jean
2026-11-10 20:07 ` Mike Rapoport [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=avN5hyR2V9C_4GPR@kernel.org \
    --to=rppt@kernel.org \
    --cc=Jeremy.Jean@oss.cyber.gouv.fr \
    --cc=akpm@linux-foundation.org \
    --cc=baoquan.he@linux.dev \
    --cc=dmitry.kasatkin@gmail.com \
    --cc=eric.snowberg@oracle.com \
    --cc=kexec@lists.infradead.org \
    --cc=linux-integrity@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=pasha.tatashin@soleen.com \
    --cc=pratyush@kernel.org \
    --cc=roberto.sassu@huawei.com \
    --cc=stable@vger.kernel.org \
    --cc=zohar@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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®