x86, boot: Sanitize boot_params if not zeroed on creation
authorH. Peter Anvin <hpa@linux.intel.com>
Tue, 29 Jan 2013 09:05:24 +0000 (01:05 -0800)
committerH. Peter Anvin <hpa@linux.intel.com>
Tue, 29 Jan 2013 09:22:17 +0000 (01:22 -0800)
Use the new sentinel field to detect bootloaders which fail to follow
protocol and don't initialize fields in struct boot_params that they
do not explicitly initialize to zero.

Based on an original patch and research by Yinghai Lu.
Changed by hpa to be invoked both in the decompression path and in the
kernel proper; the latter for the case where a bootloader takes over
decompression.

Originally-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1359058816-7615-26-git-send-email-yinghai@kernel.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
arch/x86/boot/compressed/misc.c
arch/x86/boot/compressed/misc.h
arch/x86/include/asm/bootparam_utils.h [new file with mode: 0644]
arch/x86/kernel/head32.c
arch/x86/kernel/head64.c

index 88f7ff6da40442086b6c6664b227f00f97bf2711..7cb56c6ca35154f19d3a1f4242845f8242a37202 100644 (file)
@@ -325,6 +325,8 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
 {
        real_mode = rmode;
 
+       sanitize_boot_params(real_mode);
+
        if (real_mode->screen_info.orig_video_mode == 7) {
                vidmem = (char *) 0xb0000;
                vidport = 0x3b4;
index 0e6dc0ee0eeabd04fc283bce937b734ea42923c7..674019d8e2355901b69de5c55cfb92669c5628be 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/page.h>
 #include <asm/boot.h>
 #include <asm/bootparam.h>
+#include <asm/bootparam_utils.h>
 
 #define BOOT_BOOT_H
 #include "../ctype.h"
diff --git a/arch/x86/include/asm/bootparam_utils.h b/arch/x86/include/asm/bootparam_utils.h
new file mode 100644 (file)
index 0000000..5b5e9cb
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef _ASM_X86_BOOTPARAM_UTILS_H
+#define _ASM_X86_BOOTPARAM_UTILS_H
+
+#include <asm/bootparam.h>
+
+/*
+ * This file is included from multiple environments.  Do not
+ * add completing #includes to make it standalone.
+ */
+
+/*
+ * Deal with bootloaders which fail to initialize unknown fields in
+ * boot_params to zero.  The list fields in this list are taken from
+ * analysis of kexec-tools; if other broken bootloaders initialize a
+ * different set of fields we will need to figure out how to disambiguate.
+ *
+ */
+static void sanitize_boot_params(struct boot_params *boot_params)
+{
+       if (boot_params->sentinel) {
+               /*fields in boot_params are not valid, clear them */
+               memset(&boot_params->olpc_ofw_header, 0,
+                      (char *)&boot_params->alt_mem_k -
+                       (char *)&boot_params->olpc_ofw_header);
+               memset(&boot_params->kbd_status, 0,
+                      (char *)&boot_params->hdr -
+                      (char *)&boot_params->kbd_status);
+               memset(&boot_params->_pad7[0], 0,
+                      (char *)&boot_params->edd_mbr_sig_buffer[0] -
+                       (char *)&boot_params->_pad7[0]);
+               memset(&boot_params->_pad8[0], 0,
+                      (char *)&boot_params->eddbuf[0] -
+                       (char *)&boot_params->_pad8[0]);
+               memset(&boot_params->_pad9[0], 0, sizeof(boot_params->_pad9));
+       }
+}
+
+#endif /* _ASM_X86_BOOTPARAM_UTILS_H */
index c18f59d10101cefc82f6638bcca758a480b70cc3..6773c918b8ccb641a02d54d3b11e3433b4b72915 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/io_apic.h>
 #include <asm/bios_ebda.h>
 #include <asm/tlbflush.h>
+#include <asm/bootparam_utils.h>
 
 static void __init i386_default_early_setup(void)
 {
@@ -30,6 +31,8 @@ static void __init i386_default_early_setup(void)
 
 void __init i386_start_kernel(void)
 {
+       sanitize_boot_params(&boot_params);
+
        memblock_reserve(__pa_symbol(&_text),
                         __pa_symbol(&__bss_stop) - __pa_symbol(&_text));
 
index 037df57a99ac34d5ba1a5cab5abaa4554e0689d0..849fc9e63c2ffd875ba23d7bb2ea879ac756c30f 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/kdebug.h>
 #include <asm/e820.h>
 #include <asm/bios_ebda.h>
+#include <asm/bootparam_utils.h>
 
 static void __init zap_identity_mappings(void)
 {
@@ -46,6 +47,7 @@ static void __init copy_bootdata(char *real_mode_data)
        char * command_line;
 
        memcpy(&boot_params, real_mode_data, sizeof boot_params);
+       sanitize_boot_params(&boot_params);
        if (boot_params.hdr.cmd_line_ptr) {
                command_line = __va(boot_params.hdr.cmd_line_ptr);
                memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);