File 0003-disk-diskfilter-Introduce-the-cryptocheck-command.patch of Package grub2

From 781d736bd5d0004c705d73b0348b154d8ab838cf Mon Sep 17 00:00:00 2001
From: Maxim Suhanov <dfirblog@gmail.com>
Date: Thu, 8 May 2025 19:02:09 +0200
Subject: [PATCH 3/8] disk/diskfilter: Introduce the "cryptocheck" command

This command examines a given diskfilter device, e.g., an LVM disk,
and checks if underlying disks, physical volumes, are cryptodisks,
e.g., LUKS disks, this layout is called "LVM-on-LUKS".

The return value is 0 when all underlying disks (of a given device)
are cryptodisks (1 if at least one disk is unencrypted or in an
unknown state).

Users are encouraged to include the relevant check before loading
anything from an LVM disk that is supposed to be encrypted.

This further supports the CLI authentication, blocking bypass
attempts when booting from an encrypted LVM disk.

Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/disk/diskfilter.c | 75 +++++++++++++++++++++++++++++++++++++
 1 file changed, 75 insertions(+)

diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c
index c45bef1caf..3f7c05e14e 100644
--- a/grub-core/disk/diskfilter.c
+++ b/grub-core/disk/diskfilter.c
@@ -20,6 +20,7 @@
 #include <grub/dl.h>
 #include <grub/disk.h>
 #include <grub/mm.h>
+#include <grub/command.h>
 #include <grub/err.h>
 #include <grub/misc.h>
 #include <grub/diskfilter.h>
@@ -1487,6 +1488,73 @@ grub_diskfilter_get_pv_from_disk (grub_disk_t disk,
 }
 #endif
 
+static int
+grub_diskfilter_check_pvs_encrypted (grub_disk_t disk, int *pvs_cnt)
+{
+  struct grub_diskfilter_lv *lv = disk->data;
+  struct grub_diskfilter_pv *pv;
+
+  *pvs_cnt = 0;
+
+  if (lv->vg->pvs)
+    for (pv = lv->vg->pvs; pv; pv = pv->next)
+      {
+        (*pvs_cnt)++;
+
+        if (pv->disk == NULL)
+          {
+            /* Can be a partially activated VG, bail out. */
+            return GRUB_ERR_TEST_FAILURE;
+          }
+
+        if (pv->disk->dev->id != GRUB_DISK_DEVICE_CRYPTODISK_ID)
+          {
+            /* All backing devices must be cryptodisks, stop. */
+            return GRUB_ERR_TEST_FAILURE;
+          }
+      }
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_cryptocheck (grub_command_t cmd __attribute__ ((unused)),
+               int argc, char **args)
+{
+  grub_disk_t disk;
+  int check_pvs_res;
+  int namelen;
+  int pvs_cnt;
+
+  if (argc != 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("disk name expected"));
+
+  namelen = grub_strlen (args[0]);
+  if (namelen > 2 && (args[0][0] == '(') && (args[0][namelen - 1] == ')'))
+    args[0][namelen - 1] = 0;
+  else
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("invalid disk: %s"),
+                       args[0]);
+
+  if (!is_valid_diskfilter_name (&args[0][1]))
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("unrecognized disk: %s"),
+                       &args[0][1]);
+
+  disk = grub_disk_open (&args[0][1]);
+  if (disk == NULL)
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("no such disk: %s"),
+                       &args[0][1]);
+
+  check_pvs_res = grub_diskfilter_check_pvs_encrypted (disk, &pvs_cnt);
+  grub_disk_close (disk);
+
+  grub_printf("%s is %sencrypted (%d pv%s examined)\n", &args[0][1],
+              (check_pvs_res == GRUB_ERR_NONE) ? "" : "un",
+              pvs_cnt,
+              (pvs_cnt > 1) ? "s" : "");
+
+  return check_pvs_res;
+}
+
 static struct grub_disk_dev grub_diskfilter_dev =
   {
     .name = "diskfilter",
@@ -1503,14 +1571,21 @@ static struct grub_disk_dev grub_diskfilter_dev =
     .next = 0
   };
 
+static grub_command_t cmd;
+
 
 GRUB_MOD_INIT(diskfilter)
 {
   grub_disk_dev_register (&grub_diskfilter_dev);
+  cmd = grub_register_command ("cryptocheck", grub_cmd_cryptocheck,
+                                N_("DEVICE"),
+                                N_("Check if a logical volume resides on encrypted disks."));
 }
 
 GRUB_MOD_FINI(diskfilter)
 {
   grub_disk_dev_unregister (&grub_diskfilter_dev);
+  if (cmd != NULL)
+    grub_unregister_command (cmd);
   free_array ();
 }
-- 
2.49.0

openSUSE Build Service is sponsored by