grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] loader/i386/linux: Calculate the setup_header length


From: Ross Philipson
Subject: Re: [PATCH] loader/i386/linux: Calculate the setup_header length
Date: Fri, 29 Mar 2019 11:55:12 -0400
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.5.2

On 03/29/2019 11:09 AM, Daniel Kiper wrote:
> From: Andrew Jeddeloh <address@hidden>
> 
> 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 <address@hidden>
> Signed-off-by: Daniel Kiper <address@hidden>
> ---
>  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);
> +

I am a little confused about the logic here and what exactly you are
trying to get the size of. The size of just the setup_header portion
would start at 0x1f1 so the logic for finding that would be something like:

len = (0x202 - 0x1f1) + *((char *) &linux_params.jump + 1);

If you are trying to find the size of all the boot params, your
calculation would leave out edd_mbr_sig_buffer and e820_map which are
after the end of the setup_header.

Note I am using setup_header as a reference to the struct as defined in
linux. GRUB does not separate it out as it's own struct but just puts
the fields in the overall linux_kernel_params struct. Maybe it should be
broken out as a separate structure for clarity.

>    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;

Yea I noticed these were missing, good to add them. You should move that
comment down nd update it to /* 268 */

Also since you added these here, do you want to add them to
linux_i386_kernel_header for consistency? That struct is still stuck at
boot protocol verion 2.10 as stated in the comment.

> +  /* 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 */
>  
> 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]