All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stefano Stabellini <stefano.stabellini@amd.com>
To: Jan Beulich <jbeulich@suse.com>
Cc: Stefano Stabellini <stefano.stabellini@amd.com>,
	<andrew.cooper3@citrix.com>, <roger@xenproject.org>,
	<jason.andryuk@amd.com>, <teddy.astie@vates.tech>,
	<xen-devel@lists.xenproject.org>
Subject: Re: [PATCH v2] x86/bzimage: Check that the payload lies within the image
Date: Tue, 27 Oct 2026 12:43:25 -0700	[thread overview]
Message-ID: <6df73c0e-0d78-d7e4-3837-e4622271f02e@amd.com> (raw)
In-Reply-To: <19979fff-0554-4ec8-969b-6fe50606b1b1@suse.com>

On Tue, 27 Oct 2026, Jan Beulich wrote:
> On 26.10.2026 23:10, Stefano Stabellini wrote:
> > bzimage_check() doesn't validate setup_sects, payload_offset or
> > payload_length against the image size.  A truncated or malformed bzImage
> > therefore makes bzimage_headroom() and bzimage_parse() read beyond the
> > end of the boot module, which shows up as a fatal page fault, a bogus
> > headroom, or a decompression failure, rather than as a bad image.
> > 
> > Reject such a header up front.  bzimage_parse() passes bzimage_check() a
> > length which includes the decompression headroom in front of the image,
> > so subtract it to check against the image alone.
> > 
> > Signed-off-by: Stefano Stabellini <stefano.stabellini@amd.com>
> > ---
> > Changes in v2:
> > - drop the UL suffix: setup_sects is 8 bits wide, so the multiplication
> >   cannot overflow, and the offset is now computed the same way as where
> >   bzimage_headroom() and bzimage_parse() use it
> 
> Upon looking again, I think this may have been a mistake:
> 
> > @@ -65,6 +67,15 @@ static __init int bzimage_check(struct setup_header *hdr, unsigned long len)
> >             hdr->version >> 8, hdr->version & 0xff);
> >          return -EINVAL;
> >      }
> > +
> > +    payload_start = (hdr->setup_sects + 1) * 512 + hdr->payload_offset;
> 
> The multiplication can't overflow, but the addition can. Question is what
> the behavior should be in that case: Adding back the UL suffix would allow
> payload_start to go beyond 4Gb, but that may not be what is intended. The
> alternative would be to check for overflow in the calculation (easiest by
> way of using __builtin_add_overflow(), yet then needing adjustment when
> backporting to 4.20).

What about this


From: Stefano Stabellini <stefano.stabellini@amd.com>
Subject: [PATCH v3] x86/bzimage: Check that the payload lies within the image

bzimage_check() doesn't validate setup_sects, payload_offset or
payload_length against the image size.  A truncated or malformed bzImage
therefore makes bzimage_headroom() and bzimage_parse() read beyond the
end of the boot module, which shows up as a fatal page fault, a bogus
headroom, or a decompression failure, rather than as a bad image.

Reject such a header up front, including one whose payload offset
overflows the 32-bit calculation bzimage_headroom() and bzimage_parse()
use.  bzimage_parse() passes bzimage_check() a length which includes the
decompression headroom in front of the image, so subtract it to check
against the image alone.

Signed-off-by: Stefano Stabellini <stefano.stabellini@amd.com>
---
Changes in v3:
- reject a payload offset whose 32-bit calculation wraps; the addend is
  at most 256 * 512, so a wrapped sum is smaller than payload_offset
- drop "the" from the error message

Changes in v2:
- drop the UL suffix: setup_sects is 8 bits wide, so the multiplication
  cannot overflow, and the offset is now computed the same way as where
  bzimage_headroom() and bzimage_parse() use it
- reword the error message
- drop the dereferences from the comment
---
 xen/arch/x86/bzimage.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/xen/arch/x86/bzimage.c b/xen/arch/x86/bzimage.c
index 66f648f311..a0cba65000 100644
--- a/xen/arch/x86/bzimage.c
+++ b/xen/arch/x86/bzimage.c
@@ -54,6 +54,8 @@ struct __packed setup_header {
 
 static __init int bzimage_check(struct setup_header *hdr, unsigned long len)
 {
+    unsigned int payload_start;
+
     if ( len < sizeof(struct setup_header) )
         return 0;
 
@@ -65,6 +67,16 @@ static __init int bzimage_check(struct setup_header *hdr, unsigned long len)
            hdr->version >> 8, hdr->version & 0xff);
         return -EINVAL;
     }
+
+    payload_start = (hdr->setup_sects + 1) * 512 + hdr->payload_offset;
+    if ( payload_start < hdr->payload_offset ||
+         payload_start > len || hdr->payload_length > len - payload_start )
+    {
+        printk("bzImage payload %#x@%#x past image size (%#lx)\n",
+               hdr->payload_length, payload_start, len);
+        return -EINVAL;
+    }
+
     return 1;
 }
 
@@ -107,7 +119,8 @@ int __init bzimage_parse(void *image_base, void **image_start,
                          unsigned long *image_len)
 {
     struct setup_header *hdr = (struct setup_header *)(*image_start);
-    int err = bzimage_check(hdr, *image_len);
+    /* image_len also counts the headroom ahead of image_start. */
+    int err = bzimage_check(hdr, *image_len - (*image_start - image_base));
     unsigned long output_len;
 
     if ( err < 0 )
-- 
2.47.3



  reply	other threads:[~2026-10-27 19:43 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-20 21:48 [PATCH] x86/bzimage: Check that the payload lies within the image Stefano Stabellini
2026-10-21  9:30 ` Roger Pau Monné
2026-10-26 12:23   ` Jan Beulich
2026-10-26 22:10 ` [PATCH v2] " Stefano Stabellini
2026-10-27 10:51   ` Jan Beulich
2026-10-27 19:43     ` Stefano Stabellini [this message]
2026-10-28  7:05       ` Jan Beulich

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=6df73c0e-0d78-d7e4-3837-e4622271f02e@amd.com \
    --to=stefano.stabellini@amd.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=jason.andryuk@amd.com \
    --cc=jbeulich@suse.com \
    --cc=roger@xenproject.org \
    --cc=teddy.astie@vates.tech \
    --cc=xen-devel@lists.xenproject.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.