From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <dja@axtens.net>
Date: Wed, 29 Jul 2020 17:46:16 +1000
Subject: [PATCH] verifiers: provide unsafe module list

Other verifiers that implement secure boot may want to be able to
use this list and behaviour.

Upstream, this factors the list out of the shim_lock verifier.
However, that hasn't hit the RHEL8.4 tree yet, so instead
of factoring it out of that we just create it.

Signed-off-by: Daniel Axtens <dja@axtens.net>
---
 grub-core/commands/verifiers.c | 46 ++++++++++++++++++++++++++++++++++++++++++
 include/grub/verify.h          | 13 ++++++++++++
 2 files changed, 59 insertions(+)

diff --git a/grub-core/commands/verifiers.c b/grub-core/commands/verifiers.c
index 599d79b75..f64343ac9 100644
--- a/grub-core/commands/verifiers.c
+++ b/grub-core/commands/verifiers.c
@@ -218,6 +218,52 @@ grub_verify_string (char *str, enum grub_verify_string_type type)
   return GRUB_ERR_NONE;
 }
 
+/* List of modules which may allow for verifcation to be bypassed. */
+static const char *const disabled_mods[] = { "iorw", "memrw", "wrmsr", NULL };
+
+/*
+ * Does the module in file `io' allow for the a verifier to be bypassed?
+ *
+ * Returns 1 if so, otherwise 0.
+ */
+char
+grub_is_dangerous_module (grub_file_t io)
+{
+  char *b, *e;
+  int i;
+
+  /* Establish GRUB module name. */
+  b = grub_strrchr (io->name, '/');
+  e = grub_strrchr (io->name, '.');
+
+  b = b ? (b + 1) : io->name;
+  e = e ? e : io->name + grub_strlen (io->name);
+  e = (e > b) ? e : io->name + grub_strlen (io->name);
+
+  for (i = 0; disabled_mods[i]; i++)
+    if (!grub_strncmp (b, disabled_mods[i],
+		       grub_strlen (b) - grub_strlen (e)))
+      return 1;
+  return 0;
+}
+
+/*
+ * Is there already an unsafe module in memory?
+ * Returns the name if one is loaded, otherwise NULL.
+ */
+const char *
+grub_dangerous_module_loaded (void)
+{
+  int i;
+
+  for (i = 0; disabled_mods[i]; i++)
+    if (grub_dl_get (disabled_mods[i]))
+      {
+	return disabled_mods[i];
+      }
+  return NULL;
+}
+
 GRUB_MOD_INIT(verifiers)
 {
   grub_file_filter_register (GRUB_FILE_FILTER_VERIFY, grub_verifiers_open);
diff --git a/include/grub/verify.h b/include/grub/verify.h
index 79022b422..60c13e7ea 100644
--- a/include/grub/verify.h
+++ b/include/grub/verify.h
@@ -76,3 +76,16 @@ grub_verifier_unregister (struct grub_file_verifier *ver)
 
 grub_err_t
 grub_verify_string (char *str, enum grub_verify_string_type type);
+
+/*
+ * Does the module in file `io' allow for the a verifier to be bypassed?
+ *
+ * Returns 1 if so, otherwise 0.
+ */
+char grub_is_dangerous_module (grub_file_t io);
+
+/*
+ * Is there already an unsafe module in memory?
+ * Returns the name if one is loaded, otherwise NULL.
+ */
+const char *grub_dangerous_module_loaded (void);
