All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
To: pbonzini@redhat.com, ebiggers@kernel.org, x86@kernel.org,
	linux-kernel@vger.kernel.org, qemu-devel@nongnu.org,
	ardb@kernel.org, kraxel@redhat.com, hpa@zytor.com, bp@alien8.de
Cc: "Jason A. Donenfeld" <Jason@zx2c4.com>
Subject: [PATCH qemu] x86: don't let decompressed kernel image clobber setup_data
Date: Wed, 28 Dec 2022 15:38:30 +0100	[thread overview]
Message-ID: <20221228143831.396245-1-Jason@zx2c4.com> (raw)

The setup_data links are appended to the compressed kernel image. Since
the kernel image is typically loaded at 0x100000, setup_data lives at
`0x100000 + compressed_size`, which does not get relocated during the
kernel's boot process.

The kernel typically decompresses the image starting at address
0x1000000 (note: there's one more zero there than the decompressed image
above). This usually is fine for most kernels.

However, if the compressed image is actually quite large, then
setup_data will live at a `0x100000 + compressed_size` that extends into
the decompressed zone at 0x1000000. In other words, if compressed_size
is larger than `0x1000000 - 0x100000`, then the decompression step will
clobber setup_data, resulting in crashes.

Fix this by detecting that possibility, and if it occurs, put setup_data
*after* the end of the decompressed kernel, so that it doesn't get
clobbered.

One caveat is that this only works for images less than around 64
megabytes, so just bail out in that case. This is unfortunate, but I
don't currently have a way of fixing it.

Cc: x86@kernel.org
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
 hw/i386/x86.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index 78cc131926..628fd2b2e9 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -1077,6 +1077,36 @@ void x86_load_linux(X86MachineState *x86ms,
     }
     fclose(f);
 
+    /* If a setup_data is going to be used, make sure that the bootloader won't
+     * decompress into it and clobber those bytes. */
+    if (dtb_filename || !legacy_no_rng_seed) {
+        uint32_t payload_offset = ldl_p(setup + 0x248);
+        uint32_t payload_length = ldl_p(setup + 0x24c);
+        uint32_t target_address = ldl_p(setup + 0x258);
+        uint32_t decompressed_length = ldl_p(kernel + payload_offset + payload_length - 4);
+
+        uint32_t estimated_setup_data_length = 4096 * 16;
+        uint32_t start_setup_data = prot_addr + kernel_size;
+        uint32_t end_setup_data = start_setup_data + estimated_setup_data_length;
+        uint32_t start_target = target_address;
+        uint32_t end_target = target_address + decompressed_length;
+
+        if ((start_setup_data >= start_target && start_setup_data < end_target) ||
+            (end_setup_data >= start_target && end_setup_data < end_target)) {
+            uint32_t padded_size = target_address + decompressed_length - prot_addr;
+
+            /* The early stage can't address past around 64 MB from the original
+             * mapping, so just give up in that case. */
+            if (padded_size < 62 * 1024 * 1024)
+                kernel_size = padded_size;
+            else {
+                fprintf(stderr, "qemu: Kernel image too large to hold setup_data\n");
+                dtb_filename = NULL;
+                legacy_no_rng_seed = true;
+            }
+        }
+    }
+
     /* append dtb to kernel */
     if (dtb_filename) {
         if (protocol < 0x209) {
-- 
2.39.0


             reply	other threads:[~2022-12-28 14:38 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-28 14:38 Jason A. Donenfeld [this message]
2022-12-28 16:02 ` [PATCH qemu] x86: don't let decompressed kernel image clobber setup_data Philippe Mathieu-Daudé
2022-12-28 16:30   ` Jason A. Donenfeld
2022-12-28 16:57     ` Jason A. Donenfeld
2022-12-28 23:58       ` H. Peter Anvin
2022-12-29  2:13         ` H. Peter Anvin
2022-12-29  2:31         ` Jason A. Donenfeld
2022-12-29  7:28           ` Philippe Mathieu-Daudé
2022-12-29  7:30           ` H. Peter Anvin
2022-12-29  7:31           ` H. Peter Anvin
2022-12-29 12:47             ` Borislav Petkov
2022-12-30 15:54               ` Jason A. Donenfeld
2022-12-30 17:01                 ` Borislav Petkov
2022-12-30 17:07                   ` Jason A. Donenfeld
2022-12-30 19:54                     ` Borislav Petkov
2022-12-30 21:58                       ` H. Peter Anvin
2022-12-30 22:10                         ` Jason A. Donenfeld
2022-12-31  1:06                           ` H. Peter Anvin
2022-12-31  1:14                             ` H. Peter Anvin
2022-12-31 12:55                             ` Jason A. Donenfeld
2022-12-31 13:40                             ` Borislav Petkov
2022-12-31 13:44                               ` Jason A. Donenfeld
2022-12-31 13:48                                 ` Borislav Petkov
2022-12-31 13:51                                   ` Jason A. Donenfeld
2022-12-31 14:24                                     ` Borislav Petkov
2022-12-31 18:22                                       ` Jason A. Donenfeld
2022-12-31 19:00                                         ` Borislav Petkov
2023-01-01  3:21                                           ` H. Peter Anvin
2023-01-01  3:31                                             ` H. Peter Anvin
2023-01-02  6:01                                               ` Borislav Petkov
2023-01-02  6:17                                                 ` Borislav Petkov
2023-01-02  9:32                                                   ` Ard Biesheuvel
2023-01-02 13:36                                                     ` Borislav Petkov
2023-01-02 15:03                                                       ` Ard Biesheuvel
2023-01-02  5:50                                             ` Borislav Petkov
2023-01-01  4:33                                         ` H. Peter Anvin
2023-01-01  4:55                                           ` Mika Penttilä
2023-01-01  5:13                                             ` H. Peter Anvin
2022-12-30 15:59             ` Jason A. Donenfeld
2022-12-30 16:21               ` Jason A. Donenfeld
2022-12-30 19:13               ` H. Peter Anvin
2022-12-31  9:48               ` Borislav Petkov
2022-12-31 12:54                 ` Jason A. Donenfeld
2022-12-31 13:35                   ` Borislav Petkov
2022-12-31 13:42                     ` Jason A. Donenfeld
2022-12-30 18:30 ` Jason A. Donenfeld

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=20221228143831.396245-1-Jason@zx2c4.com \
    --to=jason@zx2c4.com \
    --cc=ardb@kernel.org \
    --cc=bp@alien8.de \
    --cc=ebiggers@kernel.org \
    --cc=hpa@zytor.com \
    --cc=kraxel@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=x86@kernel.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.