File 0001-cli_lock-Add-build-option-to-block-command-line-inte.patch of Package grub2

From bb65d81fe320e4b20d0a9b32232a7546eb275ecc Mon Sep 17 00:00:00 2001
From: Alec Brown <alec.r.brown@oracle.com>
Date: Wed, 24 Jan 2024 06:26:37 +0000
Subject: [PATCH] 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>
---
 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(-)

Index: grub-2.12/docs/grub.texi
===================================================================
--- grub-2.12.orig/docs/grub.texi
+++ grub-2.12/docs/grub.texi
@@ -6470,8 +6470,10 @@ the GRUB command line, edit menu entries
 @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
Index: grub-2.12/grub-core/kern/main.c
===================================================================
--- grub-2.12.orig/grub-core/kern/main.c
+++ grub-2.12/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)
 {
@@ -241,6 +244,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)
 {
@@ -298,6 +323,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 ();
Index: grub-2.12/grub-core/kern/rescue_reader.c
===================================================================
--- grub-2.12.orig/grub-core/kern/rescue_reader.c
+++ grub-2.12/grub-core/kern/rescue_reader.c
@@ -78,6 +78,19 @@ grub_rescue_read_line (char **line, int
 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)
Index: grub-2.12/grub-core/normal/auth.c
===================================================================
--- grub-2.12.orig/grub-core/normal/auth.c
+++ grub-2.12/grub-core/normal/auth.c
@@ -209,6 +209,9 @@ grub_auth_check_authentication (const ch
   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))
Index: grub-2.12/grub-core/normal/menu_text.c
===================================================================
--- grub-2.12.orig/grub-core/normal/menu_text.c
+++ grub-2.12/grub-core/normal/menu_text.c
@@ -194,21 +194,24 @@ command-line or ESC to discard edits and
       grub_free (msg_translated);
 #endif
 
-      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;
Index: grub-2.12/include/grub/kernel.h
===================================================================
--- grub-2.12.orig/include/grub/kernel.h
+++ grub-2.12/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.  */
Index: grub-2.12/include/grub/misc.h
===================================================================
--- grub-2.12.orig/include/grub/misc.h
+++ grub-2.12/include/grub/misc.h
@@ -430,6 +430,8 @@ grub_uint64_t EXPORT_FUNC(grub_divmod64)
 					  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)))
Index: grub-2.12/include/grub/util/install.h
===================================================================
--- grub-2.12.orig/include/grub/util/install.h
+++ grub-2.12/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 }
 
@@ -130,7 +132,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;
@@ -192,7 +195,8 @@ grub_install_generate_image (const char
 			     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);
Index: grub-2.12/util/grub-install-common.c
===================================================================
--- grub-2.12.orig/util/grub-install-common.c
+++ grub-2.12/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
   *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
 			       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 ();
 }
Index: grub-2.12/util/grub-mkimage.c
===================================================================
--- grub-2.12.orig/util/grub-mkimage.c
+++ grub-2.12/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
       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",
Index: grub-2.12/util/mkimage.c
===================================================================
--- grub-2.12.orig/util/mkimage.c
+++ grub-2.12/util/mkimage.c
@@ -886,7 +886,8 @@ grub_install_generate_image (const char
 			     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
   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);
@@ -1093,6 +1097,16 @@ grub_install_generate_image (const char
       header->size = grub_host_to_target32 (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)
     {
openSUSE Build Service is sponsored by