diff --git a/grub-core/commands/verifiers.c b/grub-core/commands/verifiers.c index fde88318d..59ea418a2 100644 --- a/grub-core/commands/verifiers.c +++ b/grub-core/commands/verifiers.c @@ -186,6 +186,20 @@ grub_verifiers_open (grub_file_t io, enum grub_file_type type) return NULL; } +grub_err_t +grub_verify_string (char *str, enum grub_verify_string_type type) +{ + struct grub_file_verifier *ver; + FOR_LIST_ELEMENTS(ver, grub_file_verifiers) + { + grub_err_t err; + err = ver->verify_string ? ver->verify_string (str, type) : GRUB_ERR_NONE; + if (err) + return err; + } + return GRUB_ERR_NONE; +} + GRUB_MOD_INIT(verifiers) { grub_file_filter_register (GRUB_FILE_FILTER_VERIFY, grub_verifiers_open); diff --git a/grub-core/commands/verify.c b/grub-core/commands/verify.c index 0819da327..1357857c5 100644 --- a/grub-core/commands/verify.c +++ b/grub-core/commands/verify.c @@ -58,7 +58,7 @@ struct grub_fs pseudo_fs = { .name = "pseudo", .read = pseudo_read -}; + }; static grub_err_t read_packet_header (grub_file_t sig, grub_uint8_t *out_type, grub_size_t *len) @@ -995,21 +995,6 @@ grub_env_write_sec (struct grub_env_var *var __attribute__ ((unused)), return grub_strdup (sec ? "enforce" : "no"); } -static grub_ssize_t -pseudo_read (struct grub_file *file, char *buf, grub_size_t len) -{ - grub_memcpy (buf, (grub_uint8_t *) file->data + file->offset, len); - return len; -} - - -/* Filesystem descriptor. */ -struct grub_fs pseudo_fs = - { - .name = "pseudo", - .read = pseudo_read - }; - struct grub_file_verifier grub_pubkey_verifier = { .name = "pgp", @@ -1019,7 +1004,6 @@ struct grub_file_verifier grub_pubkey_verifier = .close = grub_pubkey_close, }; -verifiers: Framework core static grub_extcmd_t cmd, cmd_trust; static grub_command_t cmd_trust_var, cmd_distrust, cmd_list; diff --git a/grub-core/lib/cmdline.c b/grub-core/lib/cmdline.c index f090ea20d..b37155053 100644 --- a/grub-core/lib/cmdline.c +++ b/grub-core/lib/cmdline.c @@ -63,12 +63,13 @@ unsigned int grub_loader_cmdline_size (int argc, char *argv[]) return size; } -int grub_create_loader_cmdline (int argc, char *argv[], char *buf, - grub_size_t size) +grub_err_t +grub_create_loader_cmdline (int argc, char *argv[], char *buf, + grub_size_t size, enum grub_verify_string_type type) { int i, space; unsigned int arg_size; - char *c, *orig = buf; + char *c, *orig_buf = buf; for (i = 0; i < argc; i++) { @@ -105,9 +106,9 @@ int grub_create_loader_cmdline (int argc, char *argv[], char *buf, *buf = 0; - grub_tpm_measure ((void *)orig, grub_strlen (orig), GRUB_ASCII_PCR, - "grub_kernel_cmdline", orig); + grub_tpm_measure ((void *)orig_buf, grub_strlen (orig_buf), GRUB_ASCII_PCR, + "grub_kernel_cmdline", orig_buf); grub_print_error(); - return i; + return grub_verify_string (orig_buf, type); } diff --git a/grub-core/loader/arm/linux.c b/grub-core/loader/arm/linux.c index b4f609d2d..80293fb1f 100644 --- a/grub-core/loader/arm/linux.c +++ b/grub-core/loader/arm/linux.c @@ -28,6 +28,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -383,8 +384,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), /* Create kernel command line. */ grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE)); - grub_create_loader_cmdline (argc, argv, - linux_args + sizeof (LINUX_IMAGE) - 1, size); + err = grub_create_loader_cmdline (argc, argv, + linux_args + sizeof (LINUX_IMAGE) - 1, size, + GRUB_VERIFY_KERNEL_CMDLINE); + if (err) + goto fail; return GRUB_ERR_NONE; diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c index db82a6c7a..8588a0378 100644 --- a/grub-core/loader/arm64/linux.c +++ b/grub-core/loader/arm64/linux.c @@ -32,6 +32,7 @@ #include #include #include +#include #include @@ -342,9 +343,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), goto fail; } grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE)); - grub_create_loader_cmdline (argc, argv, - linux_args + sizeof (LINUX_IMAGE) - 1, - cmdline_size); + err = grub_create_loader_cmdline (argc, argv, + linux_args + sizeof (LINUX_IMAGE) - 1, + cmdline_size, + GRUB_VERIFY_KERNEL_CMDLINE); + if (err) + goto fail; if (grub_errno == GRUB_ERR_NONE) { diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c index d34da14d9..c26edb4a9 100644 --- a/grub-core/loader/i386/bsd.c +++ b/grub-core/loader/i386/bsd.c @@ -35,6 +35,7 @@ #include #include #include +#include #ifdef GRUB_MACHINE_PCBIOS #include #endif @@ -416,6 +417,8 @@ grub_freebsd_add_meta_module (const char *filename, const char *type, grub_addr_t addr, grub_uint32_t size) { const char *name; + grub_err_t err; + name = grub_strrchr (filename, '/'); if (name) name++; @@ -469,6 +472,9 @@ grub_freebsd_add_meta_module (const char *filename, const char *type, *(p++) = ' '; } *p = 0; + err = grub_verify_string (cmdline, GRUB_VERIFY_MODULE_CMDLINE); + if (err) + return err; } } diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index c608b7b4f..c1c0bf577 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -984,11 +984,17 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), if (!linux_cmdline) goto fail; grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE)); - grub_create_loader_cmdline (argc, argv, - linux_cmdline - + sizeof (LINUX_IMAGE) - 1, - maximal_cmdline_size - - (sizeof (LINUX_IMAGE) - 1)); + { + grub_err_t err; + err = grub_create_loader_cmdline (argc, argv, + linux_cmdline + + sizeof (LINUX_IMAGE) - 1, + maximal_cmdline_size + - (sizeof (LINUX_IMAGE) - 1), + GRUB_VERIFY_KERNEL_CMDLINE); + if (err) + goto fail; + } grub_pass_verity_hash(&lh, linux_cmdline, maximal_cmdline_size); len = prot_file_size; diff --git a/grub-core/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c index ca85358f7..ee74a4b46 100644 --- a/grub-core/loader/i386/multiboot_mbi.c +++ b/grub-core/loader/i386/multiboot_mbi.c @@ -677,10 +677,8 @@ grub_multiboot_init_mbi (int argc, char *argv[]) return grub_errno; cmdline_size = len; - grub_create_loader_cmdline (argc, argv, cmdline, - cmdline_size); - - return GRUB_ERR_NONE; + return grub_create_loader_cmdline (argc, argv, cmdline, + cmdline_size, GRUB_VERIFY_KERNEL_CMDLINE); } grub_err_t @@ -689,6 +687,7 @@ grub_multiboot_add_module (grub_addr_t start, grub_size_t size, { struct module *newmod; grub_size_t len = 0; + grub_err_t err; newmod = grub_malloc (sizeof (*newmod)); if (!newmod) @@ -708,8 +707,13 @@ grub_multiboot_add_module (grub_addr_t start, grub_size_t size, newmod->cmdline_size = len; total_modcmd += ALIGN_UP (len, 4); - grub_create_loader_cmdline (argc, argv, newmod->cmdline, - newmod->cmdline_size); + err = grub_create_loader_cmdline (argc, argv, newmod->cmdline, + newmod->cmdline_size, GRUB_VERIFY_MODULE_CMDLINE); + if (err) + { + grub_free (newmod); + return grub_errno; + } if (modules_last) modules_last->next = newmod; diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c index 63049a32c..7493e7341 100644 --- a/grub-core/loader/i386/pc/linux.c +++ b/grub-core/loader/i386/pc/linux.c @@ -346,11 +346,14 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), /* Create kernel command line. */ grub_memcpy ((char *)grub_linux_real_chunk + GRUB_LINUX_CL_OFFSET, LINUX_IMAGE, sizeof (LINUX_IMAGE)); - grub_create_loader_cmdline (argc, argv, - (char *)grub_linux_real_chunk - + GRUB_LINUX_CL_OFFSET + sizeof (LINUX_IMAGE) - 1, - maximal_cmdline_size - - (sizeof (LINUX_IMAGE) - 1)); + err = grub_create_loader_cmdline (argc, argv, + (char *)grub_linux_real_chunk + + GRUB_LINUX_CL_OFFSET + sizeof (LINUX_IMAGE) - 1, + maximal_cmdline_size + - (sizeof (LINUX_IMAGE) - 1), + GRUB_VERIFY_KERNEL_CMDLINE); + if (err) + goto fail; if (grub_linux_is_bzimage) grub_linux_prot_target = GRUB_LINUX_BZIMAGE_ADDR; diff --git a/grub-core/loader/i386/pc/plan9.c b/grub-core/loader/i386/pc/plan9.c index 0351090da..37550155d 100644 --- a/grub-core/loader/i386/pc/plan9.c +++ b/grub-core/loader/i386/pc/plan9.c @@ -33,6 +33,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -505,6 +506,7 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[]) configptr = grub_stpcpy (configptr, "bootfile="); configptr = grub_stpcpy (configptr, bootpath); *configptr++ = '\n'; + char *cmdline = configptr; { int i; for (i = 1; i < argc; i++) @@ -513,6 +515,15 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[]) *configptr++ = '\n'; } } + + { + grub_err_t err; + *configptr = '\0'; + err = grub_verify_string (cmdline, GRUB_VERIFY_KERNEL_CMDLINE); + if (err) + goto fail; + } + configptr = grub_stpcpy (configptr, fill_ctx.pmap); { diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c index 9cd806afc..4786ca6a5 100644 --- a/grub-core/loader/i386/xen.c +++ b/grub-core/loader/i386/xen.c @@ -40,6 +40,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -647,6 +648,9 @@ grub_cmd_xen (grub_command_t cmd __attribute__ ((unused)), grub_create_loader_cmdline (argc - 1, argv + 1, (char *) xen_state.next_start.cmd_line, sizeof (xen_state.next_start.cmd_line) - 1); + err = grub_verify_string (xen_state.next_start.cmd_line, GRUB_VERIFY_MODULE_CMDLINE); + if (err) + return err; file = grub_file_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL); if (!file) @@ -910,6 +914,9 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)), grub_create_loader_cmdline (argc - 1, argv + 1, get_virtual_current_address (ch), cmdline_len); + err = grub_verify_string (get_virtual_current_address (ch), GRUB_VERIFY_MODULE_CMDLINE); + if (err) + goto fail; xen_state.module_info_page[xen_state.n_modules].cmdline = xen_state.max_addr - xen_state.modules_target_start; diff --git a/grub-core/loader/ia64/efi/linux.c b/grub-core/loader/ia64/efi/linux.c index 96fce713a..6477d70f0 100644 --- a/grub-core/loader/ia64/efi/linux.c +++ b/grub-core/loader/ia64/efi/linux.c @@ -33,6 +33,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -501,6 +502,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), p = grub_stpcpy (p, argv[i]); } cmdline[10] = '='; + + *p = '\0'; + + err = grub_verify_string (cmdline, GRUB_VERIFY_KERNEL_CMDLINE); + if (err) + goto fail; boot_param->command_line = (grub_uint64_t) cmdline; boot_param->efi_systab = (grub_uint64_t) grub_efi_system_table; diff --git a/grub-core/loader/mips/linux.c b/grub-core/loader/mips/linux.c index 7b28ba731..e256c440f 100644 --- a/grub-core/loader/mips/linux.c +++ b/grub-core/loader/mips/linux.c @@ -327,6 +327,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), linux_argv++; linux_args += ALIGN_UP (sizeof ("a0"), 4); + char *params = linux_args; + #ifdef GRUB_MACHINE_MIPS_LOONGSON { unsigned mtype = grub_arch_machine; @@ -352,6 +354,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), linux_args += ALIGN_UP (grub_strlen (argv[i]) + 1, 4); } + *linux_args = '\0'; + + err = grub_verify_string (params, GRUB_VERIFY_KERNEL_CMDLINE); + if (err) + return err; + /* Reserve space for rd arguments. */ rd_addr_arg_off = (grub_uint8_t *) linux_args - (grub_uint8_t *) playground; linux_args += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4); diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c index 55a003a95..1a48305fa 100644 --- a/grub-core/loader/multiboot_mbi2.c +++ b/grub-core/loader/multiboot_mbi2.c @@ -1042,10 +1042,8 @@ grub_multiboot2_init_mbi (int argc, char *argv[]) return grub_errno; cmdline_size = len; - grub_create_loader_cmdline (argc, argv, cmdline, - cmdline_size); - - return GRUB_ERR_NONE; + return grub_create_loader_cmdline (argc, argv, cmdline, cmdline_size, + GRUB_VERIFY_KERNEL_CMDLINE); } grub_err_t @@ -1054,6 +1052,7 @@ grub_multiboot2_add_module (grub_addr_t start, grub_size_t size, { struct module *newmod; grub_size_t len = 0; + grub_err_t err; newmod = grub_malloc (sizeof (*newmod)); if (!newmod) @@ -1072,8 +1071,10 @@ grub_multiboot2_add_module (grub_addr_t start, grub_size_t size, newmod->cmdline_size = len; total_modcmd += ALIGN_UP (len, MULTIBOOT_TAG_ALIGN); - grub_create_loader_cmdline (argc, argv, newmod->cmdline, - newmod->cmdline_size); + err = grub_create_loader_cmdline (argc, argv, newmod->cmdline, + newmod->cmdline_size, GRUB_VERIFY_MODULE_CMDLINE); + if (err) + return err; if (modules_last) modules_last->next = newmod; diff --git a/grub-core/loader/powerpc/ieee1275/linux.c b/grub-core/loader/powerpc/ieee1275/linux.c index 6e814649f..c114e7df4 100644 --- a/grub-core/loader/powerpc/ieee1275/linux.c +++ b/grub-core/loader/powerpc/ieee1275/linux.c @@ -302,8 +302,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), /* Create kernel command line. */ grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE)); - grub_create_loader_cmdline (argc, argv, linux_args + sizeof (LINUX_IMAGE) - 1, - size); + if (grub_create_loader_cmdline (argc, argv, linux_args + sizeof (LINUX_IMAGE) - 1, + size)) + goto out; out: diff --git a/grub-core/loader/sparc64/ieee1275/linux.c b/grub-core/loader/sparc64/ieee1275/linux.c index 67ef04883..abe46faa0 100644 --- a/grub-core/loader/sparc64/ieee1275/linux.c +++ b/grub-core/loader/sparc64/ieee1275/linux.c @@ -340,8 +340,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), /* Create kernel command line. */ grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE)); - grub_create_loader_cmdline (argc, argv, linux_args + sizeof (LINUX_IMAGE) - 1, - size); + if (grub_create_loader_cmdline (argc, argv, linux_args + sizeof (LINUX_IMAGE) - 1, + size, GRUB_VERIFY_KERNEL_CMDLINE)) + goto out; out: if (elf) diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c index 84c8b939c..ff66be4bf 100644 --- a/grub-core/loader/xnu.c +++ b/grub-core/loader/xnu.c @@ -33,6 +33,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -425,6 +426,10 @@ grub_cmd_xnu_kernel (grub_command_t cmd __attribute__ ((unused)), if (ptr != grub_xnu_cmdline) *(ptr - 1) = 0; + err = grub_verify_string (grub_xnu_cmdline, GRUB_VERIFY_KERNEL_CMDLINE); + if (err) + return err; + #if defined (__i386) && !defined (GRUB_MACHINE_EFI) err = grub_efiemu_autocore (); if (err) @@ -534,6 +539,10 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)), if (ptr != grub_xnu_cmdline) *(ptr - 1) = 0; + err = grub_verify_string (grub_xnu_cmdline, GRUB_VERIFY_KERNEL_CMDLINE); + if (err) + return err; + #if defined (__i386) && !defined (GRUB_MACHINE_EFI) err = grub_efiemu_autocore (); if (err) diff --git a/include/grub/lib/cmdline.h b/include/grub/lib/cmdline.h index 1fe8d0179..cdca09b7a 100644 --- a/include/grub/lib/cmdline.h +++ b/include/grub/lib/cmdline.h @@ -21,11 +21,12 @@ #define GRUB_CMDLINE_HEADER 1 #include +#include #define LINUX_IMAGE "BOOT_IMAGE=" unsigned int grub_loader_cmdline_size (int argc, char *argv[]); -int grub_create_loader_cmdline (int argc, char *argv[], char *buf, - grub_size_t size); +grub_err_t grub_create_loader_cmdline (int argc, char *argv[], char *buf, + grub_size_t size, enum grub_verify_string_type type); #endif /* ! GRUB_CMDLINE_HEADER */ diff --git a/include/grub/verify.h b/include/grub/verify.h index 298120f57..9f892d8fe 100644 --- a/include/grub/verify.h +++ b/include/grub/verify.h @@ -25,6 +25,12 @@ enum grub_verify_flags GRUB_VERIFY_FLAGS_SINGLE_CHUNK = 2 }; +enum grub_verify_string_type + { + GRUB_VERIFY_KERNEL_CMDLINE, + GRUB_VERIFY_MODULE_CMDLINE, + }; + struct grub_file_verifier { struct grub_file_verifier *next; @@ -48,6 +54,8 @@ struct grub_file_verifier grub_err_t (*fini) (void *context); void (*close) (void *context); + + grub_err_t (*verify_string) (char *str, enum grub_verify_string_type type); }; extern struct grub_file_verifier *grub_file_verifiers; @@ -63,3 +71,6 @@ grub_verifier_unregister (struct grub_file_verifier *ver) { grub_list_remove (GRUB_AS_LIST (ver)); } + +grub_err_t +grub_verify_string (char *str, enum grub_verify_string_type type);