This gives load_env support for naming variables that is the same as save_env. This is useful to prevent potentially unwanted variables within a grubenv file from impacting the behavior of a configuration, especially if using check_signatures=enforce but wishing to retain support for savedefault, boot_once, and similar.
This version of this patch drops all direct interaction with the logic in verify.c. The author of grub.cfg must take care to disable and re-enable check_signatures as appropriate. Signed-off-by: Jon McCune <jonmcc...@google.com> --- grub-core/commands/loadenv.c | 57 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 5 deletions(-) diff --git a/grub-core/commands/loadenv.c b/grub-core/commands/loadenv.c index a431499..5828f5f 100644 --- a/grub-core/commands/loadenv.c +++ b/grub-core/commands/loadenv.c @@ -122,15 +122,59 @@ set_var (const char *name, const char *value) return 0; } +#define MAX_VAR_NAME 1024 +/* TODO: eliminate the need for these to be global */ +static grub_size_t whitelist_len = 0; +static char **whitelist_vars = NULL; +static int +/* Assumptions: name, value, and each element of whitelist_vars[] are non-NULL + and NULL-terminated. */ +set_var_whitelist (const char *name, const char *value) +{ + grub_size_t i; + if (whitelist_len < 1 || whitelist_vars == NULL) + return GRUB_ERR_OUT_OF_RANGE; + + /* search for 'name' in the whitelist */ + for (i = 0; i < whitelist_len; i++) + { + if (0 == grub_strncmp (name, whitelist_vars[i], MAX_VAR_NAME)) + { + /* TODO: also validate the characters in the variables */ + grub_dprintf ("crypt", "set_var_whitelist APPOVED: %s=%s\n", + name, value); + grub_env_set (name, value); + return 0; + } + } + + grub_dprintf ("crypt", + "set_var_whitelist REFUSING TO SET name='%s' value='%s'\n", + name, value); + /* Still considered success */ + return 0; +} + +/* Load environment variables from a file. Accepts a flag which can override + the file from which variables are read. If additional parameters are passed + (argc > 0), then those are interpreted as a whitelist of environment + variables whose values can be changed based on the contents of the file, and + the file is never signature-checked. + Otherwise, all variables from the file are processed, and the file must be + properly signed when check_signatures=enforce. */ static grub_err_t -grub_cmd_load_env (grub_extcmd_context_t ctxt, - int argc __attribute__ ((unused)), - char **args __attribute__ ((unused))) +grub_cmd_load_env (grub_extcmd_context_t ctxt, int argc, char **args) { struct grub_arg_list *state = ctxt->state; grub_file_t file; grub_envblk_t envblk; + /* argc > 0 indicates caller provided a whitelist of variables to read */ + if (argc > 0) + { + whitelist_len = (argc >= 0) ? argc : 0; + whitelist_vars = args; + } file = open_envblk_file ((state[0].set) ? state[0].arg : 0); if (!file) return grub_errno; @@ -139,10 +183,12 @@ grub_cmd_load_env (grub_extcmd_context_t ctxt, if (!envblk) goto fail; - grub_envblk_iterate (envblk, set_var); + grub_envblk_iterate (envblk, argc > 0 ? set_var_whitelist : set_var); grub_envblk_close (envblk); fail: + whitelist_len = 0; + whitelist_vars = NULL; grub_file_close (file); return grub_errno; } @@ -387,7 +433,8 @@ static grub_extcmd_t cmd_load, cmd_list, cmd_save; GRUB_MOD_INIT (loadenv) { cmd_load = - grub_register_extcmd ("load_env", grub_cmd_load_env, 0, N_("[-f FILE]"), + grub_register_extcmd ("load_env", grub_cmd_load_env, 0, + N_("[-f FILE] [whitelisted_variable_name] [...]"), N_("Load variables from environment block file."), options); cmd_list = -- 1.8.4 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel