Reviewed-By: Vladimir Serbinenko

On Wed, Jan 24, 2024 at 9:27 AM Alec Brown <alec.r.br...@oracle.com> wrote:
>
> Added 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.br...@oracle.com>
> ---
>  docs/grub.texi                 |  6 ++++--
>  grub-core/kern/main.c          | 28 ++++++++++++++++++++++++++++
>  grub-core/kern/rescue_reader.c | 13 +++++++++++++
>  grub-core/normal/auth.c        |  3 +++
>  grub-core/normal/menu_text.c   | 31 +++++++++++++++++--------------
>  include/grub/kernel.h          |  3 ++-
>  include/grub/misc.h            |  2 ++
>  include/grub/util/install.h    |  8 ++++++--
>  util/grub-install-common.c     | 11 ++++++++---
>  util/grub-mkimage.c            |  9 ++++++++-
>  util/mkimage.c                 | 16 +++++++++++++++-
>  11 files changed, 106 insertions(+), 24 deletions(-)
>
> diff --git a/docs/grub.texi b/docs/grub.texi
> index a225f9a88..96ab17d5b 100644
> --- a/docs/grub.texi
> +++ b/docs/grub.texi
> @@ -6412,8 +6412,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
>  entries are automatically restricted to superusers. Setting @samp{superusers}
>  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
> -the section defined by the @samp{submenu} command (@pxref{submenu}).
> +entries. Building a grub image with @samp{--disable-cli} option will also
> +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
>  usernames (as above) using the @option{--users} option to the
> diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
> index 731c07c29..30643164e 100644
> --- a/grub-core/kern/main.c
> +++ b/grub-core/kern/main.c
> @@ -30,11 +30,14 @@
>  #include <grub/reader.h>
>  #include <grub/parser.h>
>  #include <grub/verify.h>
> +#include <grub/types.h>
>
>  #ifdef GRUB_MACHINE_PCBIOS
>  #include <grub/machine/memory.h>
>  #endif
>
> +static bool cli_disabled = false;
> +
>  grub_addr_t
>  grub_modules_get_end (void)
>  {
> @@ -237,6 +240,28 @@ grub_load_normal_mode (void)
>    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
>  reclaim_module_space (void)
>  {
> @@ -294,6 +319,9 @@ grub_main (void)
>
>    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,
>       for convenience.  */
>    grub_set_prefix_and_root ();
> diff --git a/grub-core/kern/rescue_reader.c b/grub-core/kern/rescue_reader.c
> index dcd7d4439..4259857ba 100644
> --- a/grub-core/kern/rescue_reader.c
> +++ b/grub-core/kern/rescue_reader.c
> @@ -78,6 +78,19 @@ grub_rescue_read_line (char **line, int cont,
>  void __attribute__ ((noreturn))
>  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");
>
>    while (1)
> diff --git a/grub-core/normal/auth.c b/grub-core/normal/auth.c
> index 517fc623f..d94020186 100644
> --- a/grub-core/normal/auth.c
> +++ b/grub-core/normal/auth.c
> @@ -209,6 +209,9 @@ grub_auth_check_authentication (const char *userlist)
>    char entered[GRUB_AUTH_MAX_PASSLEN];
>    struct grub_auth_user *user;
>
> +  if (grub_is_cli_disabled ())
> +    return GRUB_ACCESS_DENIED;
> +
>    grub_memset (login, 0, sizeof (login));
>
>    if (is_authenticated (userlist))
> diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
> index b1321eb26..9c383e64a 100644
> --- a/grub-core/normal/menu_text.c
> +++ b/grub-core/normal/menu_text.c
> @@ -178,21 +178,24 @@ command-line or ESC to discard edits and return to the 
> GRUB menu."),
>
>        grub_free (msg_translated);
>
> -      if (nested)
> +      if (!grub_is_cli_disabled ())
>         {
> -         ret += grub_print_message_indented_real
> -           (_("Press enter to boot the selected OS, "
> -              "`e' to edit the commands before booting "
> -              "or `c' for a command-line. ESC to return previous menu."),
> -            STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
> -       }
> -      else
> -       {
> -         ret += grub_print_message_indented_real
> -           (_("Press enter to boot the selected OS, "
> -              "`e' to edit the commands before booting "
> -              "or `c' for a command-line."),
> -            STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
> +         if (nested)
> +           {
> +             ret += grub_print_message_indented_real
> +               (_("Press enter to boot the selected OS, "
> +                  "`e' to edit the commands before booting "
> +                  "or `c' for a command-line. ESC to return previous menu."),
> +                STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
> +           }
> +         else
> +           {
> +             ret += grub_print_message_indented_real
> +               (_("Press enter to boot the selected OS, "
> +                  "`e' to edit the commands before booting "
> +                  "or `c' for a command-line."),
> +                STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
> +           }
>         }
>      }
>    return ret;
> diff --git a/include/grub/kernel.h b/include/grub/kernel.h
> index abbca5ea3..6121c1e66 100644
> --- a/include/grub/kernel.h
> +++ b/include/grub/kernel.h
> @@ -30,7 +30,8 @@ enum
>    OBJ_TYPE_PREFIX,
>    OBJ_TYPE_PUBKEY,
>    OBJ_TYPE_DTB,
> -  OBJ_TYPE_DISABLE_SHIM_LOCK
> +  OBJ_TYPE_DISABLE_SHIM_LOCK,
> +  OBJ_TYPE_DISABLE_CLI
>  };
>
>  /* The module header.  */
> diff --git a/include/grub/misc.h b/include/grub/misc.h
> index 1b35a167f..1578f36c3 100644
> --- a/include/grub/misc.h
> +++ b/include/grub/misc.h
> @@ -391,6 +391,8 @@ grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n,
>                                           grub_uint64_t d,
>                                           grub_uint64_t *r);
>
> +extern bool EXPORT_FUNC(grub_is_cli_disabled) (void);
> +
>  /* Must match softdiv group in gentpl.py.  */
>  #if !defined(GRUB_MACHINE_EMU) && (defined(__arm__) || defined(__ia64__) || \
>      (defined(__riscv) && (__riscv_xlen == 32)))
> diff --git a/include/grub/util/install.h b/include/grub/util/install.h
> index 35cf17a8d..5c0a52ca2 100644
> --- a/include/grub/util/install.h
> +++ b/include/grub/util/install.h
> @@ -67,6 +67,8 @@
>        N_("SBAT metadata"), 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_("disabled command line interface access"), 0 },                 \
>    { "verbose", 'v', 0, 0,                                              \
>      N_("print verbose messages."), 1 }
>
> @@ -129,7 +131,8 @@ enum grub_install_options {
>    GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS,
>    GRUB_INSTALL_OPTIONS_DTB,
>    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;
> @@ -191,7 +194,8 @@ grub_install_generate_image (const char *dir, const char 
> *prefix,
>                              const struct grub_install_image_target_desc 
> *image_target,
>                              int note,
>                              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 *
>  grub_install_get_image_target (const char *arg);
> diff --git a/util/grub-install-common.c b/util/grub-install-common.c
> index ce854d86f..22bccb6a3 100644
> --- a/util/grub-install-common.c
> +++ b/util/grub-install-common.c
> @@ -466,6 +466,7 @@ static size_t npubkeys;
>  static char *sbat;
>  static int disable_shim_lock;
>  static grub_compression_t compression;
> +static int disable_cli;
>
>  int
>  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:
>        disable_shim_lock = 1;
>        return 1;
> +    case GRUB_INSTALL_OPTIONS_DISABLE_CLI:
> +      disable_cli = 1;
> +      return 1;
>
>      case GRUB_INSTALL_OPTIONS_VERBOSITY:
>        verbosity++;
> @@ -679,11 +683,12 @@ grub_install_make_image_wrap_file (const char *dir, 
> const char *prefix,
>    *p = '\0';
>
>    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,
>                   mkimage_target, compnames[compression],
>                   note ? " --note" : "",
> -                 disable_shim_lock ? " --disable-shim-lock" : "", s);
> +                 disable_shim_lock ? " --disable-shim-lock" : "",
> +                 disable_cli ? " --disable-cli" : "", s);
>    free (s);
>
>    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,
>                                pubkeys, npubkeys, config_path, tgt,
>                                note, compression, dtb, sbat,
> -                              disable_shim_lock);
> +                              disable_shim_lock, disable_cli);
>    while (dc--)
>      grub_install_pop_module ();
>  }
> diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c
> index c0d559937..547f7310f 100644
> --- a/util/grub-mkimage.c
> +++ b/util/grub-mkimage.c
> @@ -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},
>    {"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-cli", GRUB_INSTALL_OPTIONS_DISABLE_CLI, 0, 0, N_("disable 
> command line interface access"), 0},
>    {"verbose",     'v', 0,      0, N_("print verbose messages."), 0},
>    { 0, 0, 0, 0, 0, 0 }
>  };
> @@ -128,6 +129,7 @@ struct arguments
>    char *sbat;
>    int note;
>    int disable_shim_lock;
> +  int disable_cli;
>    const struct grub_install_image_target_desc *image_target;
>    grub_compression_t comp;
>  };
> @@ -239,6 +241,10 @@ argp_parser (int key, char *arg, struct argp_state 
> *state)
>        arguments->disable_shim_lock = 1;
>        break;
>
> +    case GRUB_INSTALL_OPTIONS_DISABLE_CLI:
> +      arguments->disable_cli = 1;
> +      break;
> +
>      case 'v':
>        verbosity++;
>        break;
> @@ -325,7 +331,8 @@ main (int argc, char *argv[])
>                                arguments.npubkeys, arguments.config,
>                                arguments.image_target, arguments.note,
>                                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)
>      grub_util_error (_("cannot sync `%s': %s"), arguments.output ? : 
> "stdout",
> diff --git a/util/mkimage.c b/util/mkimage.c
> index 4237383ac..8c5660825 100644
> --- a/util/mkimage.c
> +++ b/util/mkimage.c
> @@ -886,7 +886,8 @@ grub_install_generate_image (const char *dir, const char 
> *prefix,
>                              size_t npubkeys, char *config_path,
>                              const struct grub_install_image_target_desc 
> *image_target,
>                              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;
>    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)
>      total_module_size += sizeof (struct grub_module_header);
>
> +  if (disable_cli)
> +    total_module_size += sizeof (struct grub_module_header);
> +
>    if (config_path)
>      {
>        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);
>      }
>
> +  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)
>      {
>        struct grub_module_header *header;
> --
> 2.27.0
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel



-- 
Regards
Vladimir 'phcoder' Serbinenko

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to