cli_lock: Add build option to block command line interface

Add functionality to disable command line interface access and editing of GRUB
menu entries if GRUB image is built with --disable-cli.

Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
Reviewed-by: Vladimir Serbinenko <phcoder@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
This commit is contained in:
Alec Brown 2024-01-24 06:26:37 +00:00 committed by Daniel Kiper
parent 56e58828cf
commit bb65d81fe3
11 changed files with 106 additions and 24 deletions

View File

@ -6422,8 +6422,10 @@ the GRUB command line, edit menu entries, and execute any menu entry. If
@samp{superusers} is set, then use of the command line and editing of menu @samp{superusers} is set, then use of the command line and editing of menu
entries are automatically restricted to superusers. Setting @samp{superusers} entries are automatically restricted to superusers. Setting @samp{superusers}
to empty string effectively disables both access to CLI and editing of menu to empty string effectively disables both access to CLI and editing of menu
entries. Note: The environment variable needs to be exported to also affect entries. Building a grub image with @samp{--disable-cli} option will also
the section defined by the @samp{submenu} command (@pxref{submenu}). disable access to CLI and editing of menu entries, as well as disabling rescue
mode. Note: The environment variable needs to be exported to also affect the
section defined by the @samp{submenu} command (@pxref{submenu}).
Other users may be allowed to execute specific menu entries by giving a list of Other users may be allowed to execute specific menu entries by giving a list of
usernames (as above) using the @option{--users} option to the usernames (as above) using the @option{--users} option to the

View File

@ -31,11 +31,14 @@
#include <grub/reader.h> #include <grub/reader.h>
#include <grub/parser.h> #include <grub/parser.h>
#include <grub/verify.h> #include <grub/verify.h>
#include <grub/types.h>
#ifdef GRUB_MACHINE_PCBIOS #ifdef GRUB_MACHINE_PCBIOS
#include <grub/machine/memory.h> #include <grub/machine/memory.h>
#endif #endif
static bool cli_disabled = false;
grub_addr_t grub_addr_t
grub_modules_get_end (void) grub_modules_get_end (void)
{ {
@ -238,6 +241,28 @@ grub_load_normal_mode (void)
grub_command_execute ("normal", 0, 0); grub_command_execute ("normal", 0, 0);
} }
bool
grub_is_cli_disabled (void)
{
return cli_disabled;
}
static void
check_is_cli_disabled (void)
{
struct grub_module_header *header;
header = 0;
FOR_MODULES (header)
{
if (header->type == OBJ_TYPE_DISABLE_CLI)
{
cli_disabled = true;
return;
}
}
}
static void static void
reclaim_module_space (void) reclaim_module_space (void)
{ {
@ -305,6 +330,9 @@ grub_main (void)
grub_boot_time ("After loading embedded modules."); grub_boot_time ("After loading embedded modules.");
/* Check if the CLI should be disabled */
check_is_cli_disabled ();
/* It is better to set the root device as soon as possible, /* It is better to set the root device as soon as possible,
for convenience. */ for convenience. */
grub_set_prefix_and_root (); grub_set_prefix_and_root ();

View File

@ -78,6 +78,19 @@ grub_rescue_read_line (char **line, int cont,
void __attribute__ ((noreturn)) void __attribute__ ((noreturn))
grub_rescue_run (void) grub_rescue_run (void)
{ {
/* Stall if the CLI has been disabled */
if (grub_is_cli_disabled ())
{
grub_printf ("Rescue mode has been disabled...\n");
do
{
/* Do not optimize out the loop. */
asm volatile ("");
}
while (1);
}
grub_printf ("Entering rescue mode...\n"); grub_printf ("Entering rescue mode...\n");
while (1) while (1)

View File

@ -209,6 +209,9 @@ grub_auth_check_authentication (const char *userlist)
char entered[GRUB_AUTH_MAX_PASSLEN]; char entered[GRUB_AUTH_MAX_PASSLEN];
struct grub_auth_user *user; struct grub_auth_user *user;
if (grub_is_cli_disabled ())
return GRUB_ACCESS_DENIED;
grub_memset (login, 0, sizeof (login)); grub_memset (login, 0, sizeof (login));
if (is_authenticated (userlist)) if (is_authenticated (userlist))

View File

@ -178,21 +178,24 @@ command-line or ESC to discard edits and return to the GRUB menu."),
grub_free (msg_translated); grub_free (msg_translated);
if (nested) if (!grub_is_cli_disabled ())
{ {
ret += grub_print_message_indented_real if (nested)
(_("Press enter to boot the selected OS, " {
"`e' to edit the commands before booting " ret += grub_print_message_indented_real
"or `c' for a command-line. ESC to return previous menu."), (_("Press enter to boot the selected OS, "
STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run); "`e' to edit the commands before booting "
} "or `c' for a command-line. ESC to return previous menu."),
else STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
{ }
ret += grub_print_message_indented_real else
(_("Press enter to boot the selected OS, " {
"`e' to edit the commands before booting " ret += grub_print_message_indented_real
"or `c' for a command-line."), (_("Press enter to boot the selected OS, "
STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run); "`e' to edit the commands before booting "
"or `c' for a command-line."),
STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
}
} }
} }
return ret; return ret;

View File

@ -30,7 +30,8 @@ enum
OBJ_TYPE_PREFIX, OBJ_TYPE_PREFIX,
OBJ_TYPE_PUBKEY, OBJ_TYPE_PUBKEY,
OBJ_TYPE_DTB, OBJ_TYPE_DTB,
OBJ_TYPE_DISABLE_SHIM_LOCK OBJ_TYPE_DISABLE_SHIM_LOCK,
OBJ_TYPE_DISABLE_CLI
}; };
/* The module header. */ /* The module header. */

View File

@ -391,6 +391,8 @@ grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n,
grub_uint64_t d, grub_uint64_t d,
grub_uint64_t *r); grub_uint64_t *r);
extern bool EXPORT_FUNC(grub_is_cli_disabled) (void);
/* Must match softdiv group in gentpl.py. */ /* Must match softdiv group in gentpl.py. */
#if !defined(GRUB_MACHINE_EMU) && (defined(__arm__) || defined(__ia64__) || \ #if !defined(GRUB_MACHINE_EMU) && (defined(__arm__) || defined(__ia64__) || \
(defined(__riscv) && (__riscv_xlen == 32))) (defined(__riscv) && (__riscv_xlen == 32)))

View File

@ -67,6 +67,8 @@
N_("SBAT metadata"), 0 }, \ N_("SBAT metadata"), 0 }, \
{ "disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, \ { "disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, \
N_("disable shim_lock verifier"), 0 }, \ N_("disable shim_lock verifier"), 0 }, \
{ "disable-cli", GRUB_INSTALL_OPTIONS_DISABLE_CLI, 0, 0, \
N_("disabled command line interface access"), 0 }, \
{ "verbose", 'v', 0, 0, \ { "verbose", 'v', 0, 0, \
N_("print verbose messages."), 1 } N_("print verbose messages."), 1 }
@ -129,7 +131,8 @@ enum grub_install_options {
GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS, GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS,
GRUB_INSTALL_OPTIONS_DTB, GRUB_INSTALL_OPTIONS_DTB,
GRUB_INSTALL_OPTIONS_SBAT, GRUB_INSTALL_OPTIONS_SBAT,
GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK,
GRUB_INSTALL_OPTIONS_DISABLE_CLI
}; };
extern char *grub_install_source_directory; extern char *grub_install_source_directory;
@ -191,7 +194,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
const struct grub_install_image_target_desc *image_target, const struct grub_install_image_target_desc *image_target,
int note, int note,
grub_compression_t comp, const char *dtb_file, grub_compression_t comp, const char *dtb_file,
const char *sbat_path, const int disable_shim_lock); const char *sbat_path, const int disable_shim_lock,
const int disable_cli);
const struct grub_install_image_target_desc * const struct grub_install_image_target_desc *
grub_install_get_image_target (const char *arg); grub_install_get_image_target (const char *arg);

View File

@ -466,6 +466,7 @@ static size_t npubkeys;
static char *sbat; static char *sbat;
static int disable_shim_lock; static int disable_shim_lock;
static grub_compression_t compression; static grub_compression_t compression;
static int disable_cli;
int int
grub_install_parse (int key, char *arg) grub_install_parse (int key, char *arg)
@ -504,6 +505,9 @@ grub_install_parse (int key, char *arg)
case GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK: case GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK:
disable_shim_lock = 1; disable_shim_lock = 1;
return 1; return 1;
case GRUB_INSTALL_OPTIONS_DISABLE_CLI:
disable_cli = 1;
return 1;
case GRUB_INSTALL_OPTIONS_VERBOSITY: case GRUB_INSTALL_OPTIONS_VERBOSITY:
verbosity++; verbosity++;
@ -679,11 +683,12 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
*p = '\0'; *p = '\0';
grub_util_info ("grub-mkimage --directory '%s' --prefix '%s' --output '%s'" grub_util_info ("grub-mkimage --directory '%s' --prefix '%s' --output '%s'"
" --format '%s' --compression '%s'%s%s%s\n", " --format '%s' --compression '%s'%s%s%s%s\n",
dir, prefix, outname, dir, prefix, outname,
mkimage_target, compnames[compression], mkimage_target, compnames[compression],
note ? " --note" : "", note ? " --note" : "",
disable_shim_lock ? " --disable-shim-lock" : "", s); disable_shim_lock ? " --disable-shim-lock" : "",
disable_cli ? " --disable-cli" : "", s);
free (s); free (s);
tgt = grub_install_get_image_target (mkimage_target); tgt = grub_install_get_image_target (mkimage_target);
@ -694,7 +699,7 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
modules.entries, memdisk_path, modules.entries, memdisk_path,
pubkeys, npubkeys, config_path, tgt, pubkeys, npubkeys, config_path, tgt,
note, compression, dtb, sbat, note, compression, dtb, sbat,
disable_shim_lock); disable_shim_lock, disable_cli);
while (dc--) while (dc--)
grub_install_pop_module (); grub_install_pop_module ();
} }

View File

@ -83,6 +83,7 @@ static struct argp_option options[] = {
{"compression", 'C', "(xz|none|auto)", 0, N_("choose the compression to use for core image"), 0}, {"compression", 'C', "(xz|none|auto)", 0, N_("choose the compression to use for core image"), 0},
{"sbat", 's', N_("FILE"), 0, N_("SBAT metadata"), 0}, {"sbat", 's', N_("FILE"), 0, N_("SBAT metadata"), 0},
{"disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, N_("disable shim_lock verifier"), 0}, {"disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, N_("disable shim_lock verifier"), 0},
{"disable-cli", GRUB_INSTALL_OPTIONS_DISABLE_CLI, 0, 0, N_("disable command line interface access"), 0},
{"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, {"verbose", 'v', 0, 0, N_("print verbose messages."), 0},
{ 0, 0, 0, 0, 0, 0 } { 0, 0, 0, 0, 0, 0 }
}; };
@ -128,6 +129,7 @@ struct arguments
char *sbat; char *sbat;
int note; int note;
int disable_shim_lock; int disable_shim_lock;
int disable_cli;
const struct grub_install_image_target_desc *image_target; const struct grub_install_image_target_desc *image_target;
grub_compression_t comp; grub_compression_t comp;
}; };
@ -239,6 +241,10 @@ argp_parser (int key, char *arg, struct argp_state *state)
arguments->disable_shim_lock = 1; arguments->disable_shim_lock = 1;
break; break;
case GRUB_INSTALL_OPTIONS_DISABLE_CLI:
arguments->disable_cli = 1;
break;
case 'v': case 'v':
verbosity++; verbosity++;
break; break;
@ -325,7 +331,8 @@ main (int argc, char *argv[])
arguments.npubkeys, arguments.config, arguments.npubkeys, arguments.config,
arguments.image_target, arguments.note, arguments.image_target, arguments.note,
arguments.comp, arguments.dtb, arguments.comp, arguments.dtb,
arguments.sbat, arguments.disable_shim_lock); arguments.sbat, arguments.disable_shim_lock,
arguments.disable_cli);
if (grub_util_file_sync (fp) < 0) if (grub_util_file_sync (fp) < 0)
grub_util_error (_("cannot sync `%s': %s"), arguments.output ? : "stdout", grub_util_error (_("cannot sync `%s': %s"), arguments.output ? : "stdout",

View File

@ -886,7 +886,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
size_t npubkeys, char *config_path, size_t npubkeys, char *config_path,
const struct grub_install_image_target_desc *image_target, const struct grub_install_image_target_desc *image_target,
int note, grub_compression_t comp, const char *dtb_path, int note, grub_compression_t comp, const char *dtb_path,
const char *sbat_path, int disable_shim_lock) const char *sbat_path, int disable_shim_lock,
int disable_cli)
{ {
char *kernel_img, *core_img; char *kernel_img, *core_img;
size_t total_module_size, core_size; size_t total_module_size, core_size;
@ -948,6 +949,9 @@ grub_install_generate_image (const char *dir, const char *prefix,
if (disable_shim_lock) if (disable_shim_lock)
total_module_size += sizeof (struct grub_module_header); total_module_size += sizeof (struct grub_module_header);
if (disable_cli)
total_module_size += sizeof (struct grub_module_header);
if (config_path) if (config_path)
{ {
config_size = ALIGN_ADDR (grub_util_get_image_size (config_path) + 1); config_size = ALIGN_ADDR (grub_util_get_image_size (config_path) + 1);
@ -1094,6 +1098,16 @@ grub_install_generate_image (const char *dir, const char *prefix,
offset += sizeof (*header); offset += sizeof (*header);
} }
if (disable_cli)
{
struct grub_module_header *header;
header = (struct grub_module_header *) (kernel_img + offset);
header->type = grub_host_to_target32 (OBJ_TYPE_DISABLE_CLI);
header->size = grub_host_to_target32 (sizeof (*header));
offset += sizeof (*header);
}
if (config_path) if (config_path)
{ {
struct grub_module_header *header; struct grub_module_header *header;