verifiers: Add possibility to verify kernel and modules command lines

Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Ross Philipson <ross.philipson@oracle.com>
This commit is contained in:
Vladimir Serbinenko 2017-02-07 02:10:14 +01:00 committed by Vincent Batts
parent 03a713b7ab
commit 0f20a51812
19 changed files with 139 additions and 56 deletions

View file

@ -186,6 +186,20 @@ grub_verifiers_open (grub_file_t io, enum grub_file_type type)
return NULL; 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_MOD_INIT(verifiers)
{ {
grub_file_filter_register (GRUB_FILE_FILTER_VERIFY, grub_verifiers_open); grub_file_filter_register (GRUB_FILE_FILTER_VERIFY, grub_verifiers_open);

View file

@ -995,21 +995,6 @@ grub_env_write_sec (struct grub_env_var *var __attribute__ ((unused)),
return grub_strdup (sec ? "enforce" : "no"); 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 = struct grub_file_verifier grub_pubkey_verifier =
{ {
.name = "pgp", .name = "pgp",
@ -1019,7 +1004,6 @@ struct grub_file_verifier grub_pubkey_verifier =
.close = grub_pubkey_close, .close = grub_pubkey_close,
}; };
verifiers: Framework core
static grub_extcmd_t cmd, cmd_trust; static grub_extcmd_t cmd, cmd_trust;
static grub_command_t cmd_trust_var, cmd_distrust, cmd_list; static grub_command_t cmd_trust_var, cmd_distrust, cmd_list;

View file

@ -63,12 +63,13 @@ unsigned int grub_loader_cmdline_size (int argc, char *argv[])
return size; return size;
} }
int grub_create_loader_cmdline (int argc, char *argv[], char *buf, grub_err_t
grub_size_t size) grub_create_loader_cmdline (int argc, char *argv[], char *buf,
grub_size_t size, enum grub_verify_string_type type)
{ {
int i, space; int i, space;
unsigned int arg_size; unsigned int arg_size;
char *c, *orig = buf; char *c, *orig_buf = buf;
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++)
{ {
@ -105,9 +106,9 @@ int grub_create_loader_cmdline (int argc, char *argv[], char *buf,
*buf = 0; *buf = 0;
grub_tpm_measure ((void *)orig, grub_strlen (orig), GRUB_ASCII_PCR, grub_tpm_measure ((void *)orig_buf, grub_strlen (orig_buf), GRUB_ASCII_PCR,
"grub_kernel_cmdline", orig); "grub_kernel_cmdline", orig_buf);
grub_print_error(); grub_print_error();
return i; return grub_verify_string (orig_buf, type);
} }

View file

@ -28,6 +28,7 @@
#include <grub/cpu/linux.h> #include <grub/cpu/linux.h>
#include <grub/lib/cmdline.h> #include <grub/lib/cmdline.h>
#include <grub/linux.h> #include <grub/linux.h>
#include <grub/verify.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
@ -383,8 +384,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
/* Create kernel command line. */ /* Create kernel command line. */
grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE)); grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE));
grub_create_loader_cmdline (argc, argv, err = grub_create_loader_cmdline (argc, argv,
linux_args + sizeof (LINUX_IMAGE) - 1, size); linux_args + sizeof (LINUX_IMAGE) - 1, size,
GRUB_VERIFY_KERNEL_CMDLINE);
if (err)
goto fail;
return GRUB_ERR_NONE; return GRUB_ERR_NONE;

View file

@ -32,6 +32,7 @@
#include <grub/efi/pe32.h> #include <grub/efi/pe32.h>
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/lib/cmdline.h> #include <grub/lib/cmdline.h>
#include <grub/verify.h>
#include <grub/verity-hash.h> #include <grub/verity-hash.h>
@ -342,9 +343,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail; goto fail;
} }
grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE)); grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE));
grub_create_loader_cmdline (argc, argv, err = grub_create_loader_cmdline (argc, argv,
linux_args + sizeof (LINUX_IMAGE) - 1, linux_args + sizeof (LINUX_IMAGE) - 1,
cmdline_size); cmdline_size,
GRUB_VERIFY_KERNEL_CMDLINE);
if (err)
goto fail;
if (grub_errno == GRUB_ERR_NONE) if (grub_errno == GRUB_ERR_NONE)
{ {

View file

@ -35,6 +35,7 @@
#include <grub/ns8250.h> #include <grub/ns8250.h>
#include <grub/bsdlabel.h> #include <grub/bsdlabel.h>
#include <grub/crypto.h> #include <grub/crypto.h>
#include <grub/verify.h>
#ifdef GRUB_MACHINE_PCBIOS #ifdef GRUB_MACHINE_PCBIOS
#include <grub/machine/int.h> #include <grub/machine/int.h>
#endif #endif
@ -416,6 +417,8 @@ grub_freebsd_add_meta_module (const char *filename, const char *type,
grub_addr_t addr, grub_uint32_t size) grub_addr_t addr, grub_uint32_t size)
{ {
const char *name; const char *name;
grub_err_t err;
name = grub_strrchr (filename, '/'); name = grub_strrchr (filename, '/');
if (name) if (name)
name++; name++;
@ -469,6 +472,9 @@ grub_freebsd_add_meta_module (const char *filename, const char *type,
*(p++) = ' '; *(p++) = ' ';
} }
*p = 0; *p = 0;
err = grub_verify_string (cmdline, GRUB_VERIFY_MODULE_CMDLINE);
if (err)
return err;
} }
} }

View file

@ -984,11 +984,17 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
if (!linux_cmdline) if (!linux_cmdline)
goto fail; goto fail;
grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE)); grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
grub_create_loader_cmdline (argc, argv, {
grub_err_t err;
err = grub_create_loader_cmdline (argc, argv,
linux_cmdline linux_cmdline
+ sizeof (LINUX_IMAGE) - 1, + sizeof (LINUX_IMAGE) - 1,
maximal_cmdline_size maximal_cmdline_size
- (sizeof (LINUX_IMAGE) - 1)); - (sizeof (LINUX_IMAGE) - 1),
GRUB_VERIFY_KERNEL_CMDLINE);
if (err)
goto fail;
}
grub_pass_verity_hash(&lh, linux_cmdline, maximal_cmdline_size); grub_pass_verity_hash(&lh, linux_cmdline, maximal_cmdline_size);
len = prot_file_size; len = prot_file_size;

View file

@ -677,10 +677,8 @@ grub_multiboot_init_mbi (int argc, char *argv[])
return grub_errno; return grub_errno;
cmdline_size = len; cmdline_size = len;
grub_create_loader_cmdline (argc, argv, cmdline, return grub_create_loader_cmdline (argc, argv, cmdline,
cmdline_size); cmdline_size, GRUB_VERIFY_KERNEL_CMDLINE);
return GRUB_ERR_NONE;
} }
grub_err_t grub_err_t
@ -689,6 +687,7 @@ grub_multiboot_add_module (grub_addr_t start, grub_size_t size,
{ {
struct module *newmod; struct module *newmod;
grub_size_t len = 0; grub_size_t len = 0;
grub_err_t err;
newmod = grub_malloc (sizeof (*newmod)); newmod = grub_malloc (sizeof (*newmod));
if (!newmod) if (!newmod)
@ -708,8 +707,13 @@ grub_multiboot_add_module (grub_addr_t start, grub_size_t size,
newmod->cmdline_size = len; newmod->cmdline_size = len;
total_modcmd += ALIGN_UP (len, 4); total_modcmd += ALIGN_UP (len, 4);
grub_create_loader_cmdline (argc, argv, newmod->cmdline, err = grub_create_loader_cmdline (argc, argv, newmod->cmdline,
newmod->cmdline_size); newmod->cmdline_size, GRUB_VERIFY_MODULE_CMDLINE);
if (err)
{
grub_free (newmod);
return grub_errno;
}
if (modules_last) if (modules_last)
modules_last->next = newmod; modules_last->next = newmod;

View file

@ -346,11 +346,14 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
/* Create kernel command line. */ /* Create kernel command line. */
grub_memcpy ((char *)grub_linux_real_chunk + GRUB_LINUX_CL_OFFSET, grub_memcpy ((char *)grub_linux_real_chunk + GRUB_LINUX_CL_OFFSET,
LINUX_IMAGE, sizeof (LINUX_IMAGE)); LINUX_IMAGE, sizeof (LINUX_IMAGE));
grub_create_loader_cmdline (argc, argv, err = grub_create_loader_cmdline (argc, argv,
(char *)grub_linux_real_chunk (char *)grub_linux_real_chunk
+ GRUB_LINUX_CL_OFFSET + sizeof (LINUX_IMAGE) - 1, + GRUB_LINUX_CL_OFFSET + sizeof (LINUX_IMAGE) - 1,
maximal_cmdline_size maximal_cmdline_size
- (sizeof (LINUX_IMAGE) - 1)); - (sizeof (LINUX_IMAGE) - 1),
GRUB_VERIFY_KERNEL_CMDLINE);
if (err)
goto fail;
if (grub_linux_is_bzimage) if (grub_linux_is_bzimage)
grub_linux_prot_target = GRUB_LINUX_BZIMAGE_ADDR; grub_linux_prot_target = GRUB_LINUX_BZIMAGE_ADDR;

View file

@ -33,6 +33,7 @@
#include <grub/mm.h> #include <grub/mm.h>
#include <grub/cpu/relocator.h> #include <grub/cpu/relocator.h>
#include <grub/extcmd.h> #include <grub/extcmd.h>
#include <grub/verify.h>
GRUB_MOD_LICENSE ("GPLv3+"); 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, "bootfile=");
configptr = grub_stpcpy (configptr, bootpath); configptr = grub_stpcpy (configptr, bootpath);
*configptr++ = '\n'; *configptr++ = '\n';
char *cmdline = configptr;
{ {
int i; int i;
for (i = 1; i < argc; 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'; *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); configptr = grub_stpcpy (configptr, fill_ctx.pmap);
{ {

View file

@ -40,6 +40,7 @@
#include <grub/xen_file.h> #include <grub/xen_file.h>
#include <grub/linux.h> #include <grub/linux.h>
#include <grub/i386/memory.h> #include <grub/i386/memory.h>
#include <grub/verify.h>
GRUB_MOD_LICENSE ("GPLv3+"); 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, grub_create_loader_cmdline (argc - 1, argv + 1,
(char *) xen_state.next_start.cmd_line, (char *) xen_state.next_start.cmd_line,
sizeof (xen_state.next_start.cmd_line) - 1); 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); file = grub_file_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL);
if (!file) if (!file)
@ -910,6 +914,9 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
grub_create_loader_cmdline (argc - 1, argv + 1, grub_create_loader_cmdline (argc - 1, argv + 1,
get_virtual_current_address (ch), cmdline_len); 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.module_info_page[xen_state.n_modules].cmdline =
xen_state.max_addr - xen_state.modules_target_start; xen_state.max_addr - xen_state.modules_target_start;

View file

@ -33,6 +33,7 @@
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/env.h> #include <grub/env.h>
#include <grub/linux.h> #include <grub/linux.h>
#include <grub/verify.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
@ -502,6 +503,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
} }
cmdline[10] = '='; 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->command_line = (grub_uint64_t) cmdline;
boot_param->efi_systab = (grub_uint64_t) grub_efi_system_table; boot_param->efi_systab = (grub_uint64_t) grub_efi_system_table;

View file

@ -327,6 +327,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
linux_argv++; linux_argv++;
linux_args += ALIGN_UP (sizeof ("a0"), 4); linux_args += ALIGN_UP (sizeof ("a0"), 4);
char *params = linux_args;
#ifdef GRUB_MACHINE_MIPS_LOONGSON #ifdef GRUB_MACHINE_MIPS_LOONGSON
{ {
unsigned mtype = grub_arch_machine; 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 += 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. */ /* Reserve space for rd arguments. */
rd_addr_arg_off = (grub_uint8_t *) linux_args - (grub_uint8_t *) playground; rd_addr_arg_off = (grub_uint8_t *) linux_args - (grub_uint8_t *) playground;
linux_args += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4); linux_args += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4);

View file

@ -1042,10 +1042,8 @@ grub_multiboot2_init_mbi (int argc, char *argv[])
return grub_errno; return grub_errno;
cmdline_size = len; cmdline_size = len;
grub_create_loader_cmdline (argc, argv, cmdline, return grub_create_loader_cmdline (argc, argv, cmdline, cmdline_size,
cmdline_size); GRUB_VERIFY_KERNEL_CMDLINE);
return GRUB_ERR_NONE;
} }
grub_err_t grub_err_t
@ -1054,6 +1052,7 @@ grub_multiboot2_add_module (grub_addr_t start, grub_size_t size,
{ {
struct module *newmod; struct module *newmod;
grub_size_t len = 0; grub_size_t len = 0;
grub_err_t err;
newmod = grub_malloc (sizeof (*newmod)); newmod = grub_malloc (sizeof (*newmod));
if (!newmod) if (!newmod)
@ -1072,8 +1071,10 @@ grub_multiboot2_add_module (grub_addr_t start, grub_size_t size,
newmod->cmdline_size = len; newmod->cmdline_size = len;
total_modcmd += ALIGN_UP (len, MULTIBOOT_TAG_ALIGN); total_modcmd += ALIGN_UP (len, MULTIBOOT_TAG_ALIGN);
grub_create_loader_cmdline (argc, argv, newmod->cmdline, err = grub_create_loader_cmdline (argc, argv, newmod->cmdline,
newmod->cmdline_size); newmod->cmdline_size, GRUB_VERIFY_MODULE_CMDLINE);
if (err)
return err;
if (modules_last) if (modules_last)
modules_last->next = newmod; modules_last->next = newmod;

View file

@ -302,8 +302,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
/* Create kernel command line. */ /* Create kernel command line. */
grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE)); grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE));
grub_create_loader_cmdline (argc, argv, linux_args + sizeof (LINUX_IMAGE) - 1, if (grub_create_loader_cmdline (argc, argv, linux_args + sizeof (LINUX_IMAGE) - 1,
size); size))
goto out;
out: out:

View file

@ -340,8 +340,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
/* Create kernel command line. */ /* Create kernel command line. */
grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE)); grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE));
grub_create_loader_cmdline (argc, argv, linux_args + sizeof (LINUX_IMAGE) - 1, if (grub_create_loader_cmdline (argc, argv, linux_args + sizeof (LINUX_IMAGE) - 1,
size); size, GRUB_VERIFY_KERNEL_CMDLINE))
goto out;
out: out:
if (elf) if (elf)

View file

@ -33,6 +33,7 @@
#include <grub/extcmd.h> #include <grub/extcmd.h>
#include <grub/env.h> #include <grub/env.h>
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/verify.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
@ -425,6 +426,10 @@ grub_cmd_xnu_kernel (grub_command_t cmd __attribute__ ((unused)),
if (ptr != grub_xnu_cmdline) if (ptr != grub_xnu_cmdline)
*(ptr - 1) = 0; *(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) #if defined (__i386) && !defined (GRUB_MACHINE_EFI)
err = grub_efiemu_autocore (); err = grub_efiemu_autocore ();
if (err) if (err)
@ -534,6 +539,10 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)),
if (ptr != grub_xnu_cmdline) if (ptr != grub_xnu_cmdline)
*(ptr - 1) = 0; *(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) #if defined (__i386) && !defined (GRUB_MACHINE_EFI)
err = grub_efiemu_autocore (); err = grub_efiemu_autocore ();
if (err) if (err)

View file

@ -21,11 +21,12 @@
#define GRUB_CMDLINE_HEADER 1 #define GRUB_CMDLINE_HEADER 1
#include <grub/types.h> #include <grub/types.h>
#include <grub/verify.h>
#define LINUX_IMAGE "BOOT_IMAGE=" #define LINUX_IMAGE "BOOT_IMAGE="
unsigned int grub_loader_cmdline_size (int argc, char *argv[]); unsigned int grub_loader_cmdline_size (int argc, char *argv[]);
int grub_create_loader_cmdline (int argc, char *argv[], char *buf, grub_err_t grub_create_loader_cmdline (int argc, char *argv[], char *buf,
grub_size_t size); grub_size_t size, enum grub_verify_string_type type);
#endif /* ! GRUB_CMDLINE_HEADER */ #endif /* ! GRUB_CMDLINE_HEADER */

View file

@ -25,6 +25,12 @@ enum grub_verify_flags
GRUB_VERIFY_FLAGS_SINGLE_CHUNK = 2 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
{ {
struct grub_file_verifier *next; struct grub_file_verifier *next;
@ -48,6 +54,8 @@ struct grub_file_verifier
grub_err_t (*fini) (void *context); grub_err_t (*fini) (void *context);
void (*close) (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; 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_list_remove (GRUB_AS_LIST (ver));
} }
grub_err_t
grub_verify_string (char *str, enum grub_verify_string_type type);