vbutil_kernel: copy zeropage fully

When copying the vmlinuz zeropage, the entries were being truncated even
though the boot protocol version was being retained. This means that
booting a kernel that depended on details from the zeropage's ignored
areas would find invalid information. Fix this by copying out the entire
possible range of memory.

BUG=chromium:230212
TEST=kernels can boot with CONFIG_RELOCATABLE
BRANCH=None

Change-Id: Ifb94bedcf881e17ab20fff44d8c1c1885b15ef9e
Signed-off-by: Kees Cook <keescook@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/47832
Reviewed-by: Luigi Semenzato <semenzato@chromium.org>
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
diff --git a/utility/include/kernel_blob.h b/utility/include/kernel_blob.h
index 5784542..f9175f6 100644
--- a/utility/include/kernel_blob.h
+++ b/utility/include/kernel_blob.h
@@ -23,14 +23,6 @@
 // RAM address where the 32-bit kernel expects to be started
 #define CROS_32BIT_ENTRY_ADDR  0x100000
 
-// Simplified version of the vmlinuz file header
-struct linux_kernel_header
-{
-  uint8_t  pad0[0x01f1 - 0x0];
-  uint8_t  setup_sects;                 // 1f1
-  uint8_t  pad1[0x0230 - 0x1f2];
-} __attribute__ ((packed));
-
 // Simplified version of x86 kernel e820 memory map entries
 #define E820_ENTRY_MAX 128
 #define E820_TYPE_RAM      1
@@ -51,14 +43,21 @@
   uint8_t  setup_sects;                 // 1f1
   uint8_t  pad2[0x1fe - 0x1f2];
   uint16_t boot_flag;                   // 1fe
-  uint8_t  pad3[0x210 - 0x200];
+  uint16_t jump;                        // 200
+  uint32_t header;                      // 202
+  uint16_t version;                     // 206
+  uint8_t  pad3[0x210 - 0x208];
   uint8_t  type_of_loader;              // 210
   uint8_t  pad4[0x218 - 0x211];
   uint32_t ramdisk_image;               // 218
   uint32_t ramdisk_size;                // 21c
   uint8_t  pad5[0x228 - 0x220];
   uint32_t cmd_line_ptr;                // 228
-  uint8_t  pad6[0x2d0 - 0x22c];
+  uint32_t ramdisk_max;                 // 22c
+  uint32_t kernel_alignment;            // 230
+  uint8_t  relocatable_kernel;          // 234
+  uint8_t  min_alignment;               // 235
+  uint8_t  pad6[0x2d0 - 0x236];
   struct   linux_kernel_e820entry e820_entries[E820_ENTRY_MAX]; // 2d0 - cd0
 } __attribute__ ((packed));
 
diff --git a/utility/vbutil_kernel.c b/utility/vbutil_kernel.c
index 615ce30..820b3af 100644
--- a/utility/vbutil_kernel.c
+++ b/utility/vbutil_kernel.c
@@ -271,8 +271,7 @@
   uint64_t kernel_size;
   uint64_t kernel32_start = 0;
   uint64_t kernel32_size = 0;
-  struct linux_kernel_header* lh = 0;
-  struct linux_kernel_params* params = 0;
+  struct linux_kernel_params *params = NULL, *lh = NULL;
 
   /* Read the kernel */
   Debug("Reading %s\n", vmlinuz_file);
@@ -298,7 +297,7 @@
 
   /* The first part of the x86 vmlinuz is a header, followed by a real-mode
    * boot stub.  We only want the 32-bit part. */
-  lh = (struct linux_kernel_header *)kernel_buf;
+  lh = (struct linux_kernel_params *)kernel_buf;
   kernel32_start = (lh->setup_sects + 1) << 9;
   if (kernel32_start >= kernel_size)
     Fatal("Malformed kernel\n");
@@ -318,7 +317,8 @@
    * tweak a few fields for our purposes */
   params = (struct linux_kernel_params *)(g_param_data);
   Memcpy(&(params->setup_sects), &(lh->setup_sects),
-         sizeof(*lh) - offsetof(struct linux_kernel_header, setup_sects));
+         offsetof(struct linux_kernel_params, e820_entries)
+         - offsetof(struct linux_kernel_params, setup_sects));
   params->boot_flag = 0;
   params->ramdisk_image = 0; /* we don't support initrd */
   params->ramdisk_size = 0;
@@ -329,6 +329,9 @@
     roundup(kernel32_size, CROS_ALIGN) +
     find_cmdline_start((char *)g_config_data, g_config_size);
   Debug(" cmdline_addr=0x%x\n", params->cmd_line_ptr);
+  Debug(" version=0x%x\n", params->version);
+  Debug(" kernel_alignment=0x%x\n", params->kernel_alignment);
+  Debug(" relocatable_kernel=0x%x\n", params->relocatable_kernel);
   /* A fake e820 memory map with 2 entries */
   params->n_e820_entry = 2;
   params->e820_entries[0].start_addr = 0x00000000;