x86/boot/compressed/64: Fix boot on machines with broken E820 table [Linux 4.19.72]

This Linux kernel change "x86/boot/compressed/64: Fix boot on machines with broken E820 table" is included in the Linux 4.19.72 release. This change is authored by Kirill A. Shutemov <kirill [at] shutemov.name> on Tue Aug 13 16:16:54 2019 +0300. The commit for this change in Linux stable tree is e02aac3 (patch) which is from upstream commit 0a46fff. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 0a46fff.

x86/boot/compressed/64: Fix boot on machines with broken E820 table

[ Upstream commit 0a46fff2f9108c2c44218380a43a736cf4612541 ]

BIOS on Samsung 500C Chromebook reports very rudimentary E820 table that
consists of 2 entries:

  BIOS-e820: [mem 0x0000000000000000-0x0000000000000fff] usable
  BIOS-e820: [mem 0x00000000fffff000-0x00000000ffffffff] reserved

It breaks logic in find_trampoline_placement(): bios_start lands on the
end of the first 4k page and trampoline start gets placed below 0.

Detect underflow and don't touch bios_start for such cases. It makes
kernel ignore E820 table on machines that doesn't have two usable pages
below BIOS_START_MAX.

Fixes: 1b3a62643660 ("x86/boot/compressed/64: Validate trampoline placement against E820")
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: x86-ml <x86@kernel.org>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=203463
Link: https://lkml.kernel.org/r/20190813131654.24378-1-kirill.shutemov@linux.intel.com
Signed-off-by: Sasha Levin <sashal@kernel.org>

There are 13 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 arch/x86/boot/compressed/pgtable_64.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/arch/x86/boot/compressed/pgtable_64.c b/arch/x86/boot/compressed/pgtable_64.c
index f8debf7..f0537a1 100644
--- a/arch/x86/boot/compressed/pgtable_64.c
+++ b/arch/x86/boot/compressed/pgtable_64.c
@@ -73,6 +73,8 @@ static unsigned long find_trampoline_placement(void)

    /* Find the first usable memory region under bios_start. */
    for (i = boot_params->e820_entries - 1; i >= 0; i--) {
+       unsigned long new;
+
        entry = &boot_params->e820_table[i];

        /* Skip all entries above bios_start. */
@@ -85,15 +87,20 @@ static unsigned long find_trampoline_placement(void)

        /* Adjust bios_start to the end of the entry if needed. */
        if (bios_start > entry->addr + entry->size)
-           bios_start = entry->addr + entry->size;
+           new = entry->addr + entry->size;

        /* Keep bios_start page-aligned. */
-       bios_start = round_down(bios_start, PAGE_SIZE);
+       new = round_down(new, PAGE_SIZE);

        /* Skip the entry if it's too small. */
-       if (bios_start - TRAMPOLINE_32BIT_SIZE < entry->addr)
+       if (new - TRAMPOLINE_32BIT_SIZE < entry->addr)
            continue;

+       /* Protect against underflow. */
+       if (new - TRAMPOLINE_32BIT_SIZE > bios_start)
+           break;
+
+       bios_start = new;
        break;
    }

Leave a Reply

Your email address will not be published. Required fields are marked *