From: Andrew Jeddeloh <andrew.jedde...@coreos.com> Previously the setup_header length was just assumed to be the size of the linux_kernel_params struct. The linux x86 32-bit boot protocol says that the size of the linux_i386_kernel_header is 0x202 + the byte value at 0x201 in the linux_i386_kernel_header. Calculate the size of the header, rather than assume it is the size of the linux_kernel_params struct.
Additionally, add some required members to the linux_kernel_params struct and align the content of linux_i386_kernel_header struct with it. New members naming was taken directly from Linux kernel source. linux_kernel_params and linux_i386_kernel_header structs require more cleanup. However, this is not urgent, so, let's do this after release. Just in case... Signed-off-by: Andrew Jeddeloh <andrew.jedde...@coreos.com> Signed-off-by: Daniel Kiper <daniel.ki...@oracle.com> --- grub-core/loader/i386/linux.c | 16 +++++++++++++++- include/grub/i386/linux.h | 14 ++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index b6015913b..73e15a90f 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -767,7 +767,21 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), linux_params.kernel_alignment = (1 << align); linux_params.ps_mouse = linux_params.padding10 = 0; - len = sizeof (linux_params) - sizeof (lh); + /* + * The Linux 32-bit boot protocol defines the setup header size + * to be 0x202 + the byte value at 0x201. + */ + len = 0x202 + *((char *) &linux_params.jump + 1); + + /* Verify the struct is big enough so we do not write past the end. */ + if (len > (char *) &linux_params.edd_mbr_sig_buffer - (char *) &linux_params) { + grub_error (GRUB_ERR_BAD_OS, "Linux setup header too big"); + goto fail; + } + + /* We've already read lh so there is no need to read it second time. */ + len -= sizeof(lh); + if (grub_file_read (file, (char *) &linux_params + sizeof (lh), len) != len) { if (!grub_errno) diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h index a96059311..ce30e7fb0 100644 --- a/include/grub/i386/linux.h +++ b/include/grub/i386/linux.h @@ -46,6 +46,9 @@ #define VIDEO_CAPABILITY_SKIP_QUIRKS (1 << 0) #define VIDEO_CAPABILITY_64BIT_BASE (1 << 1) /* Frame buffer base is 64-bit. */ +/* Maximum number of MBR signatures to store. */ +#define EDD_MBR_SIG_MAX 16 + #ifdef __x86_64__ #define GRUB_LINUX_EFI_SIGNATURE \ @@ -142,6 +145,7 @@ struct linux_i386_kernel_header grub_uint64_t setup_data; grub_uint64_t pref_address; grub_uint32_t init_size; + grub_uint32_t handover_offset; } GRUB_PACKED; /* Boot parameters for Linux based on 2.6.12. This is used by the setup @@ -273,6 +277,7 @@ struct linux_kernel_params grub_uint8_t padding9[0x1f1 - 0x1e9]; + /* Linux setup header copy - BEGIN. */ grub_uint8_t setup_sects; /* The size of the setup in sectors */ grub_uint16_t root_flags; /* If the root is mounted readonly */ grub_uint16_t syssize; /* obsolete */ @@ -311,9 +316,14 @@ struct linux_kernel_params grub_uint32_t payload_offset; grub_uint32_t payload_length; grub_uint64_t setup_data; - grub_uint8_t pad2[120]; /* 258 */ + grub_uint64_t pref_address; + grub_uint32_t init_size; + grub_uint32_t handover_offset; + /* Linux setup header copy - END. */ + + grub_uint8_t _pad7[40]; + grub_uint32_t edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 290 */ struct grub_e820_mmap e820_map[(0x400 - 0x2d0) / 20]; /* 2d0 */ - } GRUB_PACKED; #endif /* ! ASM_FILE */ -- 2.11.0 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel