static grub_err_t
grub_cmd_source (grub_command_t cmd, int argc, char **args)
{
- int new_env;
+ int new_env, jail;
if (argc != 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
- new_env = (cmd->name[0] == 'c');
+ jail = (cmd->name[0] == 'j');
+ new_env = (cmd->name[jail ? 5 : 0] == 'c');
if (new_env)
- {
- grub_cls ();
- grub_env_context_open (1);
- }
+ grub_cls ();
+
+ if (new_env && !jail)
+ grub_env_context_open ();
+ if (jail)
+ grub_env_jail_open (!new_env);
grub_normal_execute (args[0], 1, ! new_env);
- if (new_env)
+ if (new_env && !jail)
grub_env_context_close ();
+ if (jail)
+ grub_env_jail_close (!new_env);
return 0;
}
static grub_command_t cmd_configfile, cmd_source, cmd_dot;
+static grub_command_t cmd_jail_source, cmd_jail_configfile;
\f
GRUB_MOD_INIT(configfile)
{
N_("FILE"),
N_("Load another config file without changing context.")
);
+
+ cmd_jail_source =
+ grub_register_command ("jail_source", grub_cmd_source,
+ N_("FILE"),
+ N_("Load another config file without changing context but take only menuentries.")
+ );
+
+ cmd_jail_configfile =
+ grub_register_command ("jail_configfile", grub_cmd_source,
+ N_("FILE"),
+ N_("Load another config file without changing context but take only menuentries.")
+ );
+
cmd_dot =
grub_register_command (".", grub_cmd_source,
N_("FILE"),
{
grub_unregister_command (cmd_configfile);
grub_unregister_command (cmd_source);
+ grub_unregister_command (cmd_jail_configfile);
+ grub_unregister_command (cmd_jail_source);
grub_unregister_command (cmd_dot);
}
grub_menu_init (void)
{
cmd = grub_register_extcmd ("menuentry", grub_cmd_menuentry,
- GRUB_COMMAND_FLAG_BLOCKS,
+ GRUB_COMMAND_FLAG_BLOCKS
+ | GRUB_COMMAND_FLAG_UNJAILED,
N_("BLOCK"), N_("Define a menuentry."), options);
}
GRUB_MOD_INIT(search)
{
cmd =
- grub_register_extcmd ("search", grub_cmd_search, 0,
+ grub_register_extcmd ("search", grub_cmd_search, GRUB_COMMAND_FLAG_UNJAILED,
N_("[-f|-l|-u|-s|-n] [--hint HINT [--hint HINT] ...]"
" NAME"),
N_("Search devices by file, filesystem label"
{
cmd_1 = grub_register_command ("[", grub_cmd_test,
N_("EXPRESSION ]"), N_("Evaluate an expression."));
+ cmd_1->flags |= GRUB_COMMAND_FLAG_UNJAILED;
cmd_2 = grub_register_command ("test", grub_cmd_test,
N_("EXPRESSION"), N_("Evaluate an expression."));
+ cmd_2->flags |= GRUB_COMMAND_FLAG_UNJAILED;
}
GRUB_MOD_FINI(test)
void
grub_register_core_commands (void)
{
- grub_register_command ("set", grub_core_cmd_set,
- N_("[ENVVAR=VALUE]"),
- N_("Set an environment variable."));
+ grub_command_t cmd;
+ cmd = grub_register_command ("set", grub_core_cmd_set,
+ N_("[ENVVAR=VALUE]"),
+ N_("Set an environment variable."));
+ if (cmd)
+ cmd->flags |= GRUB_COMMAND_FLAG_UNJAILED;
grub_register_command ("unset", grub_core_cmd_unset,
N_("ENVVAR"),
N_("Remove an environment variable."));
current_menu->menu = nmenu;
}
-grub_err_t
-grub_env_context_open (int export)
+static grub_err_t
+grub_env_new_context (int export_all)
{
struct grub_env_context *context;
int i;
struct grub_env_var *var;
for (var = context->prev->vars[i]; var; var = var->next)
- {
- if (export && var->global)
- {
- if (grub_env_set (var->name, var->value) != GRUB_ERR_NONE)
- {
- grub_env_context_close ();
- return grub_errno;
- }
- grub_env_export (var->name);
- grub_register_variable_hook (var->name, var->read_hook, var->write_hook);
- }
- }
+ if (var->global || export_all)
+ {
+ if (grub_env_set (var->name, var->value) != GRUB_ERR_NONE)
+ {
+ grub_env_context_close ();
+ return grub_errno;
+ }
+ grub_env_export (var->name);
+ grub_register_variable_hook (var->name, var->read_hook, var->write_hook);
+ }
}
return GRUB_ERR_NONE;
}
+grub_err_t
+grub_env_context_open (void)
+{
+ return grub_env_new_context (0);
+}
+
+int grub_jail_level = 0;
+
+grub_err_t
+grub_env_jail_open (int source)
+{
+ grub_jail_level++;
+ return grub_env_new_context (source);
+}
+
grub_err_t
grub_env_context_close (void)
{
return GRUB_ERR_NONE;
}
+grub_err_t
+grub_env_jail_close (int source)
+{
+ grub_menu_t menu, menu2;
+ grub_menu_entry_t *last;
+ grub_err_t err;
+
+ if (source)
+ {
+ menu = grub_env_get_menu ();
+ grub_env_unset_menu ();
+ }
+ err = grub_env_context_close ();
+
+ if (source)
+ {
+ menu2 = grub_env_get_menu ();
+
+ last = &menu2->entry_list;
+ while (*last)
+ last = &(*last)->next;
+
+ *last = menu->entry_list;
+ menu2->size += menu->size;
+ }
+
+ grub_jail_level--;
+ return err;
+}
+
grub_err_t
grub_env_export (const char *name)
{
/* Execute the GRUB command or function. */
if (grubcmd)
{
- if ((grubcmd->flags & GRUB_COMMAND_FLAG_BLOCKS) &&
- (grubcmd->flags & GRUB_COMMAND_FLAG_EXTCMD))
+ if (grub_jail_level && !(grubcmd->flags & GRUB_COMMAND_FLAG_UNJAILED))
+ ret = grub_error (GRUB_ERR_JAIL, "%s isn't allowed to execute in jail",
+ cmdname);
+ else if ((grubcmd->flags & GRUB_COMMAND_FLAG_BLOCKS) &&
+ (grubcmd->flags & GRUB_COMMAND_FLAG_EXTCMD))
ret = grub_extcmd_dispatcher (grubcmd, argc, args, argv.script);
else
ret = (grubcmd->func) (grubcmd, argc, args);
GRUB_COMMAND_ACCEPT_DASH = 0x80,
/* This command accepts only options preceding direct arguments. */
GRUB_COMMAND_OPTIONS_AT_START = 0x100,
+ /* Can be executed in a jail. */
+ GRUB_COMMAND_FLAG_UNJAILED = 0x200
} grub_command_flags_t;
struct grub_command;
grub_env_read_hook_t read_hook,
grub_env_write_hook_t write_hook);
-grub_err_t grub_env_context_open (int export);
+grub_err_t grub_env_context_open (void);
grub_err_t grub_env_context_close (void);
grub_err_t grub_env_export (const char *name);
grub_menu_t grub_env_get_menu (void);
void grub_env_set_menu (grub_menu_t nmenu);
+grub_err_t
+grub_env_jail_open (int source);
+
+grub_err_t
+grub_env_jail_close (int source);
+
+
#endif /* ! GRUB_ENV_HEADER */
GRUB_ERR_MENU,
GRUB_ERR_TIMEOUT,
GRUB_ERR_IO,
- GRUB_ERR_ACCESS_DENIED
+ GRUB_ERR_ACCESS_DENIED,
+ GRUB_ERR_JAIL
}
grub_err_t;
void grub_xputs_normal (const char *str);
+extern int grub_jail_level;
+
#endif /* ! GRUB_NORMAL_HEADER */