From dab6a0f0c31d2805fff1f58e5c37e21260602b6b Mon Sep 17 00:00:00 2001 From: Michael Marineau Date: Wed, 19 Oct 2016 14:12:55 -0700 Subject: [PATCH 1/2] loader: validate cmdline string length before appending verity arg --- grub-core/loader/i386/efi/linux.c | 2 +- grub-core/loader/i386/linux.c | 2 +- grub-core/loader/i386/verity-hash.h | 14 ++++++++++---- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c index e572d2351..d195c59bf 100644 --- a/grub-core/loader/i386/efi/linux.c +++ b/grub-core/loader/i386/efi/linux.c @@ -286,7 +286,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), linux_cmdline + sizeof (LINUX_IMAGE) - 1, lh.cmdline_size - (sizeof (LINUX_IMAGE) - 1)); - grub_pass_verity_hash(&lh, linux_cmdline); + grub_pass_verity_hash(&lh, linux_cmdline, lh.cmdline_size); lh.cmd_line_ptr = (grub_uint32_t)(grub_uint64_t)linux_cmdline; handover_offset = lh.handover_offset; diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index 7f92c363a..84ec8e241 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -1029,7 +1029,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), maximal_cmdline_size - (sizeof (LINUX_IMAGE) - 1)); - grub_pass_verity_hash(&lh, linux_cmdline); + grub_pass_verity_hash(&lh, linux_cmdline, maximal_cmdline_size); len = prot_file_size; grub_memcpy (prot_mode_mem, kernel + kernel_offset, len); kernel_offset += len; diff --git a/grub-core/loader/i386/verity-hash.h b/grub-core/loader/i386/verity-hash.h index 4027be6aa..afbfd14d6 100644 --- a/grub-core/loader/i386/verity-hash.h +++ b/grub-core/loader/i386/verity-hash.h @@ -1,9 +1,11 @@ #define VERITY_ARG " verity.usrhash=" +#define VERITY_ARG_LENGTH (sizeof (VERITY_ARG) - 1) #define VERITY_HASH_OFFSET 0x40 #define VERITY_HASH_LENGTH 64 static inline void grub_pass_verity_hash(struct linux_kernel_header *lh, - char *cmdline) + char *cmdline, + grub_size_t cmdline_max_len) { char *buf = (char *)lh; grub_size_t cmdline_len; @@ -16,10 +18,14 @@ static inline void grub_pass_verity_hash(struct linux_kernel_header *lh, return; } - grub_memcpy (cmdline + grub_strlen(cmdline), VERITY_ARG, - sizeof (VERITY_ARG)); cmdline_len = grub_strlen(cmdline); + if (cmdline_len + VERITY_ARG_LENGTH + VERITY_HASH_LENGTH > cmdline_max_len) + return; + + grub_memcpy (cmdline + cmdline_len, VERITY_ARG, VERITY_ARG_LENGTH); + cmdline_len += VERITY_ARG_LENGTH; grub_memcpy (cmdline + cmdline_len, buf + VERITY_HASH_OFFSET, VERITY_HASH_LENGTH); - cmdline[cmdline_len + VERITY_HASH_LENGTH] = '\0'; + cmdline_len += VERITY_HASH_LENGTH; + cmdline[cmdline_len] = '\0'; } From bcd7fb9fd29561db1963a739a222a76f8b0922aa Mon Sep 17 00:00:00 2001 From: Michael Marineau Date: Wed, 19 Oct 2016 14:48:50 -0700 Subject: [PATCH 2/2] loader: add support for passing verity hash to xen kernels This only supports DomU Linux bzImage, ignoring bare ELF images and Dom0 Xen+Linux but those cases are not applicable to us on CoreOS. --- grub-core/loader/i386/xen.c | 4 +++- grub-core/loader/i386/xen_file.c | 13 +++++++++++++ include/grub/xen_file.h | 3 +++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c index c4d9689f7..f460c9a16 100644 --- a/grub-core/loader/i386/xen.c +++ b/grub-core/loader/i386/xen.c @@ -416,7 +416,9 @@ grub_cmd_xen (grub_command_t cmd __attribute__ ((unused)), if (!file) return grub_errno; - elf = grub_xen_file (file); + elf = grub_xen_file_and_cmdline (file, + (char *) next_start.cmd_line, + sizeof (next_start.cmd_line) - 1); if (!elf) goto fail; diff --git a/grub-core/loader/i386/xen_file.c b/grub-core/loader/i386/xen_file.c index 583621890..a5cd714fa 100644 --- a/grub-core/loader/i386/xen_file.c +++ b/grub-core/loader/i386/xen_file.c @@ -20,8 +20,18 @@ #include #include +#include "verity-hash.h" + grub_elf_t grub_xen_file (grub_file_t file) +{ + return grub_xen_file_and_cmdline (file, NULL, 0); +} + +grub_elf_t +grub_xen_file_and_cmdline (grub_file_t file, + char *cmdline, + grub_size_t cmdline_max_len) { grub_elf_t elf; struct linux_kernel_header lh; @@ -57,6 +67,9 @@ grub_xen_file (grub_file_t file) + lh.payload_offset, (unsigned long long) lh.payload_length - 4); + if (cmdline) + grub_pass_verity_hash (&lh, cmdline, cmdline_max_len); + off_file = grub_file_offset_open (file, (lh.setup_sects + 1) * 512 + lh.payload_offset, lh.payload_length - 4); diff --git a/include/grub/xen_file.h b/include/grub/xen_file.h index 4b2ccba78..45a45a55b 100644 --- a/include/grub/xen_file.h +++ b/include/grub/xen_file.h @@ -24,6 +24,9 @@ #include grub_elf_t grub_xen_file (grub_file_t file); +grub_elf_t grub_xen_file_and_cmdline (grub_file_t file, + char *cmdline, + grub_size_t cmdline_max_len); struct grub_xen_file_info {