Compare commits

1 Commits
main ... 1.1

125 changed files with 8145 additions and 20713 deletions

View File

@@ -1,325 +0,0 @@
From cb72de6caff51b79c0e5ef13dbd7a79754e3de35 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 17 Apr 2025 22:13:43 +0800
Subject: [PATCH] Fix PowerPC CAS reboot to evaluate menu context
The Client Architecture Support (CAS) negotiation between the firmware
and the operating system kernel can result in a reboot, allowing the
firmware to reinitialize itself to satisfy the request. In this case,
grub is expected to resume from the previous session by booting the
entry recorded in the boot-last-label OpenFirmware property.
However, the current implementation fails when a CAS-triggered reboot
originates from a menu entry within a submenu. For example, when booting
into a Btrfs snapshot. The root cause is that the menu context is not
evaluated. As a result, if the resumed boot entry relies on any
evaluated variables, the behavior becomes undefined.
This patch addresses the issue by storing both the entry ID and its
content in the boot-last-label property. The ID is used to descend into
the correct menu context, ensuring the entry is executed in the same
environment it was originally selected from.
A caret (^) is used to separate the entry ID from its content. The
resulting format in boot-last-label looks like this:
gnulinux-simple-2315b72a-17f2-4537-bc62-63da478ce1dd^setparams 'SLES 15-SP6'
set gfxpayload=text
insmod gzio
insmod part_gpt
insmod btrfs
search --no-floppy --fs-uuid --set=root 2315b72a-17f2- ...
echo 'Loading Linux 6.4.0-150600.23.25-default ...'
linux /boot/vmlinux-6.4.0-150600.23.25-default root=UUID= ...
echo 'Loading initial ramdisk ...'
initrd /boot/initrd-6.4.0-150600.23.25-default
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/normal/main.c | 60 ++++++++++++++++++++++--------
grub-core/normal/menu.c | 45 +++++++++++++++++++++-
grub-core/normal/menu_entry.c | 70 +++++++++++++++++++++++++++++++++--
grub-core/script/execute.c | 7 ----
4 files changed, 154 insertions(+), 28 deletions(-)
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -365,21 +365,6 @@
{
menu = read_config_file (config);
-#ifdef GRUB_MACHINE_IEEE1275
- int boot;
- boot = 0;
- char *script = NULL;
- char *dummy[1] = { NULL };
- if (! grub_ieee1275_cas_reboot (&script) && script)
- {
- if (! grub_script_execute_new_scope (script, 0, dummy))
- boot = 1;
- }
- grub_free (script);
- if (boot)
- grub_command_execute ("boot", 0, 0);
-#endif
-
/* Ignore any error. */
grub_errno = GRUB_ERR_NONE;
}
@@ -393,7 +378,50 @@
{
if (menu && menu->size)
{
+#ifdef GRUB_MACHINE_IEEE1275
+ char *entry_id = NULL;
+ char *delim;
+ const char *chosen;
+ if (grub_ieee1275_cas_reboot (&entry_id) != 0)
+ goto enter_menu;
+
+ if ((delim = grub_strchr (entry_id, '^')) != NULL)
+ *delim = '\0';
+ else
+ goto enter_menu;
+
+ chosen = grub_env_get ("chosen") ? : "";
+ if (! grub_strlen (chosen))
+ {
+ grub_env_set ("default", entry_id);
+ grub_env_set ("timeout", "0");
+ }
+ else
+ {
+ delim = entry_id;
+ while ((delim = grub_strchr (delim, '>')) != NULL)
+ {
+ if (delim[1] == '>')
+ {
+ delim += 2;
+ continue;
+ }
+ *delim = '\0';
+ if (grub_strcmp (chosen, entry_id) == 0)
+ {
+ grub_env_set ("default", delim + 1);
+ grub_env_set ("timeout", "0");
+ break;
+ }
+ *delim++ = '>';
+ }
+ if (delim == NULL)
+ grub_dprintf ("normal", "CAS triggered but find no match: %s\n", entry_id);
+ }
+ enter_menu:
+ grub_free (entry_id);
+#endif
grub_boot_time ("Entering menu");
grub_show_menu (menu, nested, 0);
if (nested)
--- a/grub-core/normal/menu.c
+++ b/grub-core/normal/menu.c
@@ -32,6 +32,9 @@
#include <grub/script_sh.h>
#include <grub/gfxterm.h>
#include <grub/dl.h>
+#ifdef GRUB_MACHINE_IEEE1275
+#include <grub/ieee1275/ieee1275.h>
+#endif
/* Time to delay after displaying an error message about a default/fallback
entry failing to boot. */
@@ -317,8 +320,31 @@
grub_env_set ("default", ptr + 1);
else
grub_env_unset ("default");
+#ifdef GRUB_MACHINE_IEEE1275
+ char *cas_entry_id = NULL;
+ char *cas_entry_source;
+ const char *id;
+ const char *sourcecode = entry->sourcecode;
+ id = grub_env_get ("chosen") ? : "";
+
+ if (grub_ieee1275_cas_reboot (&cas_entry_id) != 0)
+ goto exec_new_scope;
+
+ if ((cas_entry_source = grub_strchr (cas_entry_id, '^')) != NULL)
+ *cas_entry_source++ = '\0';
+ else
+ goto exec_new_scope;
+
+ if (grub_strcmp (id, cas_entry_id) == 0)
+ sourcecode = cas_entry_source;
+
+ exec_new_scope:
+ grub_script_execute_new_scope (sourcecode, entry->argc, entry->args);
+ grub_free (cas_entry_id);
+#else
grub_script_execute_new_scope (entry->sourcecode, entry->argc, entry->args);
+#endif
if (errs_before != grub_err_printed_errors)
grub_wait_after_message ();
@@ -326,8 +352,23 @@
errs_before = grub_err_printed_errors;
if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
- /* Implicit execution of boot, only if something is loaded. */
- grub_command_execute ("boot", 0, 0);
+ {
+#ifdef GRUB_MACHINE_IEEE1275
+ char *entry_data;
+
+ entry_data = grub_xasprintf ("%s^%s", id, sourcecode);
+ if (entry_data)
+ grub_ieee1275_set_boot_last_label (entry_data);
+ else
+ grub_print_error ();
+ grub_free (entry_data);
+#endif
+ /* Implicit execution of boot, only if something is loaded. */
+ grub_command_execute ("boot", 0, 0);
+#ifdef GRUB_MACHINE_IEEE1275
+ grub_ieee1275_set_boot_last_label ("");
+#endif
+ }
if (errs_before != grub_err_printed_errors)
grub_wait_after_message ();
--- a/grub-core/normal/menu_entry.c
+++ b/grub-core/normal/menu_entry.c
@@ -29,6 +29,9 @@
#include <grub/charset.h>
#include <grub/safemath.h>
#include <grub/crypttab.h>
+#ifdef GRUB_MACHINE_IEEE1275
+#include <grub/ieee1275/ieee1275.h>
+#endif
enum update_mode
{
@@ -78,6 +81,9 @@
int completion_shown;
int submenu;
+#ifdef GRUB_MACHINE_IEEE1275
+ char *id;
+#endif
struct per_term_screen *terms;
unsigned nterms;
@@ -578,6 +584,9 @@
grub_free (screen->killed_text);
grub_free (screen->lines);
grub_free (screen->terms);
+#ifdef GRUB_MACHINE_IEEE1275
+ grub_free (screen->id);
+#endif
grub_free (screen);
}
@@ -599,6 +608,11 @@
screen->lines = grub_malloc (sizeof (struct line));
if (! screen->lines)
goto fail;
+#ifdef GRUB_MACHINE_IEEE1275
+ screen->id = grub_strdup (entry->id);
+ if (! screen->id)
+ goto fail;
+#endif
/* Initialize the first line which must be always present. */
if (! init_line (screen, screen->lines))
@@ -1215,14 +1229,64 @@
script[size] = '\0';
}
grub_script_execute_new_scope (script, 0, dummy);
- grub_free (script);
if (errs_before != grub_err_printed_errors)
grub_wait_after_message ();
if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
- /* Implicit execution of boot, only if something is loaded. */
- grub_command_execute ("boot", 0, 0);
+ {
+#ifdef GRUB_MACHINE_IEEE1275
+ char *entry_data = NULL;
+ const char *chosen;
+ const char *ptr;
+ grub_size_t sz = 0;
+ char *buf = NULL;
+ char *optr;
+
+ chosen = grub_env_get ("chosen") ? : "";
+ for (ptr = screen->id; *ptr; ptr++)
+ sz += (*ptr == '>') ? 2 : 1;
+ sz++;
+ sz += grub_strlen (chosen);
+ sz++;
+ buf = grub_malloc (sz);
+ if (!buf)
+ {
+ grub_print_error ();
+ goto exec_boot;
+ }
+ optr = buf;
+ if (*chosen != '\0')
+ {
+ optr = grub_stpcpy (optr, chosen);
+ *optr++ = '>';
+ }
+ for (ptr = screen->id; *ptr; ptr++)
+ {
+ if (*ptr == '>')
+ *optr++ = '>';
+ *optr++ = *ptr;
+ }
+ *optr = 0;
+ entry_data = grub_xasprintf ("%s^%s", buf, script);
+ if (entry_data)
+ grub_ieee1275_set_boot_last_label (entry_data);
+ else
+ grub_print_error ();
+ grub_free (entry_data);
+ grub_free (buf);
+ grub_free (script);
+ script = NULL;
+ exec_boot:
+#endif
+ /* Implicit execution of boot, only if something is loaded. */
+ grub_command_execute ("boot", 0, 0);
+#ifdef GRUB_MACHINE_IEEE1275
+ grub_ieee1275_set_boot_last_label ("");
+#endif
+ }
+
+ grub_free (script);
if (screen->submenu)
{
--- a/grub-core/script/execute.c
+++ b/grub-core/script/execute.c
@@ -28,9 +28,6 @@
#include <grub/extcmd.h>
#include <grub/i18n.h>
#include <grub/verify.h>
-#ifdef GRUB_MACHINE_IEEE1275
-#include <grub/ieee1275/ieee1275.h>
-#endif
/* Max digits for a char is 3 (0xFF is 255), similarly for an int it
is sizeof (int) * 3, and one extra for a possible -ve sign. */
@@ -886,10 +883,6 @@
grub_err_t ret = 0;
struct grub_script *parsed_script;
-#ifdef GRUB_MACHINE_IEEE1275
- grub_ieee1275_set_boot_last_label (source);
-#endif
-
while (source)
{
char *line;

View File

@@ -1,7 +1,7 @@
From 7b6cdb8ff71e43f95de9cefc19a7949e924c2be9 Mon Sep 17 00:00:00 2001
From 27b3e919b9b51a4fedeb3a5aef19c87f0cd7b687 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 17 Nov 2023 12:32:59 +0800
Subject: [PATCH 1/2] Improve TPM key protection on boot interruptions
Subject: [PATCH] Improve TPM key protection on boot interruptions
The unattended boot process for full disk encryption relies on an
authorized TPM policy to ensure the system's integrity before releasing
@@ -25,21 +25,19 @@ By implementing these changes, this enhancement seeks to fortify the
protection of TPM keys, thereby ensuring a more robust defense against
potential unauthorized modifications during the boot process.
v2: erase cached credentials in grub_cryptodisk_erasesecrets
Signed-Off-by Michael Chang <mchang@suse.com>
---
grub-core/commands/crypttab.c | 38 ++++++++++++++++++++++++++---------
grub-core/disk/cryptodisk.c | 10 ++++++++-
grub-core/disk/cryptodisk.c | 8 +++++++-
grub-core/loader/linux.c | 6 +++---
grub-core/normal/main.c | 2 +-
grub-core/normal/menu.c | 7 +++++++
grub-core/normal/menu_entry.c | 2 +-
include/grub/crypttab.h | 18 ++++++++++-------
7 files changed, 61 insertions(+), 22 deletions(-)
7 files changed, 59 insertions(+), 22 deletions(-)
diff --git a/grub-core/commands/crypttab.c b/grub-core/commands/crypttab.c
index c2217ca980..9397bede9e 100644
index c2217ca98..9397bede9 100644
--- a/grub-core/commands/crypttab.c
+++ b/grub-core/commands/crypttab.c
@@ -9,17 +9,20 @@
@@ -127,7 +125,7 @@ index c2217ca980..9397bede9e 100644
static grub_command_t cmd;
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index cb87d337ac..5fd68f4549 100644
index aa0d43562..babc94868 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -1071,6 +1071,9 @@ grub_cryptodisk_scan_device_real (const char *name,
@@ -140,15 +138,17 @@ index cb87d337ac..5fd68f4549 100644
dev = grub_cryptodisk_get_by_source_disk (source);
@@ -1185,6 +1188,7 @@ grub_cryptodisk_scan_device_real (const char *name,
@@ -1183,6 +1186,9 @@ grub_cryptodisk_scan_device_real (const char *name,
ret = grub_cryptodisk_insert (dev, name, source);
if (ret != GRUB_ERR_NONE)
goto error;
#ifndef GRUB_UTIL
grub_cli_set_auth_needed ();
+#ifndef GRUB_UTIL
+ is_tpmkey = 1;
#endif
+#endif
goto cleanup;
}
@@ -1247,7 +1251,7 @@ grub_cryptodisk_scan_device_real (const char *name,
}
@@ -1244,7 +1250,7 @@ grub_cryptodisk_scan_device_real (const char *name,
#ifndef GRUB_UTIL
if (cargs->key_data && dev)
@@ -157,19 +157,8 @@ index cb87d337ac..5fd68f4549 100644
#endif
if (askpass)
{
@@ -1792,6 +1796,10 @@ grub_cryptodisk_erasesecrets (void)
grub_cryptodisk_t i;
grub_uint8_t *buf;
+#ifndef GRUB_UTIL
+ grub_cryptokey_discard ();
+#endif
+
buf = grub_zalloc (GRUB_CRYPTODISK_MAX_KEYLEN);
if (buf == NULL)
grub_fatal ("grub_cryptodisk_erasesecrets: cannot allocate memory");
diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c
index 9ee8f37907..e5e7929581 100644
index 9ee8f3790..e5e792958 100644
--- a/grub-core/loader/linux.c
+++ b/grub-core/loader/linux.c
@@ -226,13 +226,13 @@ grub_initrd_init (int argc, char *argv[],
@@ -198,10 +187,10 @@ index 9ee8f37907..e5e7929581 100644
{
grub_initrd_component (pk->key, pk->key_len, pk->path, initrd_ctx);
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index 320adbe337..343cdbae2c 100644
index a3f711d1d..1b426af69 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -599,7 +599,7 @@ grub_cmdline_run (int nested, int force_auth)
@@ -479,7 +479,7 @@ grub_cmdline_run (int nested, int force_auth)
return;
}
@@ -211,7 +200,7 @@ index 320adbe337..343cdbae2c 100644
while (1)
diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
index f243c5e0bd..897da6abac 100644
index 14b0ab1ec..1df2638d7 100644
--- a/grub-core/normal/menu.c
+++ b/grub-core/normal/menu.c
@@ -32,6 +32,7 @@
@@ -219,10 +208,10 @@ index f243c5e0bd..897da6abac 100644
#include <grub/gfxterm.h>
#include <grub/dl.h>
+#include <grub/crypttab.h>
#ifdef GRUB_MACHINE_IEEE1275
#include <grub/ieee1275/ieee1275.h>
#endif
@@ -769,6 +770,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot, int *notify_boot)
/* Time to delay after displaying an error message about a default/fallback
entry failing to boot. */
@@ -708,6 +709,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot, int *notify_boot)
if (grub_key_is_interrupt (key))
{
timeout = -1;
@@ -230,7 +219,7 @@ index f243c5e0bd..897da6abac 100644
break;
}
@@ -851,6 +853,11 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot, int *notify_boot)
@@ -790,6 +792,11 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot, int *notify_boot)
clear_timeout ();
}
@@ -243,10 +232,10 @@ index f243c5e0bd..897da6abac 100644
{
case GRUB_TERM_KEY_HOME:
diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c
index 38c958e657..bbd05e5638 100644
index 384ab9ce3..e5ba91ea4 100644
--- a/grub-core/normal/menu_entry.c
+++ b/grub-core/normal/menu_entry.c
@@ -1331,7 +1331,7 @@ grub_menu_entry_run (grub_menu_entry_t entry)
@@ -1263,7 +1263,7 @@ grub_menu_entry_run (grub_menu_entry_t entry)
return;
}
@@ -256,7 +245,7 @@ index 38c958e657..bbd05e5638 100644
screen = make_screen (entry);
if (! screen)
diff --git a/include/grub/crypttab.h b/include/grub/crypttab.h
index 113c53cfce..f86404686f 100644
index 113c53cfc..f86404686 100644
--- a/include/grub/crypttab.h
+++ b/include/grub/crypttab.h
@@ -4,21 +4,25 @@
@@ -293,5 +282,5 @@ index 113c53cfce..f86404686f 100644
+grub_cryptokey_tpmkey_discard (void);
#endif /* ! GRUB_CRYPTTAB_HEADER */
--
2.49.0
2.35.3

View File

@@ -1,188 +0,0 @@
From 8201e8e6fbb7ee992c430679705852ede91efcd6 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Tue, 20 Aug 2024 12:14:35 +0800
Subject: [PATCH] Streamline BLS and improve PCR stability
Introduce an environment variable enable_blscfg to allow looking for and
reading BLS (Boot Loader Specification) configurations right at startup,
rather than relying on the traditional grub.cfg. The benefit of this
approach is that it eliminates the layer of using an external grub.cfg
to piggyback the blscfg command. This change reduces the complexity of
managing command sequences, which would otherwise complicate the PCR
(Platform Configuration Register) policy. Managing a sequence of
commands can be difficult to maintain and ensure they remain in order
indefinitely.
Along the way, we can remove the external grub.cfg and have everything
embedded in memdisk and early embedded configurations. This approach
significantly improves the overall stability and makes it easier to
maintain a consistent and predictable PCR outcome.
The grubenv in the EFI boot directory can be used to override default
settings in the grubbls image, allowing for continued customization.
By introducing grubbls.efi for managing BLS configuration integration,
all necessary modules are built-in, and sensible default settings are
applied. This allows us to remove the following hardcoded command
sequences in blscfg:
load_video
set gfxpalyload=keep
insmod gzio
Since these are now part of the EFI image, this change effectively
simplifies the TPM event log, making it easier to handle with tools like
pcr-oracle or systemd-pcrlock.
Signed-Off-by: Michael Chang <mchang@suse.com>
---
grub-core/commands/blscfg.c | 4 ++
grub-core/normal/main.c | 82 +++++++++++++++++++++++++++++++++++++
include/grub/parser.h | 4 ++
3 files changed, 90 insertions(+)
diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c
index cbe2a289e..e08f35817 100644
--- a/grub-core/commands/blscfg.c
+++ b/grub-core/commands/blscfg.c
@@ -953,10 +953,14 @@ static void create_entry (struct bls_entry *entry)
const char *sdval = grub_env_get("save_default");
bool savedefault = ((NULL != sdval) && (grub_strcmp(sdval, "true") == 0));
+#ifdef GRUB_MACHINE_EFI
+ src = grub_xasprintf ("%slinux %s%s%s%s\n"
+#else
src = grub_xasprintf ("%sload_video\n"
"set gfxpayload=keep\n"
"insmod gzio\n"
"linux %s%s%s%s\n"
+#endif
"%s%s",
savedefault ? "savedefault\n" : "",
#ifdef GRUB_MACHINE_EMU
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index 03631f07a..8e58ced67 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -113,6 +113,65 @@ read_config_file_getline (char **line, int cont __attribute__ ((unused)),
return GRUB_ERR_NONE;
}
+#ifdef GRUB_MACHINE_EFI
+
+static void
+read_envblk_from_cmdpath (void)
+{
+ const char *cmdpath;
+ char *envfile = NULL;
+ int found = 0;
+
+ cmdpath = grub_env_get ("cmdpath");
+
+ if (cmdpath)
+ envfile = grub_xasprintf ("%s/grubenv", cmdpath);
+
+ if (envfile)
+ {
+ grub_file_t file;
+
+ file = grub_file_open (envfile, GRUB_FILE_TYPE_FS_SEARCH
+ | GRUB_FILE_TYPE_NO_DECOMPRESS | GRUB_FILE_TYPE_SKIP_SIGNATURE);
+ if (file)
+ {
+ found = 1;
+ grub_file_close (file);
+ }
+ }
+
+ if (found)
+ {
+ char *cfg;
+
+ cfg = grub_xasprintf ("load_env -f %s\n", envfile);
+ grub_parser_execute ((char *)cfg);
+ grub_free (cfg);
+ }
+
+ grub_free (envfile);
+}
+
+static grub_menu_t
+read_blscfg (void)
+{
+ grub_menu_t newmenu;
+ newmenu = grub_env_get_menu ();
+ if (! newmenu)
+ {
+ newmenu = grub_zalloc (sizeof (*newmenu));
+ if (! newmenu)
+ return 0;
+
+ grub_env_set_menu (newmenu);
+ }
+
+ grub_parser_execute ((char *)"blscfg\n");
+ return newmenu;
+}
+
+#endif
+
static grub_menu_t
read_config_file (const char *config)
{
@@ -282,6 +341,26 @@ grub_normal_execute (const char *config, int nested, int batch)
grub_boot_time ("Executing config file");
+#ifdef GRUB_MACHINE_EFI
+ const char *val;
+
+ val = grub_env_get ("enable_blscfg");
+ if (val && (val[0] == '1' || val[0] == 'y'))
+ read_envblk_from_cmdpath ();
+
+ /* Above would be used to override enable_blscfg, so verify again */
+ val = grub_env_get ("enable_blscfg");
+ if (val && (val[0] == '1' || val[0] == 'y'))
+ {
+ menu = read_blscfg ();
+ /* Ignore any error. */
+ grub_errno = GRUB_ERR_NONE;
+ /* unset to let configfile and source commands continue to work */
+ grub_env_unset ("enable_blscfg");
+ goto check_batch;
+ }
+#endif
+
if (config)
{
menu = read_config_file (config);
@@ -307,6 +386,9 @@ grub_normal_execute (const char *config, int nested, int batch)
grub_boot_time ("Executed config file");
+#ifdef GRUB_MACHINE_EFI
+ check_batch:
+#endif
if (! batch)
{
if (menu && menu->size)
diff --git a/include/grub/parser.h b/include/grub/parser.h
index 64f9f5cc2..9d702571a 100644
--- a/include/grub/parser.h
+++ b/include/grub/parser.h
@@ -86,7 +86,11 @@ struct grub_parser
};
typedef struct grub_parser *grub_parser_t;
+#ifdef GRUB_MACHINE_EFI
+grub_err_t EXPORT_FUNC (grub_parser_execute) (char *source);
+#else
grub_err_t grub_parser_execute (char *source);
+#endif
grub_err_t
grub_rescue_parse_line (char *line,
--
2.46.0

View File

@@ -1,34 +0,0 @@
From f85cc4bac3cfb787c5a47a8864a4565519dd01e9 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 6 Mar 2025 16:29:48 +0800
Subject: [PATCH] autofs: Ignore zfs not found
We put zfs modules in a separate package so they can be missing during
the file-system probe that kicks in automatic file-system module
loading. We ignore the error message for the missing zfs module, as that
is not an abnormal condition like others.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/normal/autofs.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/grub-core/normal/autofs.c b/grub-core/normal/autofs.c
index 7a7cf2b0f7..591b5fc8c3 100644
--- a/grub-core/normal/autofs.c
+++ b/grub-core/normal/autofs.c
@@ -42,6 +42,11 @@ autoload_fs_module (void)
break;
}
+ /* We put zfs in a separate package, so ignoring if it's not found */
+ if (grub_strcmp (p->name, "zfs") == 0 &&
+ grub_errno == GRUB_ERR_FILE_NOT_FOUND)
+ grub_errno = GRUB_ERR_NONE;
+
if (grub_errno)
grub_print_error ();
--
2.48.1

View File

@@ -1,82 +0,0 @@
From 552a2de0642bb95dd38fcdb7894ea7e07171975e Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 15 Jul 2024 11:43:07 +0800
Subject: [PATCH] bli: Fix crash in get_part_uuid
The get_part_uuid() function made an assumption that the target grub
device is a partition device and accessed device->disk->partition
without checking for NULL. There are four situations where this
assumption is problematic:
1. The device is a net device instead of a disk.
2. The device is an abstraction device, like LVM, RAID, or CRYPTO, which
is mostly logical "disk" ((lvmid/<UUID>) and so on).
3. Firmware RAID may present the ESP to grub as an EFI disk (hd0) device
if it is contained within a Linux software RAID.
4. When booting from a cdrom, the ESP is a vfat image indexed by the El
Torito boot catalog. The boot device is set to (cd0), corresponding
to the cdrom image mounted as an iso9660 filesystem.
As a result, get_part_uuid() could lead to a NULL pointer dereference
and trigger a synchronous exception during boot if the ESP falls into
one of these categories. This patch fixes the problem by adding the
necessary checks to handle cases where the ESP is not a partition
device.
Additionally, to avoid disrupting the boot process, this patch relaxes
the severity of the errors in this context to non-critical. Errors will
be logged, but they will not prevent the boot process from continuing.
Fixes: e0fa7dc84 (bli: Add a module for the Boot Loader Interface)
Signed-off-by: Michael Chang <mchang@suse.com>
Reviewed-By: Oliver Steffen <osteffen@redhat.com>
---
grub-core/commands/bli.c | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/grub-core/commands/bli.c b/grub-core/commands/bli.c
index e0d8a54f7..298c5f70a 100644
--- a/grub-core/commands/bli.c
+++ b/grub-core/commands/bli.c
@@ -48,6 +48,22 @@ get_part_uuid (const char *device_name, char **part_uuid)
if (device == NULL)
return grub_error (grub_errno, N_("cannot open device: %s"), device_name);
+ if (device->disk == NULL)
+ {
+ grub_dprintf ("bli", "%s is not a disk device, partuuid skipped\n", device_name);
+ *part_uuid = NULL;
+ grub_device_close (device);
+ return GRUB_ERR_NONE;
+ }
+
+ if (device->disk->partition == NULL)
+ {
+ grub_dprintf ("bli", "%s has no partition, partuuid skipped\n", device_name);
+ *part_uuid = NULL;
+ grub_device_close (device);
+ return GRUB_ERR_NONE;
+ }
+
disk = grub_disk_open (device->disk->name);
if (disk == NULL)
{
@@ -99,7 +115,7 @@ set_loader_device_part_uuid (void)
status = get_part_uuid (device_name, &part_uuid);
- if (status == GRUB_ERR_NONE)
+ if (status == GRUB_ERR_NONE && part_uuid)
status = grub_efi_set_variable_to_string ("LoaderDevicePartUUID", &bli_vendor_guid, part_uuid,
GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS |
GRUB_EFI_VARIABLE_RUNTIME_ACCESS);
@@ -117,4 +133,6 @@ GRUB_MOD_INIT (bli)
GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS |
GRUB_EFI_VARIABLE_RUNTIME_ACCESS);
set_loader_device_part_uuid ();
+ /* No error here is critical, other than being logged */
+ grub_print_error ();
}
--
2.46.0

View File

@@ -1,44 +0,0 @@
From e873743f4ed7841542dd7dc11a183cb136670382 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Wed, 19 Feb 2025 14:52:52 +0800
Subject: [PATCH] bls: Accept .conf suffix in setting default entry
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/normal/menu.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
index b11b28e0d9..dfdf0c7268 100644
--- a/grub-core/normal/menu.c
+++ b/grub-core/normal/menu.c
@@ -557,6 +557,26 @@ get_entry_number (grub_menu_t menu, const char *name)
entry = i;
break;
}
+
+ if (e->bls)
+ {
+ char *v, *ext;
+
+ if ((v = grub_strdup (val)) &&
+ (ext = grub_strrchr (v, '.')) &&
+ grub_strcmp (ext, ".conf") == 0)
+ {
+ *ext = '\0';
+ if (menuentry_eq (e->id, v))
+ {
+ entry = i;
+ grub_free (v);
+ break;
+ }
+ }
+ grub_free (v);
+ }
+
e = e->next;
/* Skip hidden entries */
--
2.48.1

View File

@@ -1,259 +0,0 @@
From 434b014e20ebb7930599fe30e09441af6b449fef Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 14 Apr 2025 08:52:26 +0800
Subject: [PATCH] blscfg: read fragments in order
The PCR 9 measurements of BLS entry files made by blscfg module are
performed in "readdir" order, which depends on the filesystem and is
therefore inherently unpredictable and unreliable. To make future PCR
values more predictable, the entries should be processed in a
deterministic order, such as alphabetically by filename.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/commands/blscfg.c | 164 ++++++++++++++++++++++--------------
1 file changed, 103 insertions(+), 61 deletions(-)
diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c
index 343c7ae989..10996722cf 100644
--- a/grub-core/commands/blscfg.c
+++ b/grub-core/commands/blscfg.c
@@ -55,6 +55,15 @@ struct keyval
static struct bls_entry *entries = NULL;
+struct bls_fragment
+{
+ struct bls_fragment *next;
+ struct bls_fragment *prev;
+ char *filename;
+};
+typedef struct bls_fragment *bls_fragment_t;
+static bls_fragment_t fragments;
+
#define FOR_BLS_ENTRIES(var) FOR_LIST_ELEMENTS (var, entries)
/* BLS appears to make paths relative to the filesystem that snippets are
@@ -466,69 +475,41 @@ struct read_entry_info {
grub_file_t file;
};
-static int read_entry (
- const char *filename,
- const struct grub_dirhook_info *dirhook_info UNUSED,
- void *data)
+static int
+read_entry (const char *filename)
{
grub_size_t m = 0, n, clip = 0;
int rc = 0;
char *p = NULL;
grub_file_t f = NULL;
struct bls_entry *entry;
- struct read_entry_info *info = (struct read_entry_info *)data;
-
- grub_dprintf ("blscfg", "filename: \"%s\"\n", filename);
+ char *slash;
- n = grub_strlen (filename);
+ grub_dprintf ("blscfg", "read_entry: \"%s\"\n", filename);
- if (info->file)
- {
- f = info->file;
- }
- else
- {
- if (filename[0] == '.')
- return 0;
+ f = grub_file_open (filename, GRUB_FILE_TYPE_CONFIG);
- if (n <= 5)
- return 0;
-
- if (grub_strcmp (filename + n - 5, ".conf") != 0)
- return 0;
-
- p = grub_xasprintf ("(%s)%s/%s", info->devid, info->dirname, filename);
-
- f = grub_file_open (p, GRUB_FILE_TYPE_CONFIG);
- if (!f)
- goto finish;
- }
+ if (!f)
+ goto finish;
entry = grub_zalloc (sizeof (*entry));
if (!entry)
goto finish;
- if (info->file)
- {
- char *slash;
+ /* Strip .conf */
+ n = grub_strlen (filename);
- if (n > 5 && !grub_strcmp (filename + n - 5, ".conf") == 0)
- clip = 5;
+ if (n > 5 && !grub_strcmp (filename + n - 5, ".conf") == 0)
+ clip = 5;
- slash = grub_strrchr (filename, '/');
- if (!slash)
- slash = grub_strrchr (filename, '\\');
+ slash = grub_strrchr (filename, '/');
+ if (!slash)
+ slash = grub_strrchr (filename, '\\');
- while (*slash == '/' || *slash == '\\')
- slash++;
+ while (*slash == '/' || *slash == '\\')
+ slash++;
- m = slash ? slash - filename : 0;
- }
- else
- {
- m = 0;
- clip = 5;
- }
+ m = slash ? slash - filename : 0;
n -= m;
entry->filename = grub_strndup(filename + m, n - clip);
@@ -573,10 +554,7 @@ static int read_entry (
if (rc < 0)
break;
}
-
- if (info->devid)
- entry->devid = grub_strdup(info->devid);
-
+ entry->devid = grub_file_get_device_name (filename);
if (!rc)
bls_add_entry(entry);
@@ -590,6 +568,73 @@ finish:
return 0;
}
+static int
+collect_fragments (
+ const char *filename,
+ const struct grub_dirhook_info *dirhook_info UNUSED,
+ void *data)
+{
+ grub_size_t n;
+ char *p = NULL;
+ struct read_entry_info *info = (struct read_entry_info *)data;
+ bls_fragment_t fragment, f, last;
+
+ if (filename[0] == '.')
+ return 0;
+
+ n = grub_strlen (filename);
+ if (n <= 5)
+ return 0;
+
+ if (grub_strcmp (filename + n - 5, ".conf") != 0)
+ return 0;
+
+ p = grub_xasprintf ("(%s)%s/%s", info->devid, info->dirname, filename);
+
+ fragment = grub_zalloc (sizeof (*fragment));
+ fragment->filename = grub_strdup (p);
+
+ if (!fragments)
+ {
+ fragments = fragment;
+ return 0;
+ }
+
+ FOR_LIST_ELEMENTS (f, fragments)
+ {
+ int rc;
+ rc = grub_strcmp(fragment->filename, f->filename);
+ if (!rc)
+ {
+ grub_free (fragment);
+ return 0;
+ }
+ if (rc < 0)
+ {
+ fragment->next = f;
+ if (f->prev)
+ f->prev->next = fragment;
+ fragment->prev = f->prev;
+ f->prev = fragment;
+ if (f == fragments)
+ {
+ fragments = fragment;
+ fragment->prev = NULL;
+ }
+ return 0;
+ }
+ last = f;
+ }
+
+ if (last)
+ {
+ last->next = fragment;
+ fragment->prev = last;
+ }
+
+ return 0;
+}
+
static grub_envblk_t saved_env = NULL;
static int UNUSED
@@ -1007,6 +1052,7 @@ static int find_entry (struct find_entry_info *info)
const char *blsdir = info->dirname;
int fallback = 0;
int r = 0;
+ bls_fragment_t fragment;
if (!blsdir) {
blsdir = grub_env_get ("blsdir");
@@ -1024,8 +1070,14 @@ static int find_entry (struct find_entry_info *info)
read_entry_info.devid = info->devid;
read_fallback:
- r = blsdir_fs->fs_dir (blsdir_dev, read_entry_info.dirname, read_entry,
+ r = blsdir_fs->fs_dir (blsdir_dev, read_entry_info.dirname, collect_fragments,
&read_entry_info);
+ FOR_LIST_ELEMENTS (fragment, fragments)
+ {
+ grub_dprintf ("blscfg", "read_entry: %s\n", fragment->filename);
+ read_entry (fragment->filename);
+ }
+
if (r != 0) {
grub_dprintf ("blscfg", "read_entry returned error\n");
grub_err_t e;
@@ -1060,21 +1112,11 @@ bls_load_entries (const char *path)
.fs = NULL,
.dirname = NULL,
};
- struct read_entry_info rei = {
- .devid = NULL,
- .dirname = NULL,
- };
if (path) {
len = grub_strlen (path);
if (grub_strcmp (path + len - 5, ".conf") == 0) {
- rei.file = grub_file_open (path, GRUB_FILE_TYPE_CONFIG);
- if (!rei.file)
- return grub_errno;
- /*
- * read_entry() closes the file
- */
- return read_entry(path, NULL, &rei);
+ return read_entry (path);
} else if (path[0] == '(') {
devid = path + 1;
--
2.49.0

View File

@@ -1,374 +0,0 @@
From c7dd3dd296592fef6166170121b54aafe634369f 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 1/2] 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(-)
diff --git a/docs/grub.texi b/docs/grub.texi
index 00c5fdc44..e89007920 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -6523,8 +6523,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 02df49206..07b6940d2 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 ae92050d7..56c6f7797 100644
--- a/grub-core/normal/menu_text.c
+++ b/grub-core/normal/menu_text.c
@@ -194,21 +194,24 @@ command-line or ESC to discard edits and return to the GRUB menu."),
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;
diff --git a/include/grub/kernel.h b/include/grub/kernel.h
index d3aafc884..9f3e2031f 100644
--- a/include/grub/kernel.h
+++ b/include/grub/kernel.h
@@ -31,7 +31,8 @@ enum
OBJ_TYPE_GPG_PUBKEY,
OBJ_TYPE_X509_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 38c6da73b..a4aac7b85 100644
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -72,6 +72,8 @@
{ "appended-signature-size", GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE,\
"SIZE", 0, N_("Add a note segment reserving SIZE bytes for an appended signature"), \
1}, \
+ { "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 }
@@ -136,7 +138,8 @@ enum grub_install_options {
GRUB_INSTALL_OPTIONS_DTB,
GRUB_INSTALL_OPTIONS_SBAT,
GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK,
- GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE
+ GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE,
+ GRUB_INSTALL_OPTIONS_DISABLE_CLI
};
extern char *grub_install_source_directory;
@@ -199,7 +202,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
const struct grub_install_image_target_desc *image_target,
int note, size_t appsig_size,
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 75fa03995..344dca664 100644
--- a/util/grub-install-common.c
+++ b/util/grub-install-common.c
@@ -469,6 +469,7 @@ static char **x509keys;
static size_t nx509keys;
static grub_compression_t compression;
static size_t appsig_size;
+static int disable_cli;
int
grub_install_parse (int key, char *arg)
@@ -514,6 +515,9 @@ grub_install_parse (int key, char *arg)
* (nx509keys + 1));
x509keys[nx509keys++] = xstrdup (arg);
return 1;
+ case GRUB_INSTALL_OPTIONS_DISABLE_CLI:
+ disable_cli = 1;
+ return 1;
case GRUB_INSTALL_OPTIONS_VERBOSITY:
verbosity++;
@@ -707,12 +711,13 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
grub_util_info ("grub-mkimage --directory '%s' --prefix '%s' --output '%s'"
" --format '%s' --compression '%s'"
- " --appended-signature-size %zu%s%s%s\n",
+ " --appended-signature-size %zu%s%s%s%s\n",
dir, prefix, outname,
mkimage_target, compnames[compression],
appsig_size,
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);
@@ -724,7 +729,7 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
pubkeys, npubkeys, x509keys, nx509keys,
config_path, tgt,
note, appsig_size, 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 7d61ef3ea..351a5e430 100644
--- a/util/grub-mkimage.c
+++ b/util/grub-mkimage.c
@@ -84,6 +84,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},
{"appended-signature-size", 'S', N_("SIZE"), 0, N_("Add a note segment reserving SIZE bytes for an appended signature"), 0},
{ 0, 0, 0, 0, 0, 0 }
@@ -133,6 +134,7 @@ struct arguments
int note;
int disable_shim_lock;
size_t appsig_size;
+ int disable_cli;
const struct grub_install_image_target_desc *image_target;
grub_compression_t comp;
};
@@ -259,6 +261,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;
@@ -347,7 +353,8 @@ main (int argc, char *argv[])
arguments.image_target, arguments.note,
arguments.appsig_size,
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 0737935fd..d6cc13475 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -889,7 +889,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
const struct grub_install_image_target_desc *image_target,
int note, size_t appsig_size, grub_compression_t comp,
const char *dtb_path, const char *sbat_path,
- int disable_shim_lock)
+ int disable_shim_lock,
+ int disable_cli)
{
char *kernel_img, *core_img;
size_t total_module_size, core_size;
@@ -964,6 +965,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);
@@ -1130,6 +1134,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.46.0

View File

@@ -1,153 +0,0 @@
From 386b59ddb42fa3f86ddfe557113b25c8fa16f88c Mon Sep 17 00:00:00 2001
From: Forest <forestix@nom.one>
Date: Mon, 6 May 2024 17:07:30 -0700
Subject: [PATCH] disk/cryptodisk: Allow user to retry failed passphrase
Give the user a chance to re-enter their cryptodisk passphrase after a typo,
rather than immediately failing (and likely dumping them into a GRUB shell).
By default, we allow 3 tries before giving up. A value in the
cryptodisk_passphrase_tries environment variable will override this default.
The user can give up early by entering an empty passphrase, just as they
could before this patch.
Signed-off-by: Forest <forestix@nom.one>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
docs/grub.texi | 9 +++++
grub-core/disk/cryptodisk.c | 71 ++++++++++++++++++++++++++++---------
2 files changed, 64 insertions(+), 16 deletions(-)
Index: grub-2.12/docs/grub.texi
===================================================================
--- grub-2.12.orig/docs/grub.texi
+++ grub-2.12/docs/grub.texi
@@ -3278,6 +3278,7 @@ These variables have special meaning to
* color_normal::
* config_directory::
* config_file::
+* cryptodisk_passphrase_tries::
* debug::
* default::
* fallback::
@@ -3450,6 +3451,14 @@ processed by commands @command{configfil
(@pxref{normal}). It is restored to the previous value when command completes.
+@node cryptodisk_passphrase_tries
+@subsection cryptodisk_passphrase_tries
+
+When prompting the user for a cryptodisk passphrase, allow this many attempts
+before giving up. Defaults to @samp{3} if unset or set to an invalid value.
+(The user can give up early by entering an empty passphrase.)
+
+
@node debug
@subsection debug
Index: grub-2.12/grub-core/disk/cryptodisk.c
===================================================================
--- grub-2.12.orig/grub-core/disk/cryptodisk.c
+++ grub-2.12/grub-core/disk/cryptodisk.c
@@ -17,6 +17,7 @@
*/
#include <grub/cryptodisk.h>
+#include <grub/env.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/dl.h>
@@ -1202,37 +1203,76 @@ grub_cryptodisk_scan_device_real (const
grub_free (part);
}
- if (!cargs->key_len)
+ if (cargs->key_len)
{
+ ret = cr->recover_key (source, dev, cargs);
+ if (ret != GRUB_ERR_NONE)
+ goto error;
+ }
+ else
+ {
+ /* Get the passphrase from the user, if no key data. */
+ unsigned long tries = 3;
+ const char *tries_env;
+
if (grub_errno)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
- /* Get the passphrase from the user, if no key data. */
askpass = 1;
- part = grub_partition_get_name (source->partition);
- grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
- source->partition != NULL ? "," : "",
- part != NULL ? part : N_("UNKNOWN"), dev->uuid);
- grub_free (part);
-
cargs->key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE);
if (cargs->key_data == NULL)
goto error;
- if (!grub_password_get ((char *) cargs->key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE))
+ tries_env = grub_env_get ("cryptodisk_passphrase_tries");
+ if (tries_env != NULL && tries_env[0] != '\0')
{
- grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied");
- goto error;
+ unsigned long tries_env_val;
+ const char *p;
+
+ tries_env_val = grub_strtoul (tries_env, &p, 0);
+ if (*p == '\0' && tries_env_val != ~0UL)
+ tries = tries_env_val;
+ else
+ grub_printf_ (N_("Invalid cryptodisk_passphrase_tries value `%s'. Defaulting to %lu.\n"),
+ tries_env,
+ tries);
}
- cargs->key_len = grub_strlen ((char *) cargs->key_data);
- }
- ret = cr->recover_key (source, dev, cargs);
- if (ret != GRUB_ERR_NONE)
- goto error;
+ for (; tries > 0; tries--)
+ {
+ part = grub_partition_get_name (source->partition);
+ grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
+ source->partition != NULL ? "," : "",
+ part != NULL ? part : N_("UNKNOWN"),
+ dev->uuid);
+ grub_free (part);
+
+ if (!grub_password_get ((char *) cargs->key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE))
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied");
+ goto error;
+ }
+ cargs->key_len = grub_strlen ((char *) cargs->key_data);
+
+ ret = cr->recover_key (source, dev, cargs);
+ if (ret == GRUB_ERR_NONE)
+ break;
+ if (ret != GRUB_ERR_ACCESS_DENIED || tries == 1)
+ goto error;
+ grub_puts_ (N_("Invalid passphrase."));
+
+ /*
+ * Since recover_key() calls a function that returns grub_errno,
+ * a leftover error value from a previously rejected passphrase
+ * will trigger a phantom failure. We therefore clear it before
+ * trying a new passphrase.
+ */
+ grub_errno = GRUB_ERR_NONE;
+ }
+ }
ret = grub_cryptodisk_insert (dev, name, source);
if (ret != GRUB_ERR_NONE)

View File

@@ -1,55 +0,0 @@
From 8b9234c7e482edd49a9b3377da8e48fbd54aab28 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Tue, 24 Sep 2024 18:59:34 +0800
Subject: [PATCH] efinet: Skip virtual VLAN devices during card enumeration
Similar to the fix in commit "c52ae4057 efinet: skip virtual IPv4 and
IPv6 devices during card enumeration", the UEFI PXE driver creates
additional VLAN child devices when a VLAN ID is configured on a network
interface associated with a physical NIC. These virtual VLAN devices
must be skipped during card enumeration to ensure that the subsequent
SNP exclusive open operation targets the correct physical card
instances, otherwise packet transfer would fail.
Example device path with VLAN nodes:
/MAC(123456789ABC,0x1)/Vlan(20)/IPv4(0.0.0.0,0x0,DHCP,0.0.0.0,0.0.0.0,0.0.0.0)
Signed-Off-by: Michael Chang <mchang@suse.com>
---
grub-core/net/drivers/efi/efinet.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
index 720b5d0e1..3d0bf34fa 100644
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -280,7 +280,8 @@ grub_efinet_findcards (void)
|| GRUB_EFI_DEVICE_PATH_SUBTYPE (child) == GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE)
&& parent
&& GRUB_EFI_DEVICE_PATH_TYPE (parent) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
- && GRUB_EFI_DEVICE_PATH_SUBTYPE (parent) == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE)
+ && (GRUB_EFI_DEVICE_PATH_SUBTYPE (parent) == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE
+ || GRUB_EFI_DEVICE_PATH_SUBTYPE (parent) == GRUB_EFI_VLAN_DEVICE_PATH_SUBTYPE))
continue;
net = grub_efi_open_protocol (*handle, &net_io_guid,
@@ -810,6 +811,15 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
dup_ldp->length = sizeof (*dup_ldp);
+
+ dup_ldp = grub_efi_find_last_device_path (dup_dp);
+ if (GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_VLAN_DEVICE_PATH_SUBTYPE)
+ {
+ dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+ dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+ dup_ldp->length = sizeof (*dup_ldp);
+ }
+
match = grub_efi_compare_device_paths (dup_dp, cdp) == 0;
grub_free (dup_dp);
if (!match)
--
2.46.1

View File

@@ -1,48 +0,0 @@
From 44f3c7978a8ac5cc94a5c885ac9e983ba2980f5e Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Wed, 29 May 2024 12:32:32 +0800
Subject: [PATCH] fix grub screen filled with post screen artifects
---
grub-core/normal/menu.c | 7 ++++---
grub-core/term/efi/console.c | 2 +-
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
index 1df2638d7..b11b28e0d 100644
--- a/grub-core/normal/menu.c
+++ b/grub-core/normal/menu.c
@@ -975,13 +975,14 @@ show_menu (grub_menu_t menu, int nested, int autobooted)
if (! e)
continue; /* Menu is empty. */
- grub_cls ();
-
if (auto_boot)
grub_menu_execute_with_fallback (menu, e, autobooted,
&execution_callback, &notify_boot);
else
- grub_menu_execute_entry (e, 0);
+ {
+ grub_cls ();
+ grub_menu_execute_entry (e, 0);
+ }
if (autobooted)
break;
}
diff --git a/grub-core/term/efi/console.c b/grub-core/term/efi/console.c
index bb587f39d..258b52737 100644
--- a/grub-core/term/efi/console.c
+++ b/grub-core/term/efi/console.c
@@ -432,7 +432,7 @@ grub_console_cls (struct grub_term_output *term __attribute__ ((unused)))
grub_efi_simple_text_output_interface_t *o;
grub_efi_int32_t orig_attr;
- if (grub_efi_is_finished || text_mode != GRUB_TEXT_MODE_AVAILABLE)
+ if (grub_prepare_for_text_output (term) != GRUB_ERR_NONE)
return;
o = grub_efi_system_table->con_out;
--
2.45.1

View File

@@ -1,65 +0,0 @@
From 7a8d9a29358fbe9eb5dcc70e63c417c4f3cd5068 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <djwong@kernel.org>
Date: Mon, 3 Feb 2025 15:41:22 -0800
Subject: [PATCH 1/3] fs/xfs: Add new superblock features added in Linux
6.12/6.13
The Linux port of XFS added a few new features in 2024. The existing
GRUB driver doesn't attempt to read or write any of the new metadata,
so, all three can be added to the incompat allowlist.
On the occasion align XFS_SB_FEAT_INCOMPAT_NREXT64 value.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/xfs.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
index c17e54e447..e3a69fe498 100644
--- a/grub-core/fs/xfs.c
+++ b/grub-core/fs/xfs.c
@@ -88,7 +88,10 @@ GRUB_MOD_LICENSE ("GPLv3+");
#define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */
#define XFS_SB_FEAT_INCOMPAT_BIGTIME (1 << 3) /* large timestamps */
#define XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR (1 << 4) /* needs xfs_repair */
-#define XFS_SB_FEAT_INCOMPAT_NREXT64 (1 << 5) /* large extent counters */
+#define XFS_SB_FEAT_INCOMPAT_NREXT64 (1 << 5) /* large extent counters */
+#define XFS_SB_FEAT_INCOMPAT_EXCHRANGE (1 << 6) /* exchangerange supported */
+#define XFS_SB_FEAT_INCOMPAT_PARENT (1 << 7) /* parent pointers */
+#define XFS_SB_FEAT_INCOMPAT_METADIR (1 << 8) /* metadata dir tree */
/*
* Directory entries with ftype are explicitly handled by GRUB code.
@@ -98,6 +101,15 @@ GRUB_MOD_LICENSE ("GPLv3+");
*
* We do not currently verify metadata UUID, so it is safe to read filesystems
* with the XFS_SB_FEAT_INCOMPAT_META_UUID feature.
+ *
+ * We do not currently replay the log, so it is safe to read filesystems
+ * with the XFS_SB_FEAT_INCOMPAT_EXCHRANGE feature.
+ *
+ * We do not currently read directory parent pointers, so it is safe to read
+ * filesystems with the XFS_SB_FEAT_INCOMPAT_PARENT feature.
+ *
+ * We do not currently look at realtime or quota metadata, so it is safe to
+ * read filesystems with the XFS_SB_FEAT_INCOMPAT_METADIR feature.
*/
#define XFS_SB_FEAT_INCOMPAT_SUPPORTED \
(XFS_SB_FEAT_INCOMPAT_FTYPE | \
@@ -105,7 +117,10 @@ GRUB_MOD_LICENSE ("GPLv3+");
XFS_SB_FEAT_INCOMPAT_META_UUID | \
XFS_SB_FEAT_INCOMPAT_BIGTIME | \
XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR | \
- XFS_SB_FEAT_INCOMPAT_NREXT64)
+ XFS_SB_FEAT_INCOMPAT_NREXT64 | \
+ XFS_SB_FEAT_INCOMPAT_EXCHRANGE | \
+ XFS_SB_FEAT_INCOMPAT_PARENT | \
+ XFS_SB_FEAT_INCOMPAT_METADIR)
struct grub_xfs_sblock
{
--
2.48.1

View File

@@ -0,0 +1,44 @@
From a59b58f6ae327a8f6949991cb5531db01e1ba14d Mon Sep 17 00:00:00 2001
From: Wen Xiong <wenxiong@linux.ibm.com>
Date: Tue, 7 Feb 2023 15:10:15 -0500
Subject: [PATCH] grub2: Can't setup a default boot device correctly on nvme
device in Beta3
The patch in Bug 200486 - SUSE1205666 - SLES15SP5 Beta1: Setup multiple dev path
for a nvmf boot device in grub2 caused the issue. That patch didn't consider
nvme devices carefully.
The new patch will check "nvme-of" instead of "nvme" to call
build_multi_boot_device().
Signed-off-by: Wen Xiong<wenxiong@linux.ibm.com>
---
grub-core/osdep/unix/platform.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/grub-core/osdep/unix/platform.c b/grub-core/osdep/unix/platform.c
index db8fa4b95..fb47c0ffa 100644
--- a/grub-core/osdep/unix/platform.c
+++ b/grub-core/osdep/unix/platform.c
@@ -288,11 +288,15 @@ grub_install_register_ieee1275 (int is_prep, const char *install_device,
}
*ptr = '\0';
}
- else if (grub_strstr(install_device, "nvme"))
- boot_device = build_multi_boot_device(install_device);
- else
+ else {
boot_device = get_ofpathname (install_device);
+ if (grub_strstr(boot_device, "nvme-of")) {
+ free (boot_device);
+ boot_device = build_multi_boot_device(install_device);
+ }
+ }
+
if (grub_util_exec ((const char * []){ "nvsetenv", "boot-device",
boot_device, NULL }))
{
--
2.39.1

View File

@@ -0,0 +1,164 @@
From 3e77c5494fd06f430588ae9c304fea370439d531 Mon Sep 17 00:00:00 2001
From: Wen Xiong <Wen Xiong>
Date: Thu, 15 Dec 2022 21:33:41 -0500
Subject: [PATCH] grub2: Set multiple device path for a nvmf boot device
nvmf support native multipath(ANA) by default.
The patch added the support for setting multiple
device path for a nvmf boot device.
localhost:~ grub2-install -v /dev/nvme1n1p1
...
...
...
grub2-install: info: executing nvsetenv boot-device /pci@800000020000132/fibre-channel@0,1/nvme-of/controller@5005076810193675,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec /pci@800000020000132/fibre-channel@0/nvme-of/controller@5005076810193675,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec /pci@800000020000132/fibre-channel@0/nvme-of/controller@50050768101935e5,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec /pci@800000020000132/fibre-channel@0,1/nvme-of/controller@50050768101935e5,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec.
Installation finished. No error reported.
localhost:~ # bootlist -m normal -o
nvme7n1
nvme5n1
nvme1n1
nvme4n1
localhost:~ # bootlist -m normal -r
/pci@800000020000132/fibre-channel@0,1/nvme-of/controller@5005076810193675,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec
/pci@800000020000132/fibre-channel@0/nvme-of/controller@5005076810193675,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec
/pci@800000020000132/fibre-channel@0/nvme-of/controller@50050768101935e5,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec
/pci@800000020000132/fibre-channel@0,1/nvme-of/controller@50050768101935e5,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec
Signed-off-by: Wen Xiong <wenxiong@linux.ibm.com>
---
grub-core/osdep/linux/ofpath.c | 6 ++---
grub-core/osdep/unix/platform.c | 48 +++++++++++++++++++++++++++++++++
include/grub/util/install.h | 3 +++
include/grub/util/ofpath.h | 9 +++++++
4 files changed, 63 insertions(+), 3 deletions(-)
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -209,7 +209,7 @@
}
}
-static char *
+char *
xrealpath (const char *in)
{
char *out;
@@ -224,7 +224,7 @@
return out;
}
-static char *
+char *
block_device_get_sysfs_path_and_link(const char *devicenode)
{
char *rpath;
@@ -535,7 +535,7 @@
}
-static char *
+char *
nvme_get_syspath(const char *nvmedev)
{
char *sysfs_path, *controller_node;
--- a/grub-core/osdep/unix/platform.c
+++ b/grub-core/osdep/unix/platform.c
@@ -19,6 +19,7 @@
#include <config.h>
#include <grub/util/install.h>
+#include <grub/util/ofpath.h>
#include <grub/emu/hostdisk.h>
#include <grub/util/misc.h>
#include <grub/misc.h>
@@ -131,6 +132,51 @@
return rc;
}
+char *
+build_multi_boot_device(const char *install_device)
+{
+ char *sysfs_path;
+ char *nvme_ns;
+ unsigned int nsid;
+ char *ptr;
+ char *boot_device_string;
+ struct dirent *ep;
+ DIR *dp;
+
+ nvme_ns = strchr(install_device, 'n');
+ nsid = of_path_get_nvme_nsid(nvme_ns);
+ sysfs_path = nvme_get_syspath(nvme_ns);
+ strcat(sysfs_path, "/device");
+ sysfs_path = xrealpath(sysfs_path);
+
+ dp = opendir(sysfs_path);
+ ptr = boot_device_string = xmalloc (1000);
+
+ /* We cannot have a boot list with more than five entries */
+ while((ep = readdir(dp)) != NULL){
+ char *nvme_device;
+
+ if (grub_strstr(ep->d_name, "nvme")) {
+ nvme_device = xasprintf ("%s%s%x ",
+ get_ofpathname(ep->d_name),"/namespace@", nsid);
+ if ((strlen(boot_device_string) + strlen(nvme_device)) >= 200*5 - 1) {
+ grub_util_warn (_("More than five entries cannot be specified in the bootlist"));
+ free(nvme_device);
+ break;
+ }
+
+ strncpy(ptr, nvme_device, strlen(nvme_device));
+ ptr += strlen(nvme_device);
+ free(nvme_device);
+ }
+ }
+
+ *--ptr = '\0';
+ closedir(dp);
+
+ return boot_device_string;
+}
+
int
grub_install_register_efi (const grub_disk_t *efidir_grub_disk,
const char *efifile_path,
@@ -242,6 +288,8 @@
}
*ptr = '\0';
}
+ else if (grub_strstr(install_device, "nvme"))
+ boot_device = build_multi_boot_device(install_device);
else
boot_device = get_ofpathname (install_device);
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -241,6 +241,9 @@
const char *efi_distributor,
const char *force_disk);
+char *
+build_multi_boot_device(const char *install_device);
+
void
grub_install_register_ieee1275 (int is_prep, const char *install_device,
int partno, const char *relpath);
--- a/include/grub/util/ofpath.h
+++ b/include/grub/util/ofpath.h
@@ -32,4 +32,13 @@
char* of_find_fc_host(char* host_wwpn);
+char* nvme_get_syspath(const char *nvmedev);
+
+char* block_device_get_sysfs_path_and_link(const char *devicenode);
+
+char* xrealpath (const char *in);
+
+unsigned int of_path_get_nvme_nsid(const char* devname);
+
+
#endif /* ! GRUB_OFPATH_MACHINE_UTIL_HEADER */

View File

@@ -1,56 +0,0 @@
From 5025c64afc876d91d3947ce07bb59ffe9af7209d Mon Sep 17 00:00:00 2001
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Date: Tue, 25 Feb 2025 19:14:24 +0530
Subject: [PATCH 1/9] ieee1275: adding failure check condition on
/ibm,secure-boot
failure check condition is missing while finding device "/" and
get property "ibm,secure-boot". So, adding the failure check condition.
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
---
grub-core/kern/ieee1275/init.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
index f86543da0d..0e1cbf24c3 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -987,12 +987,20 @@ grub_get_ieee1275_secure_boot (void)
int rc;
grub_uint32_t is_sb;
- grub_ieee1275_finddevice ("/", &root);
-
- rc = grub_ieee1275_get_integer_property (root, "ibm,secure-boot", &is_sb,
- sizeof (is_sb), 0);
+ if (grub_ieee1275_finddevice ("/", &root))
+ {
+ grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't find / node");
+ return;
+ }
- /* ibm,secure-boot:
+ rc = grub_ieee1275_get_integer_property (root, "ibm,secure-boot", &is_sb, sizeof (is_sb), 0);
+ if (rc < 0)
+ {
+ grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't examine /ibm,secure-boot property");
+ return;
+ }
+ /*
+ * ibm,secure-boot:
* 0 - disabled
* 1 - audit
* 2 - enforce
@@ -1000,7 +1008,7 @@ grub_get_ieee1275_secure_boot (void)
*
* We only support enforce.
*/
- if (rc >= 0 && is_sb >= 2)
+ if (is_sb >= 2)
grub_lockdown ();
}
--
2.48.1

View File

@@ -1,220 +0,0 @@
From e56c40ade88270bec8b50680fe34bb358919057b Mon Sep 17 00:00:00 2001
From: Avnish Chouhan <avnish@linux.ibm.com>
Date: Mon, 19 May 2025 16:34:34 +0530
Subject: [PATCH] ieee1275: support added for multiple nvme bootpaths
This patch sets mupltiple NVMe boot-devices for more robust boot.
Scenario where NVMe multipaths are available, all the available bootpaths (Max 5)
will be added as the boot-device.
Signed-off-by: Avnish Chouhan <avnish@linux.ibm.com>
Link: https://lore.kernel.org/r/20250519110434.28686-1-avnish@linux.ibm.com
---
grub-core/osdep/linux/ofpath.c | 6 +-
grub-core/osdep/unix/platform.c | 114 +++++++++++++++++++++++++++++++-
include/grub/util/install.h | 3 +
include/grub/util/ofpath.h | 4 ++
4 files changed, 123 insertions(+), 4 deletions(-)
diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
index dd50d785dd..66a256b18b 100644
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -209,7 +209,7 @@ find_obppath (const char *sysfs_path_orig)
}
}
-static char *
+char *
xrealpath (const char *in)
{
char *out;
@@ -224,7 +224,7 @@ xrealpath (const char *in)
return out;
}
-static char *
+char *
block_device_get_sysfs_path_and_link(const char *devicenode)
{
char *rpath;
@@ -613,7 +613,7 @@ of_path_get_nvme_nsid (const char* devname)
return nsid;
}
-static char *
+char *
nvme_get_syspath (const char *nvmedev)
{
char *sysfs_path, *controller_node;
diff --git a/grub-core/osdep/unix/platform.c b/grub-core/osdep/unix/platform.c
index 1e2961e006..e8e28f3d4b 100644
--- a/grub-core/osdep/unix/platform.c
+++ b/grub-core/osdep/unix/platform.c
@@ -28,6 +28,8 @@
#include <dirent.h>
#include <string.h>
#include <errno.h>
+#include <grub/util/ofpath.h>
+#define BOOTDEV_BUFFER 1000
static char *
get_ofpathname (const char *dev)
@@ -203,6 +205,105 @@ grub_install_register_efi (const grub_disk_t *efidir_grub_disk,
return 0;
}
+
+char *
+add_multiple_nvme_bootdevices (const char *install_device)
+{
+ char *sysfs_path, *nvme_ns, *ptr, *non_splitter_path;
+ unsigned int nsid;
+ char *multipath_boot, *ofpath, *ext_dir;
+ struct dirent *ep, *splitter_ep;
+ DIR *dp, *splitter_dp;
+ char *cntl_id, *dirR1, *dirR2, *splitter_info_path;
+ int is_FC = 0, is_splitter = 0;
+
+ nvme_ns = grub_strstr (install_device, "nvme");
+ nsid = of_path_get_nvme_nsid (nvme_ns);
+ if (nsid == 0)
+ return NULL;
+
+ sysfs_path = nvme_get_syspath (nvme_ns);
+ ofpath = xasprintf ("%s",get_ofpathname (nvme_ns));
+
+ if (grub_strstr (ofpath, "fibre-channel"))
+ {
+ strcat (sysfs_path, "/device");
+ is_FC = 1;
+ }
+ else
+ {
+ strcat (sysfs_path, "/subsystem");
+ is_FC = 0;
+ }
+ if (is_FC == 0)
+ {
+ cntl_id = grub_strstr (nvme_ns, "e");
+ dirR1 = xasprintf ("nvme%c",cntl_id[1]);
+
+ splitter_info_path = xasprintf ("%s%s%s", "/sys/block/", nvme_ns, "/device");
+ splitter_dp = opendir (splitter_info_path);
+ if (!splitter_dp)
+ return NULL;
+
+ while ((splitter_ep = readdir (splitter_dp)) != NULL)
+ {
+ if (grub_strstr (splitter_ep->d_name, "nvme"))
+ {
+ if (grub_strstr (splitter_ep->d_name, dirR1))
+ continue;
+
+ ext_dir = grub_strstr (splitter_ep->d_name, "e");
+ if (!(grub_strstr (ext_dir, "n")))
+ {
+ dirR2 = xasprintf("%s", splitter_ep->d_name);
+ is_splitter = 1;
+ break;
+ }
+ }
+ }
+ closedir (splitter_dp);
+ }
+ sysfs_path = xrealpath (sysfs_path);
+ dp = opendir (sysfs_path);
+ if (!dp)
+ return NULL;
+
+ ptr = multipath_boot = xmalloc (BOOTDEV_BUFFER);
+ if (is_splitter == 0 && is_FC == 0)
+ {
+ non_splitter_path = xasprintf ("%s%s%x:1 ", get_ofpathname (dirR1), "/namespace@", nsid);
+ strncpy (ptr, non_splitter_path, strlen (non_splitter_path));
+ ptr += strlen (non_splitter_path);
+ free (non_splitter_path);
+ }
+ else
+ {
+ while ((ep = readdir (dp)) != NULL)
+ {
+ char *path;
+ if (grub_strstr (ep->d_name, "nvme"))
+ {
+ if (is_FC == 0 && !grub_strstr (ep->d_name, dirR1) && !grub_strstr (ep->d_name, dirR2))
+ continue;
+ path = xasprintf ("%s%s%x ", get_ofpathname (ep->d_name), "/namespace@", nsid);
+ if ((strlen (multipath_boot) + strlen (path)) > BOOTDEV_BUFFER)
+ {
+ grub_util_warn (_("Maximum five entries are allowed in the bootlist"));
+ free (path);
+ break;
+ }
+ strncpy (ptr, path, strlen (path));
+ ptr += strlen (path);
+ free (path);
+ }
+ }
+ }
+ *--ptr = '\0';
+ closedir (dp);
+
+ return multipath_boot;
+}
+
void
grub_install_register_ieee1275 (int is_prep, const char *install_device,
int partno, const char *relpath)
@@ -242,8 +343,19 @@ grub_install_register_ieee1275 (int is_prep, const char *install_device,
}
*ptr = '\0';
}
+ else if (grub_strstr (install_device, "nvme"))
+ {
+ boot_device = add_multiple_nvme_bootdevices (install_device);
+ }
else
- boot_device = get_ofpathname (install_device);
+ {
+ boot_device = get_ofpathname (install_device);
+ if (grub_strstr (boot_device, "nvme-of"))
+ {
+ free (boot_device);
+ boot_device = add_multiple_nvme_bootdevices (install_device);
+ }
+ }
if (grub_util_exec ((const char * []){ "nvsetenv", "boot-device",
boot_device, NULL }))
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
index 563cf68e94..2f220ed3aa 100644
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -223,6 +223,9 @@ grub_install_get_image_targets_string (void);
const char *
grub_util_get_target_dirname (const struct grub_install_image_target_desc *t);
+char *
+add_multiple_nvme_bootdevices (const char *install_device);
+
void
grub_install_create_envblk_file (const char *name);
diff --git a/include/grub/util/ofpath.h b/include/grub/util/ofpath.h
index 7ab377c7cc..7e75866853 100644
--- a/include/grub/util/ofpath.h
+++ b/include/grub/util/ofpath.h
@@ -30,5 +30,9 @@ int add_filename_to_pile (char *filename, struct ofpath_files_list_root* root);
void find_file (char* filename, char* directory, struct ofpath_files_list_root* root, int max_depth, int depth);
char* of_find_fc_host (char* host_wwpn);
void free_ofpath_files_list (struct ofpath_files_list_root* root);
+char* nvme_get_syspath (const char *nvmedev);
+char* block_device_get_sysfs_path_and_link (const char *devicenode);
+char* xrealpath (const char *in);
+unsigned int of_path_get_nvme_nsid (const char* devname);
#endif /* ! GRUB_OFPATH_MACHINE_UTIL_HEADER */
--
2.49.0

View File

@@ -1,122 +0,0 @@
From ba65f46ffd2952a3f69d85a4534b1e55291f080c Mon Sep 17 00:00:00 2001
From: Avnish Chouhan <avnish@linux.ibm.com>
Date: Thu, 23 May 2024 18:43:14 +0530
Subject: [PATCH] kern/ieee1275/init: Add IEEE 1275 Radix support for KVM on
Power
This patch adds support for Radix, Xive and Radix_gtse in Options
vector5 which is required for KVM LPARs. KVM LPARs ONLY support
Radix and not the Hash. Not enabling Radix on any PowerVM KVM LPARs
will result in boot failure.
Signed-off-by: Avnish Chouhan <avnish@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/kern/ieee1275/init.c | 63 +++++++++++++++++++++++++++++++++-
1 file changed, 62 insertions(+), 1 deletion(-)
diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
index bb800b275..8e08e5dd5 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -115,6 +115,16 @@ grub_addr_t grub_ieee1275_original_stack;
#define DRC_INFO 0x40
#define BYTE22 (DY_MEM_V2 | DRC_INFO)
+/* For ibm,arch-vec-5-platform-support. */
+#define XIVE_INDEX 0x17
+#define MMU_INDEX 0x18
+#define RADIX_GTSE_INDEX 0x1a
+#define RADIX_ENABLED 0x40
+#define XIVE_ENABLED 0x40
+#define HASH_ENABLED 0x00
+#define MAX_SUPPORTED 0xC0
+#define RADIX_GTSE_ENABLED 0x40
+
void
grub_exit (void)
{
@@ -740,6 +750,10 @@ struct option_vector5
grub_uint32_t platform_facilities;
grub_uint8_t sub_processors;
grub_uint8_t byte22;
+ grub_uint8_t xive;
+ grub_uint8_t mmu;
+ grub_uint8_t hpt_ext;
+ grub_uint8_t radix_gtse;
} GRUB_PACKED;
struct pvr_entry
@@ -778,6 +792,13 @@ grub_ieee1275_ibm_cas (void)
{
int rc;
grub_ieee1275_ihandle_t root;
+ grub_uint8_t ibm_arch_platform_support[8];
+ grub_ssize_t actual;
+ grub_uint8_t xive_support = 0;
+ grub_uint8_t mmu_support = 0;
+ grub_uint8_t radix_gtse_support = 0;
+ int i = 0;
+ int prop_len = 8;
struct cas_args
{
struct grub_ieee1275_common_hdr common;
@@ -786,6 +807,46 @@ grub_ieee1275_ibm_cas (void)
grub_ieee1275_cell_t cas_addr;
grub_ieee1275_cell_t result;
} args;
+
+ grub_ieee1275_get_integer_property (grub_ieee1275_chosen,
+ "ibm,arch-vec-5-platform-support",
+ (grub_uint32_t *) ibm_arch_platform_support,
+ sizeof (ibm_arch_platform_support),
+ &actual);
+
+ for (i = 0; i < prop_len; i++)
+ {
+ switch (ibm_arch_platform_support[i])
+ {
+ case XIVE_INDEX:
+ if (ibm_arch_platform_support[i + 1] & MAX_SUPPORTED)
+ xive_support = XIVE_ENABLED;
+ else
+ xive_support = 0;
+ break;
+
+ case MMU_INDEX:
+ if (ibm_arch_platform_support[i + 1] & MAX_SUPPORTED)
+ mmu_support = RADIX_ENABLED;
+ else
+ mmu_support = HASH_ENABLED;
+ break;
+
+ case RADIX_GTSE_INDEX:
+ if (mmu_support == RADIX_ENABLED)
+ radix_gtse_support = ibm_arch_platform_support[i + 1] & RADIX_GTSE_ENABLED;
+ else
+ radix_gtse_support = 0;
+ break;
+
+ default:
+ /* Ignoring the other indexes of ibm,arch-vec-5-platform-support. */
+ break;
+ }
+ /* Skipping the property value. */
+ i++;
+ }
+
struct cas_vector vector =
{
.pvr_list = { { 0x00000000, 0xffffffff } }, /* any processor */
@@ -802,7 +863,7 @@ grub_ieee1275_ibm_cas (void)
.vec4 = 0x0001, /* set required minimum capacity % to the lowest value */
.vec5_size = 1 + sizeof (struct option_vector5) - 2,
.vec5 = {
- 0, BYTE2, 0, CMO, ASSOCIATIVITY, BIN_OPTS, 0, 0, MAX_CPU, 0, 0, PLATFORM_FACILITIES, SUB_PROCESSORS, BYTE22
+ 0, BYTE2, 0, CMO, ASSOCIATIVITY, BIN_OPTS, 0, 0, MAX_CPU, 0, 0, PLATFORM_FACILITIES, SUB_PROCESSORS, BYTE22, xive_support, mmu_support, 0, radix_gtse_support
}
};
--
2.47.0

View File

@@ -1,66 +0,0 @@
From 56b221476d31310de485af26550c8651618832bb Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Tue, 29 Oct 2024 11:54:28 +0800
Subject: [PATCH] kern/main: Fix cmdpath in root directory
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The "cmdpath" environment variable is set at startup to the location
from which the grub image is loaded. It includes a device part and,
optionally, an absolute directory name if the grub image is booted as a
file in a local file-system directory, or in a remote server directory,
like TFTP.
This entire process relies on firmware to provide the correct device
path of the booted image.
We encountered an issue when the image is booted from the root
directory, where the absolute directory name "/" is discarded. This
makes it unclear whether the root path was missing in the firmware
provided device path or if it is simply the root directory. This
ambiguity can cause confusion in custom scripts, potentially causing
them to interpret firmware data incorrectly and trigger unintended
fallback measures.
This patch fixes the problem by properly assigning the "fwpath" returned
by "grub_machine_get_bootlocation()" to "cmdpath". The fix is based on
the fact that fwpath is NULL if the firmware didnt provide a path part
or an NUL character, "", if it represents the root directory. With this,
it becomes possible to clearly distinguish:
- cmdpath=(hd0,1) - Either the image is booted from the first (raw)
partition, or the firmware failed to provide the path part.
- cmdpath=(hd0,1)/ - The image is booted from the root directory in the
first partition.
As a side note, the fix is similar to [1], but without the renaming
part.
[1] https://mail.gnu.org/archive/html/grub-devel/2024-10/msg00155.html
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/kern/main.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
index ef3b3756d..f9ab12c74 100644
--- a/grub-core/kern/main.c
+++ b/grub-core/kern/main.c
@@ -136,7 +136,11 @@ grub_set_prefix_and_root (void)
{
char *cmdpath;
- cmdpath = grub_xasprintf ("(%s)%s", fwdevice, fwpath ? : "");
+ if (fwpath && *fwpath == '\0')
+ cmdpath = grub_xasprintf ("(%s)/", fwdevice);
+ else
+ cmdpath = grub_xasprintf ("(%s)%s", fwdevice, fwpath ? : "");
+
if (cmdpath)
{
grub_env_set ("cmdpath", cmdpath);
--
2.47.0

View File

@@ -1,33 +0,0 @@
From 4f45e963ea913000fd8e3fe20f9afb3722073cea Mon Sep 17 00:00:00 2001
From: Maxim Suhanov <dfirblog@gmail.com>
Date: Thu, 8 May 2025 19:02:07 +0200
Subject: [PATCH 1/8] kern/rescue_reader: Block the rescue mode until the CLI
authentication
This further mitigates potential misuse of the CLI after the
root device has been successfully unlocked via TPM.
Fixes: CVE-2025-4382
Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/kern/rescue_reader.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/kern/rescue_reader.c b/grub-core/kern/rescue_reader.c
index 4259857ba9..a71ada8fb7 100644
--- a/grub-core/kern/rescue_reader.c
+++ b/grub-core/kern/rescue_reader.c
@@ -79,7 +79,7 @@ void __attribute__ ((noreturn))
grub_rescue_run (void)
{
/* Stall if the CLI has been disabled */
- if (grub_is_cli_disabled ())
+ if (grub_is_cli_disabled () || grub_is_cli_need_auth ())
{
grub_printf ("Rescue mode has been disabled...\n");
--
2.49.0

View File

@@ -1,7 +1,7 @@
From 1bc53f8fc980914132040670b85a010e094559ec Mon Sep 17 00:00:00 2001
From bf09618c47c6632b763960e265436294ab98dd43 Mon Sep 17 00:00:00 2001
From: Hernan Gatta <hegatta@linux.microsoft.com>
Date: Tue, 1 Feb 2022 05:02:53 -0800
Subject: [PATCH] key_protector: Add key protectors framework
Subject: [PATCH 1/5] key_protector: Add key protectors framework
A key protector encapsulates functionality to retrieve an unlocking key
for a fully-encrypted disk from a specific source. A key protector
@@ -19,18 +19,17 @@ Cc: Vladimir Serbinenko <phcoder@gmail.com>
Signed-off-by: Hernan Gatta <hegatta@linux.microsoft.com>
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/Makefile.am | 1 +
grub-core/Makefile.core.def | 5 +++
grub-core/disk/key_protector.c | 73 ++++++++++++++++++++++++++++++++++
include/grub/key_protector.h | 47 ++++++++++++++++++++++
4 files changed, 126 insertions(+)
grub-core/disk/key_protector.c | 78 ++++++++++++++++++++++++++++++++++
include/grub/key_protector.h | 46 ++++++++++++++++++++
4 files changed, 130 insertions(+)
create mode 100644 grub-core/disk/key_protector.c
create mode 100644 include/grub/key_protector.h
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index 1eda467e0..e50db8106 100644
index f18550c1c..9d3d5f519 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -90,6 +90,7 @@ endif
@@ -42,10 +41,10 @@ index 1eda467e0..e50db8106 100644
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index a38955e18..37f131ae2 100644
index bc893e547..4307b8e2d 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1282,6 +1282,11 @@ module = {
@@ -1302,6 +1302,11 @@ module = {
common = disk/raid6_recover.c;
};
@@ -59,14 +58,13 @@ index a38955e18..37f131ae2 100644
common = disk/scsi.c;
diff --git a/grub-core/disk/key_protector.c b/grub-core/disk/key_protector.c
new file mode 100644
index 000000000..0d146c1c0
index 000000000..b84afe1c7
--- /dev/null
+++ b/grub-core/disk/key_protector.c
@@ -0,0 +1,73 @@
@@ -0,0 +1,78 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2022 Microsoft Corporation
+ * Copyright (C) 2024 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
@@ -95,14 +93,16 @@ index 000000000..0d146c1c0
+grub_err_t
+grub_key_protector_register (struct grub_key_protector *protector)
+{
+ if (protector == NULL || protector->name == NULL || protector->name[0] == '\0')
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid key protector for registration");
+ if (protector == NULL || protector->name == NULL || grub_strlen (protector->name) == 0)
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ if (grub_key_protectors != NULL &&
+ grub_named_list_find (GRUB_AS_NAMED_LIST (grub_key_protectors), protector->name) != NULL)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Key protector '%s' already registered", protector->name);
+ if (grub_key_protectors &&
+ grub_named_list_find (GRUB_AS_NAMED_LIST (grub_key_protectors),
+ protector->name))
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ grub_list_push (GRUB_AS_LIST_P (&grub_key_protectors), GRUB_AS_LIST (protector));
+ grub_list_push (GRUB_AS_LIST_P (&grub_key_protectors),
+ GRUB_AS_LIST (protector));
+
+ return GRUB_ERR_NONE;
+}
@@ -111,7 +111,7 @@ index 000000000..0d146c1c0
+grub_key_protector_unregister (struct grub_key_protector *protector)
+{
+ if (protector == NULL)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid key protector for unregistration");
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ grub_list_remove (GRUB_AS_LIST (protector));
+
@@ -125,27 +125,30 @@ index 000000000..0d146c1c0
+ struct grub_key_protector *kp = NULL;
+
+ if (grub_key_protectors == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "No key protector registered");
+ return GRUB_ERR_OUT_OF_RANGE;
+
+ if (protector == NULL || protector[0] == '\0')
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid key protector");
+ if (protector == NULL || grub_strlen (protector) == 0)
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ kp = grub_named_list_find (GRUB_AS_NAMED_LIST (grub_key_protectors), protector);
+ kp = grub_named_list_find (GRUB_AS_NAMED_LIST (grub_key_protectors),
+ protector);
+ if (kp == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "Key protector '%s' not found", protector);
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
+ N_("A key protector with name '%s' could not be found. "
+ "Is the name spelled correctly and is the "
+ "corresponding module loaded?"), protector);
+
+ return kp->recover_key (key, key_size);
+}
diff --git a/include/grub/key_protector.h b/include/grub/key_protector.h
new file mode 100644
index 000000000..00b15c13d
index 000000000..6e6a6fb24
--- /dev/null
+++ b/include/grub/key_protector.h
@@ -0,0 +1,47 @@
@@ -0,0 +1,46 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2022 Microsoft Corporation
+ * Copyright (C) 2024 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
@@ -190,5 +193,5 @@ index 000000000..00b15c13d
+
+#endif /* ! GRUB_PROTECTOR_HEADER */
--
2.43.0
2.35.3

View File

@@ -1,68 +0,0 @@
From f0a61161f74f9855af84778261338224d926a61f Mon Sep 17 00:00:00 2001
From: B Horn <b@horn.uk>
Date: Sat, 15 Jun 2024 02:33:08 +0100
Subject: [PATCH 01/20] misc: Implement grub_strlcpy()
grub_strlcpy() acts the same way as strlcpy() does on most *NIX,
returning the length of src and ensuring dest is always NUL
terminated except when size is 0.
Signed-off-by: B Horn <b@horn.uk>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
include/grub/misc.h | 39 +++++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/include/grub/misc.h b/include/grub/misc.h
index 6e94d18f5a..e087e7b3e8 100644
--- a/include/grub/misc.h
+++ b/include/grub/misc.h
@@ -64,6 +64,45 @@ grub_stpcpy (char *dest, const char *src)
return d - 1;
}
+static inline grub_size_t
+grub_strlcpy (char *dest, const char *src, grub_size_t size)
+{
+ char *d = dest;
+ grub_size_t res = 0;
+ /*
+ * We do not subtract one from size here to avoid dealing with underflowing
+ * the value, which is why to_copy is always checked to be greater than one
+ * throughout this function.
+ */
+ grub_size_t to_copy = size;
+
+ /* Copy size - 1 bytes to dest. */
+ if (to_copy > 1)
+ while ((*d++ = *src++) != '\0' && ++res && --to_copy > 1)
+ ;
+
+ /*
+ * NUL terminate if size != 0. The previous step may have copied a NUL byte
+ * if it reached the end of the string, but we know dest[size - 1] must always
+ * be a NUL byte.
+ */
+ if (size != 0)
+ dest[size - 1] = '\0';
+
+ /* If there is still space in dest, but are here, we reached the end of src. */
+ if (to_copy > 1)
+ return res;
+
+ /*
+ * If we haven't reached the end of the string, iterate through to determine
+ * the strings total length.
+ */
+ while (*src++ != '\0' && ++res)
+ ;
+
+ return res;
+}
+
/* XXX: If grub_memmove is too slow, we must implement grub_memcpy. */
static inline void *
grub_memcpy (void *dest, const void *src, grub_size_t n)
--
2.48.1

View File

@@ -1,53 +0,0 @@
From a5208417eecf9313239aa0659d4b015f2a3ba33e Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 29 May 2025 11:47:08 +0800
Subject: [PATCH] mkconfig: Determine GRUB_DISTRIBUTOR from /etc/SUSE-brand
Starting with SLE 16, the $NAME field in /etc/os-release contains only
the unified value "SLE". To provide a more specific OS label for GRUB
menu entries, GRUB should instead use the value from /etc/SUSE-brand.
Signed-off-by: Michael Chang <mchang@suse.com>
---
util/grub-mkconfig.in | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index 31c4851aee..e11835ad69 100644
--- a/util/grub-mkconfig.in
+++ b/util/grub-mkconfig.in
@@ -226,6 +226,17 @@ GRUB_ACTUAL_DEFAULT="$GRUB_DEFAULT"
if [ "x${GRUB_ACTUAL_DEFAULT}" = "xsaved" ] ; then GRUB_ACTUAL_DEFAULT="`"${grub_editenv}" - list | sed -n '/^saved_entry=/ s,^saved_entry=,,p'`" ; fi
+# Use /etc/SUSE-brand for os label (bsc#1239169)
+grub_os_id () (
+ VERSION=""
+ GRUB_OS_ID=""
+ # Source /etc/SUSE-brand only if it defines GRUB_OS_ID
+ ! grep -q "^GRUB_OS_ID=" "${sysconfdir}/SUSE-brand" 2>/dev/null || source "${sysconfdir}/SUSE-brand"
+ # Check VERSION is 16.0 or newer before applying for backward compatibility
+ [ x"`echo -e "${VERSION}\n16.0" | sort -V | head -n1`" = x"16.0" ] || GRUB_OS_ID=""
+ echo "$GRUB_OS_ID"
+)
+
if [ x"${GRUB_DISTRIBUTOR}" = x ] ; then
for i in "${sysconfdir}/os-release" "/usr/lib/os-release" ; do
if [ -f "$i" ] ; then
@@ -233,7 +244,12 @@ if [ x"${GRUB_DISTRIBUTOR}" = x ] ; then
break
fi
done
- if [ x"${NAME}" != x ] && [ x"${VERSION}" != x ] ; then
+
+ OS_ID=`grub_os_id`
+
+ if [ x"${OS_ID}" != x ] ; then
+ GRUB_DISTRIBUTOR="${OS_ID}"
+ elif [ x"${NAME}" != x ] && [ x"${VERSION}" != x ] ; then
GRUB_DISTRIBUTOR="${NAME} ${VERSION}"
else
GRUB_DISTRIBUTOR="${NAME}"
--
2.49.0

View File

@@ -1,171 +0,0 @@
From 4b26a490def61786bfd5f66f0f68a33447dccb90 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 10 Feb 2025 18:20:28 +0800
Subject: [PATCH] ofpath: Add error check in NVMEoF device translation
Signed-Off-by: Michael Chang <mchang@suse.com>
---
grub-core/osdep/linux/ofpath.c | 95 ++++++++++++++++++++++++----------
1 file changed, 69 insertions(+), 26 deletions(-)
diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
index 66a256b18b..4b920ddc20 100644
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -536,52 +536,90 @@ of_path_get_nvmeof_adapter_info (char* sysfs_path,
}
snprintf (buf, 512, "%s/subsysnqn", sysfs_path);
- fp = fopen (buf, "r");
- fscanf (fp, "%s", nvmeof_info->nqn);
+ if (! (fp = fopen (buf, "r")) ||
+ fscanf (fp, "%s", nvmeof_info->nqn) != 1)
+ {
+ if (fp)
+ fclose (fp);
+ free (nvmeof_info->host_wwpn);
+ free (nvmeof_info->target_wwpn);
+ free (nvmeof_info->nqn);
+ free (buf);
+ return -1;
+ }
fclose (fp);
snprintf (buf, 512, "%s/cntlid", sysfs_path);
- fp = fopen (buf, "r");
- fscanf (fp, "%u", &(nvmeof_info->cntlid));
+ if (! (fp = fopen (buf, "r")) ||
+ fscanf (fp, "%u", &(nvmeof_info->cntlid)) != 1)
+ {
+ if (fp)
+ fclose (fp);
+ free (nvmeof_info->host_wwpn);
+ free (nvmeof_info->target_wwpn);
+ free (nvmeof_info->nqn);
+ free (buf);
+ return -1;
+ }
fclose (fp);
snprintf (buf, 512, "%s/address", sysfs_path);
- fp = fopen (buf, "r");
- buf2 = malloc (sizeof (char) * 512);
-
- if (!buf2)
+ buf2 = NULL;
+ fp = NULL;
+ if (! (buf2 = malloc (sizeof (char) * 512)) ||
+ ! (fp = fopen (buf, "r")) ||
+ fscanf (fp, "%s", buf2) != 1)
{
+ if (fp)
+ fclose (fp);
free (nvmeof_info->host_wwpn);
free (nvmeof_info->target_wwpn);
free (nvmeof_info->nqn);
free (buf);
+ free (buf2);
return -1;
}
-
- fscanf (fp, "%s", buf2);
fclose (fp);
- buf3 = strrchr (buf2, '-') + 1;
- grub_memcpy (nvmeof_info->host_wwpn, buf3, 256);
- buf3=strchr (buf2, '-') + 1;
- buf3=strchr (buf3, '-') + 1;
- buf3=strchr (buf3, 'x') + 1;
- grub_memcpy (nvmeof_info->target_wwpn, buf3, 256);
+ if (! (buf3 = strrchr (buf2, '-')))
+ {
+ free (nvmeof_info->host_wwpn);
+ free (nvmeof_info->target_wwpn);
+ free (nvmeof_info->nqn);
+ free (buf);
+ free (buf2);
+ return -1;
+ }
+ grub_memcpy (nvmeof_info->host_wwpn, buf3 + 1, 256);
+ if (! (buf3 = strchr (buf2, '-')) ||
+ ! (buf3 = strchr (buf3 + 1, '-')) ||
+ ! (buf3 = strchr (buf3 + 1, 'x')))
+ {
+ free (nvmeof_info->host_wwpn);
+ free (nvmeof_info->target_wwpn);
+ free (nvmeof_info->nqn);
+ free (buf);
+ free (buf2);
+ return -1;
+ }
+ grub_memcpy (nvmeof_info->target_wwpn, buf3 + 1, 256);
buf3 = strchr (nvmeof_info->target_wwpn, ',');
- *buf3 = '\0';
+ if (buf3)
+ *buf3 = '\0';
free (buf);
free (buf2);
return 0;
}
-#define MAX_NVME_NSID_DIGITS 6
+#define OFPATH_MAX_UINT_HEX_DIGITS 8
+#define OFPATH_MAX_INT_DIGITS 10
static char *
of_path_get_nvme_controller_name_node (const char* devname)
{
char *controller_node, *end;
- controller_node = strdup (devname);
+ controller_node = xstrdup (devname);
end = grub_strchr (controller_node + 1, 'n');
if (end != NULL)
{
@@ -616,15 +654,20 @@ of_path_get_nvme_nsid (const char* devname)
char *
nvme_get_syspath (const char *nvmedev)
{
- char *sysfs_path, *controller_node;
+ char *sysfs_path;
sysfs_path = block_device_get_sysfs_path_and_link (nvmedev);
if (strstr (sysfs_path, "nvme-subsystem"))
{
- controller_node = of_path_get_nvme_controller_name_node (nvmedev);
- strcat (sysfs_path, "/");
- strcat (sysfs_path, controller_node);
- sysfs_path = xrealpath (sysfs_path);
+ char *controller_node = of_path_get_nvme_controller_name_node (nvmedev);
+ char *buf = xmalloc (strlen (sysfs_path) + strlen ("/") + strlen (controller_node) + 1);
+ strcpy (buf, sysfs_path);
+ strcat (buf, "/");
+ strcat (buf, controller_node);
+ free (sysfs_path);
+ free (controller_node);
+ sysfs_path = xrealpath (buf);
+ free (buf);
}
return sysfs_path;
@@ -693,7 +736,7 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
unsigned int nsid = of_path_get_nvme_nsid (nvmedev);
if (nsid)
{
- snprintf (disk+chars_written, sizeof("/namespace@") + MAX_NVME_NSID_DIGITS,
+ snprintf (disk+chars_written, sizeof("/namespace@") + OFPATH_MAX_UINT_HEX_DIGITS + OFPATH_MAX_INT_DIGITS,
"/namespace@%x:%d", nsid, part);
}
free (nvmeof_info);
@@ -734,7 +777,7 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
unsigned int nsid = of_path_get_nvme_nsid (device);
if (nsid)
{
- snprintf (disk+chars_written,sizeof("/namespace@") + sizeof(char) * MAX_NVME_NSID_DIGITS,
+ snprintf (disk+chars_written,sizeof("/namespace@") + sizeof(char) * OFPATH_MAX_UINT_HEX_DIGITS,
"/namespace@%x", nsid);
}
free (nvmeof_info);
--
2.48.1

View File

@@ -1,102 +0,0 @@
From 68a2663cc316d55c2670a639c8a4a2a43ffdb141 Mon Sep 17 00:00:00 2001
From: Avnish Chouhan <avnish@linux.ibm.com>
Date: Wed, 15 Jan 2025 17:46:05 +0530
Subject: [PATCH] powerpc: increase MIN RMA size for CAS negotiation
Change RMA size from 512 MB to 768 MB which will result
in more memory at boot time for PowerPC. When PowerPC LPAR use/uses vTPM,
Secure Boot or FADump, the 512 MB RMA memory is not sufficient for
booting. With this 512 MB RMA, GRUB2 run out of memory and unable to
load the necessary. Sometimes even usage of CDROM which requires more
memory for installation along with the options mentioned above troubles
the boot memory and result in boot failures. Increasing the RMA size
will resolves multiple out of memory issues observed in PowerPC.
Failure details (GRUB2 debugs):
kern/ieee1275/init.c:550: mm requested region of size 8513000, flags 1
kern/ieee1275/init.c:563: Cannot satisfy allocation and retain minimum runtime
space
kern/ieee1275/init.c:550: mm requested region of size 8513000, flags 0
kern/ieee1275/init.c:563: Cannot satisfy allocation and retain minimum runtime
space
kern/file.c:215: Closing `/ppc/ppc64/initrd.img' ...
kern/disk.c:297: Closing
`ieee1275//vdevice/v-scsi
@30000067/disk@8300000000000000'...
kern/disk.c:311: Closing
`ieee1275//vdevice/v-scsi
@30000067/disk@8300000000000000' succeeded.
kern/file.c:225: Closing `/ppc/ppc64/initrd.img' failed with 3.
kern/file.c:148: Opening `/ppc/ppc64/initrd.img' succeeded.
error: ../../grub-core/kern/mm.c:552:out of memory.
Signed-off-by: Avnish Chouhan <avnish@linux.ibm.com>
Link: https://lore.kernel.org/r/20250115121605.56049-1-avnish@linux.ibm.com
---
grub-core/kern/ieee1275/init.c | 33 +++++++++++++++++++++++++++++----
1 file changed, 29 insertions(+), 4 deletions(-)
diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
index 8e08e5dd5c..e0634603ef 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -855,7 +855,7 @@ grub_ieee1275_ibm_cas (void)
.vec1 = 0x80, /* ignore */
.vec2_size = 1 + sizeof (struct option_vector2) - 2,
.vec2 = {
- 0, 0, -1, -1, -1, -1, -1, 512, -1, 0, 48
+ 0, 0, -1, -1, -1, -1, -1, 768, -1, 0, 48
},
.vec3_size = 2 - 1,
.vec3 = 0x00e0, /* ask for FP + VMX + DFP but don't halt if unsatisfied */
@@ -892,6 +892,10 @@ grub_claim_heap (void)
{
grub_err_t err;
grub_uint32_t total = HEAP_MAX_SIZE;
+#if defined(__powerpc__)
+ grub_uint32_t ibm_ca_support_reboot;
+ grub_ssize_t actual;
+#endif
err = grub_ieee1275_total_mem (&rmo_top);
@@ -904,11 +908,32 @@ grub_claim_heap (void)
grub_mm_add_region_fn = grub_ieee1275_mm_add_region;
#if defined(__powerpc__)
+ /* Check if it's a CAS reboot with below property. If so, we will skip CAS call */
+ ibm_ca_support_reboot = 0;
+ if (grub_ieee1275_get_integer_property (grub_ieee1275_chosen,
+ "ibm,client-architecture-support-reboot",
+ &ibm_ca_support_reboot,
+ sizeof (ibm_ca_support_reboot),
+ &actual) >= 0)
+ grub_dprintf ("ieee1275", "ibm,client-architecture-support-reboot: %u\n",
+ ibm_ca_support_reboot);
+
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CAN_TRY_CAS_FOR_MORE_MEMORY))
{
- /* if we have an error, don't call CAS, just hope for the best */
- if (err == GRUB_ERR_NONE && rmo_top < (512 * 1024 * 1024))
- grub_ieee1275_ibm_cas ();
+ /*
+ * If we have an error or the reboot is detected as CAS reboot,
+ * don't call CAS, just hope for the best.
+ * Along with the above, if the rmo_top is 512 MB or above. We
+ * will skip the CAS call. Though if we call CAS, the rmo_top will
+ * be set to 768 MB via CAS Vector2. This condition is required to avoid the
+ * issue where the older Linux kernels are still using rmo_top as 512 MB.
+ * Calling CAS when rmo_top is less then 768 MB will result in a issue
+ * where we won't be able to boot to a newer kernel and continue to
+ * boot with older kernel having rmo_top as 512 MB.
+ */
+ if (!ibm_ca_support_reboot && err == GRUB_ERR_NONE
+ && rmo_top < (512 * 1024 * 1024))
+ grub_ieee1275_ibm_cas ();
}
#endif
--
2.48.1

View File

@@ -1,61 +0,0 @@
From e2ffbaf62f0a97caa1e4214be7ee71db0a49ad6c Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Tue, 14 Jan 2025 14:28:35 +0800
Subject: [PATCH] prep_loadenv: Measure the environment block into PCR 9
Since the firmware is not aware of the environment block in the PReP
partition, the measurement of PCR 4 does not include that block. To
close the gap, prep_loadenv now measures the block into PCR 9.
Signed-off-by: Gary Lin <glin@suse.com>
---
grub-core/commands/prep_loadenv.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/grub-core/commands/prep_loadenv.c b/grub-core/commands/prep_loadenv.c
index 109b7ca5a..5b8ade8db 100644
--- a/grub-core/commands/prep_loadenv.c
+++ b/grub-core/commands/prep_loadenv.c
@@ -11,6 +11,7 @@
#include <grub/i18n.h>
#include <grub/gpt_partition.h>
#include <regex.h>
+#include <grub/tpm.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -122,6 +123,7 @@ prep_read_envblk (const char *devname)
char *buf = NULL;
grub_device_t dev = NULL;
grub_envblk_t envblk = NULL;
+ grub_err_t err;
dev = grub_device_open (devname);
if (!dev)
@@ -140,6 +142,23 @@ prep_read_envblk (const char *devname)
if (grub_disk_read (dev->disk, dev->disk->partition->len - (GRUB_ENVBLK_PREP_SIZE >> GRUB_DISK_SECTOR_BITS), 0, GRUB_ENVBLK_PREP_SIZE, buf))
goto fail;
+ /*
+ * Measure the environment block in the PReP partition
+ * The firmware is not aware of this block, so the content of the environment
+ * block is not measured into PCR 4.
+ */
+ if (grub_tpm_present () == true)
+ {
+ err = grub_tpm_measure ((unsigned char*)buf, GRUB_ENVBLK_PREP_SIZE, GRUB_BINARY_PCR, "PReP envblk");
+ if (err != GRUB_ERR_NONE && grub_is_tpm_fail_fatal () == true)
+ {
+ grub_errno = err;
+ goto fail;
+ }
+ else
+ grub_errno = GRUB_ERR_NONE;
+ }
+
envblk = grub_envblk_open (buf, GRUB_ENVBLK_PREP_SIZE);
if (!envblk)
{
--
2.43.0

View File

@@ -1,71 +0,0 @@
From c6f690a50ab75edf06cd2a8d2100e9312a86decc Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Wed, 26 Feb 2025 16:35:14 +0800
Subject: [PATCH] s390x-emu: Pass through PAES cipher as AES
Protected AES (PAES) enhances AES encryption with hardware key
protection exclusively on IBM Z's s390x architecture.
This patch addresses issues in GRUB utilities that cannot handle
PAES-encrypted volumes due to a lack of native cipher support. The
solution works because, on s390x, grub-emu is used to boot the target
via kexec. As a Linux userspace program, grub-emu leverages kernel
support and bypasses the limitations of GRUB's built-in functionality.
We can pass through PAES as AES on Linux platforms since the underlying
cipher appears as plain AES from a userland application's perspective.
Additionally, GRUB's linux applications perform "cheat mount" that
doesn't attempt to open the LUKS container. Instead, they initialize the
cryptodisk structure using attributes from the LUKS header to obtain
necessary information like crypto-uuid.
Furthermore, root probing for Btrfs can be skipped to avoid issues with
unsupported devices, as grub-emu doesn't rely on GRUB's own
configurations for booting Btrfs. Instead, it operates entirely from a
Dracut initramfs.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/osdep/devmapper/getroot.c | 5 +++++
util/grub-install.c | 6 ++++--
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/grub-core/osdep/devmapper/getroot.c b/grub-core/osdep/devmapper/getroot.c
index 3b37336bc9..344df9a589 100644
--- a/grub-core/osdep/devmapper/getroot.c
+++ b/grub-core/osdep/devmapper/getroot.c
@@ -266,6 +266,11 @@ grub_util_pull_devmapper (const char *os_dev)
remaining -= seek_head - c + 1;
c = seek_head + 1;
+#if defined (__s390x__)
+ if (grub_strcasecmp (cipher, "paes") == 0)
+ grub_strcpy(cipher, "aes");
+#endif
+
/* Now, the cipher mode. */
seek_head = grub_memchr (c, ' ', remaining);
if (seek_head == NULL)
diff --git a/util/grub-install.c b/util/grub-install.c
index a187a9c63c..0ab0cf8fe7 100644
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -1108,11 +1108,13 @@ main (int argc, char *argv[])
char *t = grub_util_path_concat (2, "/", rootdir);
#ifdef __linux__
- if (!grub_can_guess_from_mountinfo (t))
+ if (!grub_can_guess_from_mountinfo (t) || platform == GRUB_INSTALL_PLATFORM_S390X_EMU)
{
free(t);
/* We can safely ignore the root probe here; whichever cannot be
- * reliably detected is irrelevant and of no interest */
+ * reliably detected is irrelevant and of no interest.
+ * Also the s390x-emu, this btrfs root detection can be omitted given
+ * it is not relevant to the capability of linux host system */
goto skip_root_probe;
}
#endif
--
2.48.1

View File

@@ -0,0 +1,60 @@
From 72a582b1c3954f9b917a4d687c95fc94faf551c6 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Wed, 24 Jan 2024 18:03:51 +0800
Subject: [PATCH] squash! ieee1275/ofpath: enable NVMeoF logical device
translation
Fixes build error on gcc-14:
[ 73s] In file included from ../grub-core/osdep/ofpath.c:2:
[ 73s] ../grub-core/osdep/linux/ofpath.c: In function 'of_find_fc_host':
[ 73s] ../grub-core/osdep/linux/ofpath.c:427:22: error: allocation of insufficient size '8' for type 'struct ofpath_files_list_root' with size '16' [-Werror=alloc-size]
[ 73s] 427 | portnames_file_list=malloc(sizeof(portnames_file_list));
[ 73s] | ^
[ 73s] ../grub-core/osdep/linux/ofpath.c: In function 'of_path_of_nvme':
[ 73s] ../grub-core/osdep/linux/ofpath.c:589:21: error: allocation of insufficient size '8' for type 'struct ofpath_nvmeof_info' with size '32' [-Werror=alloc-size]
[ 73s] 589 | nvmeof_info = malloc(sizeof(nvmeof_info));
[ 73s] | ^
[ 73s] ../grub-core/osdep/linux/ofpath.c:618:21: error: allocation of insufficient size '8' for type 'struct ofpath_nvmeof_info' with size '32' [-Werror=alloc-size]
[ 73s] 618 | nvmeof_info = malloc(sizeof(nvmeof_info));
[ 73s] | ^
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/osdep/linux/ofpath.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
index 7129099db..55ed7ddf2 100644
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -424,7 +424,7 @@ of_find_fc_host(char* host_wwpn){
struct ofpath_files_list_root* portnames_file_list;
- portnames_file_list=malloc(sizeof(portnames_file_list));
+ portnames_file_list=malloc(sizeof(*portnames_file_list));
portnames_file_list->items=0;
portnames_file_list->first=NULL;
@@ -586,7 +586,7 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
/* If is a NVMeoF */
if(strstr(sysfs_path,"nvme-fabrics")){
struct ofpath_nvmeof_info* nvmeof_info;
- nvmeof_info = malloc(sizeof(nvmeof_info));
+ nvmeof_info = malloc(sizeof(*nvmeof_info));
of_path_get_nvmeof_adapter_info(sysfs_path, nvmeof_info);
@@ -615,7 +615,7 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
sysfs_path = nvme_get_syspath (device);
if(strstr(sysfs_path,"nvme-fabrics")){
struct ofpath_nvmeof_info* nvmeof_info;
- nvmeof_info = malloc(sizeof(nvmeof_info));
+ nvmeof_info = malloc(sizeof(*nvmeof_info));
of_path_get_nvmeof_adapter_info(sysfs_path, nvmeof_info);
--
2.43.0

View File

@@ -1,67 +0,0 @@
From 0a8f0e75151067a8b7c09a6ffdfa9558aa040d3b Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 14 Jul 2025 17:59:20 +0800
Subject: [PATCH 1/4] test: Fix -f test on files over network
The "test -f ..." aka "if [ -f ... ]; " does not work for files over
network in both TFTP and HTTP and always evaluates to false.
It is caused by network protocols like TFTP and HTTP are designed for
transferring files and not a file system over network. In that way they
do not have a way to list files in a directory and test their properties
individually. The current logic in grub assumes that directory and file
listing must be implemented, which applies to local file systems but not
to file reading over the network. This logic should be adjusted to test
network files.
This patch updates the logic to detect when the underlying device is a
network device. If so, it attempts to test the file using
grub_file_open. If the file opens successfully, the ctx->file_exists
flag is set accordingly to true. Other properties that cannot be
determined over the network, such as whether the file is a directory or
whether the modification time is set, are conservatively set to false.
This means that -d cannot reliably detect directories on network
devices, and -e may not work as expected if the target is a directory.
In addition, comparisons such as -nt and -ot will not function
correctly, since file timestamps are not available. Despite these
limitations, this patch ensures that the -f test behaves correctly in
the most common case: checking whether a "file" exists on a network
device.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/commands/test.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/grub-core/commands/test.c b/grub-core/commands/test.c
index 62d3fb398..541f36daf 100644
--- a/grub-core/commands/test.c
+++ b/grub-core/commands/test.c
@@ -91,6 +91,23 @@ get_fileinfo (char *path, struct test_parse_ctx *ctx)
return;
}
+ if (! dev->disk && dev->net)
+ {
+ grub_file_t file;
+
+ file = grub_file_open (path , GRUB_FILE_TYPE_GET_SIZE
+ | GRUB_FILE_TYPE_NO_DECOMPRESS);
+ ctx->file_exists = file ? 1 : 0;
+ ctx->file_info.dir = 0;
+ ctx->file_info.mtimeset = 0;
+ grub_errno = GRUB_ERR_NONE;
+ if (file)
+ grub_file_close (file);
+ grub_free (device_name);
+ grub_device_close (dev);
+ return;
+ }
+
fs = grub_fs_probe (dev);
if (! fs)
{
--
2.50.0

View File

@@ -1,44 +0,0 @@
From cda4b7a415eb45743ea54a7760b302c0cfe718cf Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 23 Sep 2024 10:32:18 +0800
Subject: [PATCH] tpm: Skip loopback image measurement
The loopback image is configured to function as a disk by being mapped
as a block device. Instead of measuring the entire block device, we
should focus on tracking the individual files accessed from it. For
example, we do not directly measure block devices like disk hd0, but the
files opened from it.
This method is important to avoid running out of memory, since loopback
images can be very large. Trying to read and measure the whole image at
once could cause out of memory errors and disrupt the boot process.
Signed-Off-by: Michael Chang <mchang@suse.com>
---
grub-core/commands/tpm.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/grub-core/commands/tpm.c b/grub-core/commands/tpm.c
index bb9aee210..ebbb4fef0 100644
--- a/grub-core/commands/tpm.c
+++ b/grub-core/commands/tpm.c
@@ -41,6 +41,16 @@ grub_tpm_verify_init (grub_file_t io,
{
*context = io->name;
*flags |= GRUB_VERIFY_FLAGS_SINGLE_CHUNK;
+
+ /*
+ * The loopback image is mapped as a disk, allowing it to function like a
+ * block device. However, we measure the files read from the block device,
+ * not the device itself. For example, we don't measure block devices like
+ * disk hd0 directly. This process is crucial to prevent out-of-memory
+ * errors, as loopback images are inherently large.
+ */
+ if ((type & GRUB_FILE_TYPE_MASK) == GRUB_FILE_TYPE_LOOPBACK)
+ *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
return GRUB_ERR_NONE;
}
--
2.46.1

View File

@@ -1,4 +1,4 @@
From 53c3dc557890466757090ee390a2c5d241e50483 Mon Sep 17 00:00:00 2001
From f41a45b080cb9c6f59879a3e23f9ec2380015a16 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Thu, 25 Apr 2024 16:21:45 +0800
Subject: [PATCH] tpm2: Add extra RSA SRK types
@@ -6,42 +6,41 @@ Subject: [PATCH] tpm2: Add extra RSA SRK types
Since fde-tools may set RSA3072 and RSA4096 as the SRK type, grub2 has
to support those parameters.
Also prevent RSA SRK type from being overwritten when 'rsaparent' is set
in the key file.
Signed-off-by: Gary Lin <glin@suse.com>
---
grub-core/commands/tpm2_key_protector/args.c | 10 ++++++++++
grub-core/commands/tpm2_key_protector/module.c | 18 +++++++++++++++---
util/grub-protect.c | 4 ++--
3 files changed, 27 insertions(+), 5 deletions(-)
grub-core/tpm2/args.c | 12 ++++++++++++
grub-core/tpm2/module.c | 16 ++++++++++++++--
util/grub-protect.c | 4 ++--
3 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/grub-core/commands/tpm2_key_protector/args.c b/grub-core/commands/tpm2_key_protector/args.c
index 48c39de01..5781a31f1 100644
--- a/grub-core/commands/tpm2_key_protector/args.c
+++ b/grub-core/commands/tpm2_key_protector/args.c
@@ -85,6 +85,16 @@ grub_tpm2_protector_parse_asymmetric (const char *value,
diff --git a/grub-core/tpm2/args.c b/grub-core/tpm2/args.c
index c11280ab9..d140364d2 100644
--- a/grub-core/tpm2/args.c
+++ b/grub-core/tpm2/args.c
@@ -92,6 +92,18 @@ grub_tpm2_protector_parse_asymmetric (const char *value,
srk_type->type = TPM_ALG_RSA;
srk_type->detail.rsa_bits = 2048;
}
+ else if (grub_strcasecmp (value, "RSA3072") == 0)
+ else if (grub_strcasecmp (value, "RSA") == 0 ||
+ grub_strcasecmp (value, "RSA3072") == 0)
+ {
+ srk_type->type = TPM_ALG_RSA;
+ srk_type->detail.rsa_bits = 3072;
+ }
+ else if (grub_strcasecmp (value, "RSA4096") == 0)
+ else if (grub_strcasecmp (value, "RSA") == 0 ||
+ grub_strcasecmp (value, "RSA4096") == 0)
+ {
+ srk_type->type = TPM_ALG_RSA;
+ srk_type->detail.rsa_bits = 4096;
+ }
else
return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("value '%s' is not a valid asymmetric key type"), value);
diff --git a/grub-core/commands/tpm2_key_protector/module.c b/grub-core/commands/tpm2_key_protector/module.c
index 74e79a545..1b2eb6b20 100644
--- a/grub-core/commands/tpm2_key_protector/module.c
+++ b/grub-core/commands/tpm2_key_protector/module.c
@@ -138,8 +138,8 @@ static const struct grub_arg_option tpm2_protector_init_cmd_options[] =
return grub_error (GRUB_ERR_OUT_OF_RANGE,
N_("Value '%s' is not a valid asymmetric key type"),
diff --git a/grub-core/tpm2/module.c b/grub-core/tpm2/module.c
index b754b38df..8b72ed6fa 100644
--- a/grub-core/tpm2/module.c
+++ b/grub-core/tpm2/module.c
@@ -136,8 +136,8 @@ static const struct grub_arg_option grub_tpm2_protector_init_cmd_options[] =
.arg = NULL,
.type = ARG_TYPE_STRING,
.doc =
@@ -52,18 +51,18 @@ index 74e79a545..1b2eb6b20 100644
},
/* NV Index-mode options */
{
@@ -517,6 +517,10 @@ srk_type_to_name (grub_srk_type_t srk_type)
return "ECC_NIST_P256";
else if (srk_type.type == TPM_ALG_RSA && srk_type.detail.rsa_bits == 2048)
return "RSA2048";
+ else if (srk_type.type == TPM_ALG_RSA && srk_type.detail.rsa_bits == 3072)
+ return "RSA3072";
+ else if (srk_type.type == TPM_ALG_RSA && srk_type.detail.rsa_bits == 4096)
+ return "RSA4096";
@@ -541,6 +541,10 @@ srk_type_to_name (grub_srk_type_t srk_type)
{
case 2048:
return "RSA2048";
+ case 3072:
+ return "RSA3072";
+ case 4096:
+ return "RSA4096";
}
}
return "Unknown";
}
@@ -535,6 +539,14 @@ tpm2_protector_load_key (const tpm2_protector_context_t *ctx,
@@ -561,6 +565,14 @@ grub_tpm2_protector_load_key (const struct grub_tpm2_protector_context *ctx,
.type = TPM_ALG_ECC,
.detail.ecc_curve = TPM_ECC_NIST_P256,
},
@@ -78,30 +77,21 @@ index 74e79a545..1b2eb6b20 100644
{
.type = TPM_ALG_RSA,
.detail.rsa_bits = 2048,
@@ -882,7 +894,7 @@ tpm2_protector_srk_recover (const tpm2_protector_context_t *ctx,
if (err != GRUB_ERR_NONE)
goto exit1;
- if (rsaparent == 1)
+ if (rsaparent == 1 && ctx->srk_type.type != TPM_ALG_RSA)
{
tpm2_protector_context_t *ctx_w;
diff --git a/util/grub-protect.c b/util/grub-protect.c
index 5b7e952f4..f1108f2c5 100644
index 869f45861..00be03ca0 100644
--- a/util/grub-protect.c
+++ b/util/grub-protect.c
@@ -202,8 +202,8 @@ static struct argp_option protect_options[] =
@@ -199,8 +199,8 @@ static struct argp_option grub_protect_options[] =
.arg = "TYPE",
.flags = 0,
.doc =
- N_("Set the type of SRK: RSA (RSA2048) and ECC (ECC_NIST_P256)."
- N_("The type of SRK: RSA (RSA2048) and ECC (ECC_NIST_P256)."
- "(default: ECC)"),
+ N_("Set the type of SRK: RSA (RSA2048), RSA3072, RSA4096, "
+ N_("The type of SRK: RSA (RSA2048), RSA3072, RSA4096, "
+ "and ECC (ECC_NIST_P256). (default: ECC)"),
.group = 0
},
{
--
2.43.0
2.35.3

View File

@@ -1,12 +1,12 @@
From 53e24662523d033ae3506b73787b972ef332db36 Mon Sep 17 00:00:00 2001
From 947009d79e3f17b10a7753bdde8d3a4a7b757bed Mon Sep 17 00:00:00 2001
From: Patrick Colp <patrick.colp@oracle.com>
Date: Mon, 31 Jul 2023 07:01:45 -0700
Subject: [PATCH] tpm2_key_protector: Implement NV index
Subject: [PATCH 1/4] tpm2: Implement NV index
Currently with the TPM2 protector, only SRK mode is supported and
NV index support is just a stub. Implement the NV index option.
Note: This only extends support on the unseal path. grub-protect
Note: This only extends support on the unseal path. grub2_protect
has not been updated. tpm2-tools can be used to insert a key into
the NV index.
@@ -36,40 +36,41 @@ Then to unseal the key in grub, add this to grub.cfg:
Signed-off-by: Patrick Colp <patrick.colp@oracle.com>
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
.../commands/tpm2_key_protector/module.c | 23 +++++++++++++++----
1 file changed, 19 insertions(+), 4 deletions(-)
grub-core/tpm2/module.c | 25 ++++++++++++++++++++-----
1 file changed, 20 insertions(+), 5 deletions(-)
diff --git a/grub-core/commands/tpm2_key_protector/module.c b/grub-core/commands/tpm2_key_protector/module.c
index 6b4b5d460..74e79a545 100644
--- a/grub-core/commands/tpm2_key_protector/module.c
+++ b/grub-core/commands/tpm2_key_protector/module.c
@@ -973,11 +973,26 @@ tpm2_protector_srk_recover (const tpm2_protector_context_t *ctx,
}
static grub_err_t
-tpm2_protector_nv_recover (const tpm2_protector_context_t *ctx __attribute__ ((unused)),
- grub_uint8_t **key __attribute__ ((unused)),
- grub_size_t *key_size __attribute__ ((unused)))
+tpm2_protector_nv_recover (const tpm2_protector_context_t *ctx,
+ grub_uint8_t **key, grub_size_t *key_size)
diff --git a/grub-core/tpm2/module.c b/grub-core/tpm2/module.c
index e83b02865..b754b38df 100644
--- a/grub-core/tpm2/module.c
+++ b/grub-core/tpm2/module.c
@@ -1035,12 +1035,27 @@ static grub_err_t
grub_tpm2_protector_nv_recover (const struct grub_tpm2_protector_context *ctx,
grub_uint8_t **key, grub_size_t *key_size)
{
- return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "NV Index mode is not implemented yet");
+ TPM_HANDLE_t sealed_handle = ctx->nv;
- (void)ctx;
- (void)key;
- (void)key_size;
+ TPM_HANDLE sealed_handle = ctx->nv;
+ tpm2key_policy_t policy_seq = NULL;
+ grub_err_t err;
+
+ /* Create a basic policy sequence based on the given PCR selection */
+ err = tpm2_protector_simple_policy_seq (ctx, &policy_seq);
+ err = grub_tpm2_protector_simple_policy_seq (ctx, &policy_seq);
+ if (err != GRUB_ERR_NONE)
+ goto exit;
+
+ err = tpm2_protector_unseal (policy_seq, sealed_handle, key, key_size);
+ err = grub_tpm2_protector_unseal (policy_seq, sealed_handle, key, key_size);
+
+ exit:
+ grub_tpm2_flushcontext (sealed_handle);
+ /* Pop error messages on success */
+ if (err == GRUB_ERR_NONE)
+ while (grub_error_pop ());
+
+exit:
+ TPM2_FlushContext (sealed_handle);
- return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
- N_("NV Index mode is not implemented yet"));
+ grub_tpm2key_free_policy_seq (policy_seq);
+
+ return err;
@@ -77,5 +78,5 @@ index 6b4b5d460..74e79a545 100644
static grub_err_t
--
2.43.0
2.35.3

View File

@@ -0,0 +1,171 @@
From 26a66098d5fa50b9462c8c815429a4c18f20310b Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Thu, 6 Apr 2023 16:00:25 +0800
Subject: [PATCH] tpm2: Support authorized policy
This commit handles the TPM2_PolicyAuthorize command from the key file
in TPM 2.0 Key File format.
TPM2_PolicyAuthorize is the essential command to support authorized
policy which allows the users to sign TPM policies with their own keys.
Per TPM 2.0 Key File(*1), CommandPolicy for TPM2_PolicyAuthorize
comprises 'TPM2B_PUBLIC pubkey', 'TPM2B_DIGEST policy_ref', and
'TPMT_SIGNATURE signature'. To verify the signature, the current policy
digest is hashed with the hash algorithm written in 'signature', and then
'signature' is verified with the hashed policy digest and 'pubkey'. Once
TPM accepts 'signature', TPM2_PolicyAuthorize is invoked to authorize the
signed policy.
To create the key file with authorized policy, here are the pcr-oracle(*2)
commands:
# Generate the RSA key and create the authorized policy file
$ pcr-oracle \
--rsa-generate-key \
--private-key policy-key.pem \
--auth authorized.policy \
create-authorized-policy 0,2,4,7,9
# Seal the secret with the authorized policy
$ pcr-oracle \
--key-format tpm2.0 \
--auth authorized.policy \
--input disk-secret.txt \
--output sealed.key \
seal-secret
# Sign the predicted PCR policy
$ pcr-oracle \
--key-format tpm2.0 \
--private-key policy-key.pem \
--from eventlog \
--stop-event "grub-file=grub.cfg" \
--after \
--input sealed.key \
--output sealed.tpm \
sign 0,2,4,7,9
Then specify the key file and the key protector to grub.cfg in the EFI
system partition:
tpm2_key_protector_init -a RSA --tpm2key=(hd0,gpt1)/boot/grub2/sealed.tpm
cryptomount -u <PART_UUID> -P tpm2
For any change in the boot components, just run the 'sign' command again
to update the signature in sealed.tpm, and TPM can unseal the key file
with the updated PCR policy.
(*1) https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html
(*2) https://github.com/okirch/pcr-oracle
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
---
grub-core/tpm2/module.c | 84 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 84 insertions(+)
diff --git a/grub-core/tpm2/module.c b/grub-core/tpm2/module.c
index 3db25ceca..e83b02865 100644
--- a/grub-core/tpm2/module.c
+++ b/grub-core/tpm2/module.c
@@ -650,6 +650,87 @@ grub_tpm2_protector_policypcr (TPMI_SH_AUTH_SESSION session,
return GRUB_ERR_NONE;
}
+static grub_err_t
+grub_tpm2_protector_policyauthorize (TPMI_SH_AUTH_SESSION session,
+ struct grub_tpm2_buffer *cmd_buf)
+{
+ TPM2B_PUBLIC pubkey;
+ TPM2B_DIGEST policy_ref;
+ TPMT_SIGNATURE signature;
+ TPM2B_DIGEST pcr_policy;
+ TPM2B_DIGEST pcr_policy_hash;
+ TPMI_ALG_HASH sig_hash;
+ TPMT_TK_VERIFIED verification_ticket;
+ TPM_HANDLE pubkey_handle = 0;
+ TPM2B_NAME pubname;
+ TPM_RC rc;
+ grub_err_t err;
+
+ grub_tpm2_mu_TPM2B_PUBLIC_Unmarshal (cmd_buf, &pubkey);
+ grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (cmd_buf, &policy_ref);
+ grub_tpm2_mu_TPMT_SIGNATURE_Unmarshal (cmd_buf, &signature);
+ if (cmd_buf->error != 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("Failed to unmarshal the buffer for TPM2_PolicyAuthorize"));
+
+ /* Retrieve Policy Digest */
+ rc = TPM2_PolicyGetDigest (session, NULL, &pcr_policy, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ return grub_error (GRUB_ERR_BAD_DEVICE,
+ N_("Failed to get policy digest (TPM2_PolicyGetDigest: 0x%x)."),
+ rc);
+
+ /* Calculate the digest of the polcy for VerifySignature */
+ sig_hash = TPMT_SIGNATURE_get_hash_alg (&signature);
+ if (sig_hash == TPM_ALG_NULL)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("Failed to get the hash algorithm of the signature"));
+
+ rc = TPM2_Hash (NULL, (TPM2B_MAX_BUFFER *)&pcr_policy, sig_hash,
+ TPM_RH_NULL, &pcr_policy_hash, NULL, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ return grub_error (GRUB_ERR_BAD_DEVICE,
+ N_("Failed to create PCR policy hash (TPM2_Hash: 0x%x)"),
+ rc);
+
+ /* Load the public key */
+ rc = TPM2_LoadExternal (NULL, NULL, &pubkey, TPM_RH_OWNER,
+ &pubkey_handle, &pubname, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ return grub_error (GRUB_ERR_BAD_DEVICE,
+ N_("Failed to load public key (TPM2_LoadExternal: 0x%x)"),
+ rc);
+
+ /* Verify the signature against the public key and the policy digest */
+ rc = TPM2_VerifySignature (pubkey_handle, NULL, &pcr_policy_hash, &signature,
+ &verification_ticket, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ err = grub_error (GRUB_ERR_BAD_DEVICE,
+ N_("Failed to verify signature (TPM2_VerifySignature: 0x%x)"),
+ rc);
+ goto error;
+ }
+
+ /* Authorize the signed policy with the public key and the verification ticket */
+ rc = TPM2_PolicyAuthorize (session, NULL, &pcr_policy, &policy_ref, &pubname,
+ &verification_ticket, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ err = grub_error (GRUB_ERR_BAD_DEVICE,
+ N_("Failed to authorize PCR policy (TPM2_PolicyAuthorize: 0x%x)"),
+ rc);
+ goto error;
+ }
+
+ err = GRUB_ERR_NONE;
+
+error:
+ TPM2_FlushContext (pubkey_handle);
+
+ return err;
+}
+
static grub_err_t
grub_tpm2_protector_enforce_policy (tpm2key_policy_t policy, TPMI_SH_AUTH_SESSION session)
{
@@ -669,6 +750,9 @@ grub_tpm2_protector_enforce_policy (tpm2key_policy_t policy, TPMI_SH_AUTH_SESSIO
case TPM_CC_PolicyPCR:
err = grub_tpm2_protector_policypcr (session, &buf);
break;
+ case TPM_CC_PolicyAuthorize:
+ err = grub_tpm2_protector_policyauthorize (session, &buf);
+ break;
default:
return grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("Unknown TPM Command: 0x%x"), policy->cmd_code);
--
2.35.3

View File

@@ -1,241 +0,0 @@
From 76a2bcb99754ee5b4159c35f66042e392139b815 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Fri, 15 Nov 2024 15:34:59 +0800
Subject: [PATCH] tpm2_key_protector: Add grub-emu support
As a preparation to test tpm2_key_protector with grub-emu, the new
option, --tpm-device, is introduced to specify the TPM device for
grub-emu so that grub-emu can access an emulated TPM device from
the host.
Since grub-emu can directly access the device on host, it's easy to
implement the essential TCG2 command submission function with the
read/write functions and enable tpm2_key_protector module for grub-emu,
so that we can further test TPM2 key unsealing with grub-emu.
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-by: Stefan Berger <stefanb@linux.ibm.com>
---
grub-core/Makefile.core.def | 3 +++
grub-core/kern/emu/main.c | 11 +++++++-
grub-core/kern/emu/misc.c | 51 +++++++++++++++++++++++++++++++++++
grub-core/lib/tss2/tcg2_emu.c | 49 +++++++++++++++++++++++++++++++++
include/grub/emu/misc.h | 5 ++++
5 files changed, 118 insertions(+), 1 deletion(-)
create mode 100644 grub-core/lib/tss2/tcg2_emu.c
Index: grub-2.12/grub-core/Makefile.core.def
===================================================================
--- grub-2.12.orig/grub-core/Makefile.core.def
+++ grub-2.12/grub-core/Makefile.core.def
@@ -2628,7 +2628,9 @@ module = {
common = lib/tss2/tpm2_cmd.c;
common = lib/tss2/tss2.c;
efi = lib/efi/tcg2.c;
+ emu = lib/tss2/tcg2_emu.c;
enable = efi;
+ enable = emu;
cppflags = '-I$(srcdir)/lib/tss2';
};
@@ -2640,6 +2642,7 @@ module = {
common = commands/tpm2_key_protector/tpm2key_asn1_tab.c;
/* The plaform support of tpm2_key_protector depends on the tcg2 implementation in tss2. */
enable = efi;
+ enable = emu;
cppflags = '-I$(srcdir)/lib/tss2';
};
Index: grub-2.12/grub-core/kern/emu/main.c
===================================================================
--- grub-2.12.orig/grub-core/kern/emu/main.c
+++ grub-2.12/grub-core/kern/emu/main.c
@@ -55,7 +55,7 @@
static jmp_buf main_env;
/* Store the prefix specified by an argument. */
-static char *root_dev = NULL, *dir = NULL;
+static char *root_dev = NULL, *dir = NULL, *tpm_dev = NULL;
grub_addr_t grub_modbase = 0;
@@ -108,6 +108,7 @@ static struct argp_option options[] = {
{"verbose", 'v', 0, 0, N_("print verbose messages."), 0},
{"hold", 'H', N_("SECS"), OPTION_ARG_OPTIONAL, N_("wait until a debugger will attach"), 0},
{"kexec", 'X', 0, 0, N_("use kexec to boot Linux kernels via systemctl (pass twice to enable dangerous fallback to non-systemctl)."), 0},
+ {"tpm-device", 't', N_("DEV"), 0, N_("set TPM device."), 0},
{ 0, 0, 0, 0, 0, 0 }
};
@@ -168,6 +169,10 @@ argp_parser (int key, char *arg, struct
case 'X':
grub_util_set_kexecute ();
break;
+ case 't':
+ free (tpm_dev);
+ tpm_dev = xstrdup (arg);
+ break;
case ARGP_KEY_ARG:
{
@@ -282,6 +287,9 @@ main (int argc, char *argv[])
dir = xstrdup (dir);
+ if (tpm_dev)
+ grub_util_tpm_open (tpm_dev);
+
/* Start GRUB! */
if (setjmp (main_env) == 0)
grub_main ();
@@ -289,6 +297,7 @@ main (int argc, char *argv[])
grub_fini_all ();
grub_hostfs_fini ();
grub_host_fini ();
+ grub_util_tpm_close ();
grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
Index: grub-2.12/grub-core/kern/emu/misc.c
===================================================================
--- grub-2.12.orig/grub-core/kern/emu/misc.c
+++ grub-2.12/grub-core/kern/emu/misc.c
@@ -28,6 +28,8 @@
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#include <grub/mm.h>
#include <grub/err.h>
@@ -41,6 +43,8 @@
int verbosity;
int kexecute;
+static int grub_util_tpm_fd = -1;
+
void
grub_util_warn (const char *fmt, ...)
{
@@ -230,3 +234,50 @@ grub_util_get_kexecute (void)
{
return kexecute;
}
+
+grub_err_t
+grub_util_tpm_open (const char *tpm_dev)
+{
+ if (grub_util_tpm_fd != -1)
+ return GRUB_ERR_NONE;
+
+ grub_util_tpm_fd = open (tpm_dev, O_RDWR);
+ if (grub_util_tpm_fd == -1)
+ grub_util_error (_("cannot open TPM device '%s': %s"), tpm_dev, strerror (errno));
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_util_tpm_close (void)
+{
+ int err;
+
+ if (grub_util_tpm_fd == -1)
+ return GRUB_ERR_NONE;
+
+ err = close (grub_util_tpm_fd);
+ if (err != GRUB_ERR_NONE)
+ grub_util_error (_("cannot close TPM device: %s"), strerror (errno));
+
+ grub_util_tpm_fd = -1;
+ return GRUB_ERR_NONE;
+}
+
+grub_size_t
+grub_util_tpm_read (void *output, grub_size_t size)
+{
+ if (grub_util_tpm_fd == -1)
+ return -1;
+
+ return read (grub_util_tpm_fd, output, size);
+}
+
+grub_size_t
+grub_util_tpm_write (const void *input, grub_size_t size)
+{
+ if (grub_util_tpm_fd == -1)
+ return -1;
+
+ return write (grub_util_tpm_fd, input, size);
+}
Index: grub-2.12/grub-core/lib/tss2/tcg2_emu.c
===================================================================
--- /dev/null
+++ grub-2.12/grub-core/lib/tss2/tcg2_emu.c
@@ -0,0 +1,49 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2024 SUSE LLC
+ * Copyright (C) 2024 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/mm.h>
+#include <grub/emu/misc.h>
+
+#include <tss2_buffer.h>
+#include <tss2_structs.h>
+#include <tcg2.h>
+
+grub_err_t
+grub_tcg2_get_max_output_size (grub_size_t *size)
+{
+ if (size == NULL)
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ *size = GRUB_TPM2_BUFFER_CAPACITY;
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_tcg2_submit_command (grub_size_t input_size, grub_uint8_t *input,
+ grub_size_t output_size, grub_uint8_t *output)
+{
+ if (grub_util_tpm_write (input, input_size) != input_size)
+ return GRUB_ERR_BAD_DEVICE;
+
+ if (grub_util_tpm_read (output, output_size) < sizeof (TPM_RESPONSE_HEADER_t))
+ return GRUB_ERR_BAD_DEVICE;
+
+ return GRUB_ERR_NONE;
+}
Index: grub-2.12/include/grub/emu/misc.h
===================================================================
--- grub-2.12.orig/include/grub/emu/misc.h
+++ grub-2.12/include/grub/emu/misc.h
@@ -75,4 +75,9 @@ grub_util_fopen (const char *path, const
int grub_util_file_sync (FILE *f);
+grub_err_t grub_util_tpm_open (const char *tpm_dev);
+grub_err_t grub_util_tpm_close (void);
+grub_size_t EXPORT_FUNC(grub_util_tpm_read) (void *output, grub_size_t size);
+grub_size_t EXPORT_FUNC(grub_util_tpm_write) (const void *input, grub_size_t size);
+
#endif /* GRUB_EMU_MISC_H */

View File

@@ -1,253 +0,0 @@
From 617dab9e476e8ea5aa314dcc5412bbd8a6f1f465 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Mon, 7 Apr 2025 16:29:15 +0800
Subject: [PATCH 1/7] tpm2_key_protector: Dump PCRs on policy fail
PCR mismatch is one common cause of TPM key unsealing fail. Since the
system may be compromised, it is not safe to boot into OS to get the PCR
values and TPM eventlog for the further investigation.
To provide some hints, GRUB now dumps PCRs on policy fail, so the user
can check the current PCR values. PCR 0~15 are chosen to cover the
firmware, bootloader, and OS.
The sample output:
PCR Mismatch! Check firmware and bootloader before typing passphrase!
TPM PCR [sha256]:
00: 17401f37710984c1d8a03a81fff3ab567ae9291bac61e21715b890ee28879738
01: 7a114329ba388445a96e8db2a072785937c1b7a8803ed7cc682b87f3ff3dd7a8
02: 11c2776849e8e24b7d80c926cbc4257871bffa744dadfefd3ed049ce25143e05
03: 6c33b362073e28e30b47302bbdd3e6f9cee4debca3a304e646f8c68245724350
04: 62d38838483ecfd2484ee3a2e5450d8ca3b35fc72cda6a8c620f9f43521c37d1
05: d8a85cb37221ab7d1f2cc5f554dbe0463acb6784b5b8dc3164ccaa66d8fff0e1
06: 9262e37cbe71ed4daf815b4a4881fb7251c9d371092dde827557d5368121e10e
07: 219d542233be492d62b079ffe46cf13396a8c27e520e88b08eaf2e6d3b7e70f5
08: de1f61c973b673e505adebe0d7e8fb65fde6c24dd4ab4fbaff9e28b18df6ecd3
09: c1de7274fa3e879a16d7e6e7629e3463d95f68adcfd17c477183846dccc41c89
10: 0000000000000000000000000000000000000000000000000000000000000000
11: 0000000000000000000000000000000000000000000000000000000000000000
12: 0000000000000000000000000000000000000000000000000000000000000000
13: 0000000000000000000000000000000000000000000000000000000000000000
14: 9ab9ebe4879a7f4dd00c04f37e79cfd69d0dd7a8bcc6b01135525b67676a3e40
15: 0000000000000000000000000000000000000000000000000000000000000000
16: 0000000000000000000000000000000000000000000000000000000000000000
17: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
18: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
19: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
20: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
21: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
22: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
23: 0000000000000000000000000000000000000000000000000000000000000000
error: failed to unseal sealed key (TPM2_Unseal: 0x99d).
error: no key protector provided a usable key for luks (af16e48f-746b-4a12-aae1-c14dcee429e0).
If the user happens to have the PCR values for key sealing, the PCR dump
can be used to identify the changed PCRs and narrow down the scope for
closer inspection.
Please note that the PCR dump is trustworthy only if the GRUB binary is
authentic, so the user has to check the GRUB binary thoroughly before
using the PCR dump.
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
.../commands/tpm2_key_protector/module.c | 118 +++++++++++++++++-
1 file changed, 114 insertions(+), 4 deletions(-)
diff --git a/grub-core/commands/tpm2_key_protector/module.c b/grub-core/commands/tpm2_key_protector/module.c
index 74e79a545..d5e530f77 100644
--- a/grub-core/commands/tpm2_key_protector/module.c
+++ b/grub-core/commands/tpm2_key_protector/module.c
@@ -790,7 +790,7 @@ tpm2_protector_simple_policy_seq (const tpm2_protector_context_t *ctx,
static grub_err_t
tpm2_protector_unseal (tpm2key_policy_t policy_seq, TPM_HANDLE_t sealed_handle,
- grub_uint8_t **key, grub_size_t *key_size)
+ grub_uint8_t **key, grub_size_t *key_size, bool *dump_pcr)
{
TPMS_AUTH_COMMAND_t authCmd = {0};
TPM2B_SENSITIVE_DATA_t data;
@@ -801,6 +801,8 @@ tpm2_protector_unseal (tpm2key_policy_t policy_seq, TPM_HANDLE_t sealed_handle,
TPM_RC_t rc;
grub_err_t err;
+ *dump_pcr = false;
+
/* Start Auth Session */
nonceCaller.size = TPM_SHA256_DIGEST_SIZE;
symmetric.algorithm = TPM_ALG_NULL;
@@ -820,6 +822,13 @@ tpm2_protector_unseal (tpm2key_policy_t policy_seq, TPM_HANDLE_t sealed_handle,
rc = grub_tpm2_unseal (sealed_handle, &authCmd, &data, NULL);
if (rc != TPM_RC_SUCCESS)
{
+ /*
+ * Trigger PCR dump on policy fail
+ * TPM_RC_S (0x800) | TPM_RC_1 (0x100) | RC_FMT (0x80) | TPM_RC_POLICY_FAIL (0x1D)
+ */
+ if (rc == 0x99D)
+ *dump_pcr = true;
+
err = grub_error (GRUB_ERR_BAD_DEVICE, "failed to unseal sealed key (TPM2_Unseal: 0x%x)", rc);
goto error;
}
@@ -845,6 +854,91 @@ tpm2_protector_unseal (tpm2key_policy_t policy_seq, TPM_HANDLE_t sealed_handle,
return err;
}
+#define TPM_PCR_STR_SIZE (sizeof (TPMU_HA_t) * 2 + 1)
+
+static grub_err_t
+tpm2_protector_get_pcr_str (const TPM_ALG_ID_t algo, grub_uint32_t index, char *pcr_str, grub_uint16_t buf_size)
+{
+ TPML_PCR_SELECTION_t pcr_sel = {
+ .count = 1,
+ .pcrSelections = {
+ {
+ .hash = algo,
+ .sizeOfSelect = 3,
+ .pcrSelect = {0}
+ },
+ }
+ };
+ TPML_DIGEST_t digest = {0};
+ grub_uint16_t i;
+ TPM_RC_t rc;
+
+ if (buf_size < TPM_PCR_STR_SIZE)
+ {
+ grub_snprintf (pcr_str, buf_size, "insufficient buffer");
+ return GRUB_ERR_OUT_OF_MEMORY;
+ }
+
+ TPMS_PCR_SELECTION_SelectPCR (&pcr_sel.pcrSelections[0], index);
+
+ rc = grub_tpm2_pcr_read (NULL, &pcr_sel, NULL, NULL, &digest, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ grub_snprintf (pcr_str, buf_size, "TPM2_PCR_Read: 0x%x", rc);
+ return GRUB_ERR_BAD_DEVICE;
+ }
+
+ /* Check the returned digest number and size */
+ if (digest.count != 1 || digest.digests[0].size > sizeof (TPMU_HA_t))
+ {
+ grub_snprintf (pcr_str, buf_size, "invalid digest");
+ return GRUB_ERR_BAD_DEVICE;
+ }
+
+ /* Print the digest to the buffer */
+ for (i = 0; i < digest.digests[0].size; i++)
+ grub_snprintf (pcr_str + 2 * i, buf_size - 2 * i, "%02x", digest.digests[0].buffer[i]);
+
+ return GRUB_ERR_NONE;
+}
+
+static void
+tpm2_protector_dump_pcr (const TPM_ALG_ID_t bank)
+{
+ const char *algo_name;
+ char pcr_str[TPM_PCR_STR_SIZE];
+ grub_uint8_t i;
+ grub_err_t err;
+
+ if (bank == TPM_ALG_SHA1)
+ algo_name = "sha1";
+ else if (bank == TPM_ALG_SHA256)
+ algo_name = "sha256";
+ else if (bank == TPM_ALG_SHA384)
+ algo_name = "sha384";
+ else if (bank == TPM_ALG_SHA512)
+ algo_name = "sha512";
+ else
+ algo_name = "other";
+
+ /* Try to fetch PCR 0 */
+ err = tpm2_protector_get_pcr_str (bank, 0, pcr_str, sizeof (pcr_str));
+ if (err != GRUB_ERR_NONE)
+ {
+ grub_printf ("Unsupported PCR bank [%s]: %s\n", algo_name, pcr_str);
+ return;
+ }
+
+ grub_printf ("TPM PCR [%s]:\n", algo_name);
+
+ grub_printf (" %02d: %s\n", 0, pcr_str);
+ for (i = 1; i < TPM_MAX_PCRS; i++)
+ {
+ tpm2_protector_get_pcr_str (bank, i, pcr_str, sizeof (pcr_str));
+ grub_printf (" %02d: %s\n", i, pcr_str);
+ }
+}
+
static grub_err_t
tpm2_protector_srk_recover (const tpm2_protector_context_t *ctx,
grub_uint8_t **key, grub_size_t *key_size)
@@ -859,6 +953,7 @@ tpm2_protector_srk_recover (const tpm2_protector_context_t *ctx,
tpm2key_policy_t policy_seq = NULL;
tpm2key_authpolicy_t authpol = NULL;
tpm2key_authpolicy_t authpol_seq = NULL;
+ bool dump_pcr = false;
grub_err_t err;
/*
@@ -924,7 +1019,7 @@ tpm2_protector_srk_recover (const tpm2_protector_context_t *ctx,
/* Iterate the authpolicy sequence to find one that unseals the key */
FOR_LIST_ELEMENTS (authpol, authpol_seq)
{
- err = tpm2_protector_unseal (authpol->policy_seq, sealed_handle, key, key_size);
+ err = tpm2_protector_unseal (authpol->policy_seq, sealed_handle, key, key_size, &dump_pcr);
if (err == GRUB_ERR_NONE)
break;
@@ -952,13 +1047,20 @@ tpm2_protector_srk_recover (const tpm2_protector_context_t *ctx,
goto exit2;
}
- err = tpm2_protector_unseal (policy_seq, sealed_handle, key, key_size);
+ err = tpm2_protector_unseal (policy_seq, sealed_handle, key, key_size, &dump_pcr);
}
/* Pop error messages on success */
if (err == GRUB_ERR_NONE)
while (grub_error_pop ());
+ /* Dump PCRs if necessary */
+ if (dump_pcr == true)
+ {
+ grub_printf ("PCR Mismatch! Check firmware and bootloader before typing passphrase!\n");
+ tpm2_protector_dump_pcr (ctx->bank);
+ }
+
exit2:
grub_tpm2_flushcontext (sealed_handle);
@@ -978,6 +1080,7 @@ tpm2_protector_nv_recover (const tpm2_protector_context_t *ctx,
{
TPM_HANDLE_t sealed_handle = ctx->nv;
tpm2key_policy_t policy_seq = NULL;
+ bool dump_pcr = false;
grub_err_t err;
/* Create a basic policy sequence based on the given PCR selection */
@@ -985,7 +1088,14 @@ tpm2_protector_nv_recover (const tpm2_protector_context_t *ctx,
if (err != GRUB_ERR_NONE)
goto exit;
- err = tpm2_protector_unseal (policy_seq, sealed_handle, key, key_size);
+ err = tpm2_protector_unseal (policy_seq, sealed_handle, key, key_size, &dump_pcr);
+
+ /* Dump PCRs if necessary */
+ if (dump_pcr == true)
+ {
+ grub_printf ("PCR Mismatch! Check firmware and bootloader before typing passphrase!\n");
+ tpm2_protector_dump_pcr (ctx->bank);
+ }
exit:
grub_tpm2_flushcontext (sealed_handle);
--
2.43.0

View File

@@ -1,158 +0,0 @@
From 7ef1b9b357c803cb8e30bbbebd44494b2b5c9d09 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Thu, 6 Apr 2023 16:00:25 +0800
Subject: [PATCH] tpm2_key_protector: Support authorized policy
This commit handles the TPM2_PolicyAuthorize command from the key file
in TPM 2.0 Key File format.
TPM2_PolicyAuthorize is the essential command to support authorized
policy which allows the users to sign TPM policies with their own keys.
Per TPM 2.0 Key File(*1), CommandPolicy for TPM2_PolicyAuthorize
comprises 'TPM2B_PUBLIC pubkey', 'TPM2B_DIGEST policy_ref', and
'TPMT_SIGNATURE signature'. To verify the signature, the current policy
digest is hashed with the hash algorithm written in 'signature', and then
'signature' is verified with the hashed policy digest and 'pubkey'. Once
TPM accepts 'signature', TPM2_PolicyAuthorize is invoked to authorize the
signed policy.
To create the key file with authorized policy, here are the pcr-oracle(*2)
commands:
# Generate the RSA key and create the authorized policy file
$ pcr-oracle \
--rsa-generate-key \
--private-key policy-key.pem \
--auth authorized.policy \
create-authorized-policy 0,2,4,7,9
# Seal the secret with the authorized policy
$ pcr-oracle \
--key-format tpm2.0 \
--auth authorized.policy \
--input disk-secret.txt \
--output sealed.key \
seal-secret
# Sign the predicted PCR policy
$ pcr-oracle \
--key-format tpm2.0 \
--private-key policy-key.pem \
--from eventlog \
--stop-event "grub-file=grub.cfg" \
--after \
--input sealed.key \
--output /boot/efi/efi/grub/sealed.tpm \
sign 0,2,4,7,9
Then specify the key file and the key protector to grub.cfg in the EFI
system partition:
tpm2_key_protector_init -a RSA --tpm2key=(hd0,gpt1)/efi/grub/sealed.tpm
cryptomount -u <PART_UUID> -P tpm2
For any change in the boot components, just run the 'sign' command again
to update the signature in sealed.tpm, and TPM can unseal the key file
with the updated PCR policy.
(*1) https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html
(*2) https://github.com/okirch/pcr-oracle
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
.../commands/tpm2_key_protector/module.c | 70 +++++++++++++++++++
1 file changed, 70 insertions(+)
diff --git a/grub-core/commands/tpm2_key_protector/module.c b/grub-core/commands/tpm2_key_protector/module.c
index 70d4d0df7..6b4b5d460 100644
--- a/grub-core/commands/tpm2_key_protector/module.c
+++ b/grub-core/commands/tpm2_key_protector/module.c
@@ -618,6 +618,73 @@ tpm2_protector_policypcr (TPMI_SH_AUTH_SESSION_t session, struct grub_tpm2_buffe
return GRUB_ERR_NONE;
}
+static grub_err_t
+tpm2_protector_policyauthorize (TPMI_SH_AUTH_SESSION_t session, struct grub_tpm2_buffer *cmd_buf)
+{
+ TPM2B_PUBLIC_t pubkey;
+ TPM2B_DIGEST_t policy_ref;
+ TPMT_SIGNATURE_t signature;
+ TPM2B_DIGEST_t pcr_policy;
+ TPM2B_DIGEST_t pcr_policy_hash;
+ TPMI_ALG_HASH_t sig_hash;
+ TPMT_TK_VERIFIED_t verification_ticket;
+ TPM_HANDLE_t pubkey_handle = 0;
+ TPM2B_NAME_t pubname;
+ TPM_RC_t rc;
+ grub_err_t err;
+
+ grub_Tss2_MU_TPM2B_PUBLIC_Unmarshal (cmd_buf, &pubkey);
+ grub_Tss2_MU_TPM2B_DIGEST_Unmarshal (cmd_buf, &policy_ref);
+ grub_Tss2_MU_TPMT_SIGNATURE_Unmarshal (cmd_buf, &signature);
+ if (cmd_buf->error != 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to unmarshal the buffer for TPM2_PolicyAuthorize");
+
+ /* Retrieve Policy Digest */
+ rc = grub_tpm2_policygetdigest (session, NULL, &pcr_policy, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "failed to get policy digest (TPM2_PolicyGetDigest: 0x%x).", rc);
+
+ /* Calculate the digest of the polcy for VerifySignature */
+ sig_hash = TPMT_SIGNATURE_get_hash_alg (&signature);
+ if (sig_hash == TPM_ALG_NULL)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to get the hash algorithm of the signature");
+
+ rc = grub_tpm2_hash (NULL, (TPM2B_MAX_BUFFER_t *) &pcr_policy, sig_hash,
+ TPM_RH_NULL, &pcr_policy_hash, NULL, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "failed to create PCR policy hash (TPM2_Hash: 0x%x)", rc);
+
+ /* Load the public key */
+ rc = grub_tpm2_loadexternal (NULL, NULL, &pubkey, TPM_RH_OWNER, &pubkey_handle, &pubname, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "failed to load public key (TPM2_LoadExternal: 0x%x)", rc);
+
+ /* Verify the signature against the public key and the policy digest */
+ rc = grub_tpm2_verifysignature (pubkey_handle, NULL, &pcr_policy_hash, &signature,
+ &verification_ticket, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ err = grub_error (GRUB_ERR_BAD_DEVICE, "failed to verify signature (TPM2_VerifySignature: 0x%x)", rc);
+ goto error;
+ }
+
+ /* Authorize the signed policy with the public key and the verification ticket */
+ rc = grub_tpm2_policyauthorize (session, NULL, &pcr_policy, &policy_ref, &pubname,
+ &verification_ticket, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ err = grub_error (GRUB_ERR_BAD_DEVICE, "failed to authorize PCR policy (TPM2_PolicyAuthorize: 0x%x)", rc);
+ goto error;
+ }
+
+ err = GRUB_ERR_NONE;
+
+ error:
+ grub_tpm2_flushcontext (pubkey_handle);
+
+ return err;
+}
+
static grub_err_t
tpm2_protector_enforce_policy (tpm2key_policy_t policy, TPMI_SH_AUTH_SESSION_t session)
{
@@ -636,6 +703,9 @@ tpm2_protector_enforce_policy (tpm2key_policy_t policy, TPMI_SH_AUTH_SESSION_t s
case TPM_CC_PolicyPCR:
err = tpm2_protector_policypcr (session, &buf);
break;
+ case TPM_CC_PolicyAuthorize:
+ err = tpm2_protector_policyauthorize (session, &buf);
+ break;
default:
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown TPM Command: 0x%x", policy->cmd_code);
}
--
2.43.0

View File

@@ -1,101 +0,0 @@
From 99ee68a0149b1132f160c80924ab2987ebafcbdd Mon Sep 17 00:00:00 2001
From: Stefan Berger <stefanb@linux.ibm.com>
Date: Tue, 26 Nov 2024 15:39:40 -0500
Subject: [PATCH 1/7] tss2: Adjust bit fields for big endian targets
The TPM bit fields need to be in reverse order for big endian targets,
such as ieee1275 PowerPC platforms that run GRUB in big endian mode.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Gary Lin <glin@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/lib/tss2/tss2_structs.h | 38 +++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/grub-core/lib/tss2/tss2_structs.h b/grub-core/lib/tss2/tss2_structs.h
index ca33db3ec..e5390ab56 100644
--- a/grub-core/lib/tss2/tss2_structs.h
+++ b/grub-core/lib/tss2/tss2_structs.h
@@ -147,6 +147,15 @@ typedef TPM2B_DIGEST_t TPM2B_NONCE_t;
/* TPMA_SESSION Structure */
struct TPMA_SESSION
{
+#ifdef GRUB_TARGET_WORDS_BIGENDIAN
+ grub_uint8_t audit:1;
+ grub_uint8_t encrypt:1;
+ grub_uint8_t decrypt:1;
+ grub_uint8_t reserved:2;
+ grub_uint8_t auditReset:1;
+ grub_uint8_t auditExclusive:1;
+ grub_uint8_t continueSession:1;
+#else
grub_uint8_t continueSession:1;
grub_uint8_t auditExclusive:1;
grub_uint8_t auditReset:1;
@@ -154,6 +163,7 @@ struct TPMA_SESSION
grub_uint8_t decrypt:1;
grub_uint8_t encrypt:1;
grub_uint8_t audit:1;
+#endif
};
typedef struct TPMA_SESSION TPMA_SESSION_t;
@@ -206,6 +216,24 @@ typedef struct TPM2B_SENSITIVE_CREATE TPM2B_SENSITIVE_CREATE_t;
/* TPMA_OBJECT Structure */
struct TPMA_OBJECT
{
+#ifdef GRUB_TARGET_WORDS_BIGENDIAN
+ grub_uint32_t reserved5:13;
+ grub_uint32_t sign:1;
+ grub_uint32_t decrypt:1;
+ grub_uint32_t restricted:1;
+ grub_uint32_t reserved4:4;
+ grub_uint32_t encryptedDuplication:1;
+ grub_uint32_t noDA:1;
+ grub_uint32_t reserved3:2;
+ grub_uint32_t adminWithPolicy:1;
+ grub_uint32_t userWithAuth:1;
+ grub_uint32_t sensitiveDataOrigin:1;
+ grub_uint32_t fixedParent:1;
+ grub_uint32_t reserved2:1;
+ grub_uint32_t stClear:1;
+ grub_uint32_t fixedTPM:1;
+ grub_uint32_t reserved1:1;
+#else
grub_uint32_t reserved1:1;
grub_uint32_t fixedTPM:1;
grub_uint32_t stClear:1;
@@ -222,6 +250,7 @@ struct TPMA_OBJECT
grub_uint32_t decrypt:1;
grub_uint32_t sign:1;
grub_uint32_t reserved5:13;
+#endif
};
typedef struct TPMA_OBJECT TPMA_OBJECT_t;
@@ -516,12 +545,21 @@ typedef struct TPM2B_DATA TPM2B_DATA_t;
/* TPMA_LOCALITY Structure */
struct TPMA_LOCALITY
{
+#ifdef GRUB_TARGET_WORDS_BIGENDIAN
+ grub_uint8_t Extended:3;
+ grub_uint8_t TPM_LOC_FOUR:1;
+ grub_uint8_t TPM_LOC_THREE:1;
+ grub_uint8_t TPM_LOC_TWO:1;
+ grub_uint8_t TPM_LOC_ONE:1;
+ grub_uint8_t TPM_LOC_ZERO:1;
+#else
grub_uint8_t TPM_LOC_ZERO:1;
grub_uint8_t TPM_LOC_ONE:1;
grub_uint8_t TPM_LOC_TWO:1;
grub_uint8_t TPM_LOC_THREE:1;
grub_uint8_t TPM_LOC_FOUR:1;
grub_uint8_t Extended:3;
+#endif
};
typedef struct TPMA_LOCALITY TPMA_LOCALITY_t;
--
2.43.0

View File

@@ -0,0 +1,411 @@
From 439de947262b0d8d4a02ca5afb1ef4f15853962c Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Fri, 9 Dec 2016 15:40:29 -0500
Subject: [PATCH 2/9] Add BLS support to grub-mkconfig
GRUB now has BootLoaderSpec support, the user can choose to use this by
setting GRUB_ENABLE_BLSCFG to true in /etc/default/grub. On this setup,
the boot menu entries are not added to the grub.cfg, instead BLS config
files are parsed by blscfg command and the entries created dynamically.
A 10_linux_bls grub.d snippet to generate menu entries from BLS files
is also added that can be used on platforms where the bootloader doesn't
have BLS support and only can parse a normal grub configuration file.
Portions of the 10_linux_bls were taken from the ostree-grub-generator
script that's included in the OSTree project.
Fixes to support multi-devices and generate a BLS section even if no
kernels are found in the boot directory were proposed by Yclept Nemo
and Tom Gundersen respectively.
Signed-off-by: Peter Jones <pjones@redhat.com>
[javierm: remove outdated URL for BLS document]
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
[iwienand@redhat.com: skip machine ID check when updating entries]
Signed-off-by: Ian Wienand <iwienand@redhat.com>
[rharwood: commit message composits, drop man pages]
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
---
util/grub-mkconfig.in | 9 +-
util/grub-mkconfig_lib.in | 22 +++-
util/grub.d/10_linux.in | 244 +++++++++++++++++++++++++++++++++++++-
3 files changed, 269 insertions(+), 6 deletions(-)
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index cf5b79342..7af15df94 100644
--- a/util/grub-mkconfig.in
+++ b/util/grub-mkconfig.in
@@ -49,6 +49,8 @@ grub_script_check="${bindir}/@grub_script_check@"
export TEXTDOMAIN=@PACKAGE@
export TEXTDOMAINDIR="@localedir@"
+export GRUB_GRUBENV_UPDATE="yes"
+
. "${pkgdatadir}/grub-mkconfig_lib"
# Usage: usage
@@ -58,6 +60,7 @@ usage () {
gettext "Generate a grub config file"; echo
echo
print_option_help "-o, --output=$(gettext FILE)" "$(gettext "output generated config to FILE [default=stdout]")"
+ print_option_help "--no-grubenv-update" "$(gettext "do not update variables in the grubenv file")"
print_option_help "-h, --help" "$(gettext "print this message and exit")"
print_option_help "-V, --version" "$(gettext "print the version information and exit")"
echo
@@ -93,6 +96,9 @@ do
--output=*)
grub_cfg=`echo "$option" | sed 's/--output=//'`
;;
+ --no-grubenv-update)
+ GRUB_GRUBENV_UPDATE="no"
+ ;;
-*)
gettext_printf "Unrecognized option \`%s'\n" "$option" 1>&2
usage
@@ -300,7 +306,8 @@ export GRUB_DEFAULT \
GRUB_DISABLE_SUBMENU \
SUSE_BTRFS_SNAPSHOT_BOOTING \
SUSE_CMDLINE_XENEFI \
- SUSE_REMOVE_LINUX_ROOT_PARAM
+ SUSE_REMOVE_LINUX_ROOT_PARAM \
+ GRUB_ENABLE_BLSCFG
if test "x${grub_cfg}" != "x"; then
rm -f "${grub_cfg}.new"
diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in
index 22fb7668f..5db4337c6 100644
--- a/util/grub-mkconfig_lib.in
+++ b/util/grub-mkconfig_lib.in
@@ -30,6 +30,9 @@ fi
if test "x$grub_file" = x; then
grub_file="${bindir}/@grub_file@"
fi
+if test "x$grub_editenv" = x; then
+ grub_editenv="${bindir}/@grub_editenv@"
+fi
if test "x$grub_mkrelpath" = x; then
grub_mkrelpath="${bindir}/@grub_mkrelpath@"
fi
@@ -123,8 +126,19 @@ EOF
fi
}
+prepare_grub_to_access_device_with_variable ()
+{
+ device_variable="$1"
+ shift
+ prepare_grub_to_access_device "$@"
+ unset "device_variable"
+}
+
prepare_grub_to_access_device ()
{
+ if [ -z "$device_variable" ]; then
+ device_variable="root"
+ fi
old_ifs="$IFS"
IFS='
'
@@ -159,18 +173,18 @@ prepare_grub_to_access_device ()
# otherwise set root as per value in device.map.
fs_hint="`"${grub_probe}" --device $@ --target=compatibility_hint`"
if [ "x$fs_hint" != x ]; then
- echo "set root='$fs_hint'"
+ echo "set ${device_variable}='$fs_hint'"
fi
if [ "x${GRUB_DISABLE_UUID}" != "xtrue" ] && fs_uuid="`"${grub_probe}" --device $@ --target=fs_uuid 2> /dev/null`" ; then
hints="`"${grub_probe}" --device $@ --target=hints_string 2> /dev/null`" || hints=
if [ "x$hints" != x ]; then
echo "if [ x\$feature_platform_search_hint = xy ]; then"
- echo " search --no-floppy --fs-uuid --set=root ${hints} ${fs_uuid}"
+ echo " search --no-floppy --fs-uuid --set=${device_variable} ${hints} ${fs_uuid}"
echo "else"
- echo " search --no-floppy --fs-uuid --set=root ${fs_uuid}"
+ echo " search --no-floppy --fs-uuid --set=${device_variable} ${fs_uuid}"
echo "fi"
else
- echo "search --no-floppy --fs-uuid --set=root ${fs_uuid}"
+ echo "search --no-floppy --fs-uuid --set=${device_variable} ${fs_uuid}"
fi
fi
IFS="$old_ifs"
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 5531239eb..49eccbeaf 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -91,6 +91,244 @@ if [ "x$SUSE_REMOVE_LINUX_ROOT_PARAM" = "xtrue" ]; then
LINUX_ROOT_DEVICE=""
fi
+populate_header_warn()
+{
+if [ "x${BLS_POPULATE_MENU}" = "xtrue" ]; then
+ bls_parser="10_linux script"
+else
+ bls_parser="blscfg command"
+fi
+cat <<EOF
+
+# This section was generated by a script. Do not modify the generated file - all changes
+# will be lost the next time file is regenerated. Instead edit the BootLoaderSpec files.
+#
+# The $bls_parser parses the BootLoaderSpec files stored in /boot/loader/entries and
+# populates the boot menu. Please refer to the Boot Loader Specification documentation
+# for the files format: https://systemd.io/BOOT_LOADER_SPECIFICATION/.
+
+EOF
+}
+
+read_config()
+{
+ config_file=${1}
+ title=""
+ initrd=""
+ options=""
+ linux=""
+ grub_arg=""
+
+ while read -r line
+ do
+ record=$(echo ${line} | cut -f 1 -d ' ')
+ value=$(echo ${line} | cut -s -f2- -d ' ')
+ case "${record}" in
+ "title")
+ title=${value}
+ ;;
+ "initrd")
+ initrd=${value}
+ ;;
+ "linux")
+ linux=${value}
+ ;;
+ "options")
+ options=${value}
+ ;;
+ "grub_arg")
+ grub_arg=${value}
+ ;;
+ esac
+ done < ${config_file}
+}
+
+blsdir="/boot/loader/entries"
+
+get_sorted_bls()
+{
+ if ! [ -d "${blsdir}" ]; then
+ return
+ fi
+
+ local IFS=$'\n'
+
+ files=($(for bls in ${blsdir}/*.conf; do
+ if ! [[ -e "${bls}" ]] ; then
+ continue
+ fi
+ bls="${bls%.conf}"
+ bls="${bls##*/}"
+ echo "${bls}"
+ done | ${kernel_sort} 2>/dev/null | tac)) || :
+
+ echo "${files[@]}"
+}
+
+update_bls_cmdline()
+{
+ local cmdline="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
+ local -a files=($(get_sorted_bls))
+
+ for bls in "${files[@]}"; do
+ local options="${cmdline}"
+ if [ -z "${bls##*debug*}" ]; then
+ options="${options} ${GRUB_CMDLINE_LINUX_DEBUG}"
+ fi
+ options="$(echo "${options}" | sed -e 's/\//\\\//g')"
+ sed -i -e "s/^options.*/options ${options}/" "${blsdir}/${bls}.conf"
+ done
+}
+
+populate_menu()
+{
+ local -a files=($(get_sorted_bls))
+
+ gettext_printf "Generating boot entries from BLS files...\n" >&2
+
+ for bls in "${files[@]}"; do
+ read_config "${blsdir}/${bls}.conf"
+
+ menu="${menu}menuentry '${title}' ${grub_arg} --id=${bls} {\n"
+ menu="${menu}\t linux ${linux} ${options}\n"
+ if [ -n "${initrd}" ] ; then
+ menu="${menu}\t initrd ${boot_prefix}${initrd}\n"
+ fi
+ menu="${menu}}\n\n"
+ done
+ # The printf command seems to be more reliable across shells for special character (\n, \t) evaluation
+ printf "$menu"
+}
+
+# Make BLS the default if GRUB_ENABLE_BLSCFG was not set and grubby is not installed.
+if [ -z "${GRUB_ENABLE_BLSCFG}" ] && ! command -v new-kernel-pkg >/dev/null; then
+ GRUB_ENABLE_BLSCFG="true"
+fi
+
+if [ "x${GRUB_ENABLE_BLSCFG}" = "xtrue" ]; then
+ if [ x$dirname = x/ ]; then
+ if [ -z "${prepare_root_cache}" ]; then
+ prepare_grub_to_access_device ${GRUB_DEVICE}
+ fi
+ else
+ if [ -z "${prepare_boot_cache}" ]; then
+ prepare_grub_to_access_device ${GRUB_DEVICE_BOOT}
+ fi
+ fi
+
+ if [ -d /sys/firmware/efi ]; then
+ bootefi_device="`${grub_probe} --target=device /boot/efi/`"
+ prepare_grub_to_access_device_with_variable boot ${bootefi_device}
+ else
+ boot_device="`${grub_probe} --target=device /boot/`"
+ prepare_grub_to_access_device_with_variable boot ${boot_device}
+ fi
+
+ arch="$(uname -m)"
+ if [ "x${arch}" = "xppc64le" ] && [ -d /sys/firmware/opal ]; then
+
+ BLS_POPULATE_MENU="true"
+ petitboot_path="/sys/firmware/devicetree/base/ibm,firmware-versions/petitboot"
+
+ if test -e ${petitboot_path}; then
+ read -r -d '' petitboot_version < ${petitboot_path}
+ petitboot_version="$(echo ${petitboot_version//v})"
+
+ if test -n ${petitboot_version}; then
+ major_version="$(echo ${petitboot_version} | cut -d . -f1)"
+ minor_version="$(echo ${petitboot_version} | cut -d . -f2)"
+
+ re='^[0-9]+$'
+ if [[ $major_version =~ $re ]] && [[ $minor_version =~ $re ]] &&
+ ([[ ${major_version} -gt 1 ]] ||
+ [[ ${major_version} -eq 1 &&
+ ${minor_version} -ge 8 ]]); then
+ BLS_POPULATE_MENU="false"
+ fi
+ fi
+ fi
+ fi
+
+ populate_header_warn
+
+ cat << EOF
+# The kernelopts variable should be defined in the grubenv file. But to ensure that menu
+# entries populated from BootLoaderSpec files that use this variable work correctly even
+# without a grubenv file, define a fallback kernelopts variable if this has not been set.
+#
+# The kernelopts variable in the grubenv file can be modified using the grubby tool or by
+# executing the grub2-mkconfig tool. For the latter, the values of the GRUB_CMDLINE_LINUX
+# and GRUB_CMDLINE_LINUX_DEFAULT options from /etc/default/grub file are used to set both
+# the kernelopts variable in the grubenv file and the fallback kernelopts variable.
+if [ -z "\${kernelopts}" ]; then
+ set kernelopts="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
+fi
+EOF
+
+ update_bls_cmdline
+
+ if [ "x${BLS_POPULATE_MENU}" = "xtrue" ]; then
+ populate_menu
+ else
+ cat << EOF
+
+insmod blscfg
+blscfg
+EOF
+ fi
+
+ if [ "x${GRUB_GRUBENV_UPDATE}" = "xyes" ]; then
+ blsdir="/boot/loader/entries"
+ [ -d "${blsdir}" ] && GRUB_BLS_FS="$(${grub_probe} --target=fs ${blsdir})"
+ if [ "x${GRUB_BLS_FS}" = "xbtrfs" ] || [ "x${GRUB_BLS_FS}" = "xzfs" ]; then
+ blsdir=$(make_system_path_relative_to_its_root "${blsdir}")
+ if [ "x${blsdir}" != "x/loader/entries" ] && [ "x${blsdir}" != "x/boot/loader/entries" ]; then
+ ${grub_editenv} - set blsdir="${blsdir}"
+ fi
+ fi
+
+ if [ -n "${GRUB_EARLY_INITRD_LINUX_CUSTOM}" ]; then
+ ${grub_editenv} - set early_initrd="${GRUB_EARLY_INITRD_LINUX_CUSTOM}"
+ fi
+
+ if [ -n "${GRUB_DEFAULT_DTB}" ]; then
+ ${grub_editenv} - set devicetree="${GRUB_DEFAULT_DTB}"
+ fi
+
+ if [ -n "${GRUB_SAVEDEFAULT}" ]; then
+ ${grub_editenv} - set save_default="${GRUB_SAVEDEFAULT}"
+ fi
+ fi
+
+ exit 0
+fi
+
+mktitle ()
+{
+ local title_type
+ local version
+ local OS_NAME
+ local OS_VERS
+
+ title_type=$1 && shift
+ version=$1 && shift
+
+ OS_NAME="$(eval $(grep ^NAME= /etc/os-release) ; echo ${NAME})"
+ OS_VERS="$(eval $(grep ^VERSION= /etc/os-release) ; echo ${VERSION})"
+
+ case $title_type in
+ recovery)
+ title=$(printf '%s (%s) %s (recovery mode)' \
+ "${OS_NAME}" "${version}" "${OS_VERS}")
+ ;;
+ *)
+ title=$(printf '%s (%s) %s' \
+ "${OS_NAME}" "${version}" "${OS_VERS}")
+ ;;
+ esac
+ echo -n ${title}
+}
+
title_correction_code=
hotkey=1
@@ -124,6 +362,7 @@ linux_entry ()
if [ -z "$boot_device_id" ]; then
boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
fi
+
if [ x$type != xsimple ] ; then
case $type in
recovery)
@@ -298,6 +537,7 @@ fi
is_top_level=true
for linux in ${reverse_sorted_list}; do
gettext_printf "Found linux image: %s\n" "$linux" >&2
+
basename=`basename $linux`
dirname=`dirname $linux`
rel_dirname=`make_system_path_relative_to_its_root $dirname`
@@ -348,7 +588,9 @@ for linux in ${reverse_sorted_list}; do
for i in ${initrd}; do
initrd_display="${initrd_display} ${dirname}/${i}"
done
- gettext_printf "Found initrd image: %s\n" "$(echo $initrd_display)" >&2
+ if [ "x${GRUB_ENABLE_BLSCFG}" != "xtrue" ]; then
+ gettext_printf "Found initrd image: %s\n" "$(echo $initrd_display)" >&2
+ fi
fi
config=
--
2.44.0

View File

@@ -1,278 +0,0 @@
From 0ed98269c5631c4d094b2cee81ce385687803730 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 29 Aug 2024 13:27:30 +0800
Subject: [PATCH 2/2] Requiring authentication after tpm unlock for CLI access
The GRUB may use TPM to verify the integrity of boot components and the
result can determine whether a previously sealed key can be released. If
everything checks out, showing nothing has been tampered with, the key
is released and GRUB unlocks the encrypted root partition for the next
stage of booting.
However, the liberal Command Line Interface (CLI) can be misused by
anyone in this case to access files in the encrypted partition one way
or another. Despite efforts to keep the CLI secure by preventing utility
command output from leaking file content, many techniques in the wild
could still be used to exploit the CLI, enabling attacks or learning
methods to attack. It's nearly impossible to account for all scenarios
where a hack could be applied.
Therefore, to mitigate potential misuse of the CLI after the root device
has been successfully unlocked via TPM, the user should be required to
authenticate using the LUKS password. This added layer of security
ensures that only authorized users can access the CLI reducing the risk
of exploitation or unauthorized access to the encrypted partition.
Fixes: CVE-2024-49504
Signed-off-by: Michael Chang <mchang@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/disk/cryptodisk.c | 84 +++++++++++++++++++++++++++++++++++
grub-core/kern/main.c | 12 +++++
grub-core/normal/auth.c | 30 +++++++++++++
grub-core/normal/main.c | 4 ++
grub-core/normal/menu_entry.c | 4 ++
include/grub/auth.h | 1 +
include/grub/cryptodisk.h | 3 ++
include/grub/misc.h | 2 +
8 files changed, 140 insertions(+)
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -1183,6 +1183,9 @@
ret = grub_cryptodisk_insert (dev, name, source);
if (ret != GRUB_ERR_NONE)
goto error;
+#ifndef GRUB_UTIL
+ grub_cli_set_auth_needed ();
+#endif
goto cleanup;
}
}
@@ -1700,6 +1703,89 @@
return ret;
}
+#ifdef GRUB_MACHINE_EFI
+grub_err_t
+grub_cryptodisk_challenge_password (void)
+{
+ grub_cryptodisk_t cr_dev;
+
+ for (cr_dev = cryptodisk_list; cr_dev != NULL; cr_dev = cr_dev->next)
+ {
+ grub_cryptodisk_dev_t cr;
+ grub_disk_t source = NULL;
+ grub_err_t ret = GRUB_ERR_NONE;
+ grub_cryptodisk_t dev = NULL;
+ char *part = NULL;
+ struct grub_cryptomount_args cargs = {0};
+
+ cargs.check_boot = 0;
+ cargs.search_uuid = cr_dev->uuid;
+
+ source = grub_disk_open (cr_dev->source);
+
+ if (source == NULL)
+ {
+ ret = grub_errno;
+ goto error_out;
+ }
+
+ FOR_CRYPTODISK_DEVS (cr)
+ {
+ dev = cr->scan (source, &cargs);
+ if (grub_errno)
+ {
+ ret = grub_errno;
+ goto error_out;
+ }
+ if (dev == NULL)
+ continue;
+ break;
+ }
+
+ if (dev == NULL)
+ {
+ ret = grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk module can handle this device");
+ goto error_out;
+ }
+
+ part = grub_partition_get_name (source->partition);
+ grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
+ source->partition != NULL ? "," : "",
+ part != NULL ? part : N_("UNKNOWN"), cr_dev->uuid);
+ grub_free (part);
+
+ cargs.key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE);
+ if (cargs.key_data == NULL)
+ {
+ ret = grub_errno;
+ goto error_out;
+ }
+
+ if (!grub_password_get ((char *) cargs.key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE))
+ {
+ ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied");
+ goto error_out;
+ }
+ cargs.key_len = grub_strlen ((char *) cargs.key_data);
+ ret = cr->recover_key (source, dev, &cargs);
+
+ error_out:
+ grub_disk_close (source);
+ if (dev != NULL)
+ cryptodisk_close (dev);
+ if (cargs.key_data)
+ {
+ grub_memset (cargs.key_data, 0, cargs.key_len);
+ grub_free (cargs.key_data);
+ }
+
+ return ret;
+ }
+
+ return GRUB_ERR_NONE;
+}
+#endif /* GRUB_MACHINE_EFI */
+
struct grub_procfs_entry luks_script =
{
.name = "luks_script",
--- a/grub-core/kern/main.c
+++ b/grub-core/kern/main.c
@@ -37,6 +37,7 @@
#endif
static bool cli_disabled = false;
+static bool cli_need_auth = false;
grub_addr_t
grub_modules_get_end (void)
@@ -246,6 +247,17 @@
return cli_disabled;
}
+bool
+grub_is_cli_need_auth (void)
+{
+ return cli_need_auth;
+}
+
+void grub_cli_set_auth_needed (void)
+{
+ cli_need_auth = true;
+}
+
static void
check_is_cli_disabled (void)
{
--- a/grub-core/normal/auth.c
+++ b/grub-core/normal/auth.c
@@ -25,6 +25,10 @@
#include <grub/time.h>
#include <grub/i18n.h>
+#ifdef GRUB_MACHINE_EFI
+#include <grub/cryptodisk.h>
+#endif
+
struct grub_auth_user
{
struct grub_auth_user *next;
@@ -201,6 +205,32 @@
}
grub_err_t
+grub_auth_check_cli_access (void)
+{
+ if (grub_is_cli_need_auth () == true)
+ {
+#ifdef GRUB_MACHINE_EFI
+ static bool authenticated = false;
+
+ if (authenticated == false)
+ {
+ grub_err_t ret;
+
+ ret = grub_cryptodisk_challenge_password ();
+ if (ret == GRUB_ERR_NONE)
+ authenticated = true;
+ return ret;
+ }
+ return GRUB_ERR_NONE;
+#else
+ return GRUB_ACCESS_DENIED;
+#endif
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
grub_auth_check_authentication (const char *userlist)
{
char login[1024];
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -560,9 +560,13 @@
}
while (err && force_auth);
+ if (err == GRUB_ERR_NONE)
+ err = grub_auth_check_cli_access ();
+
if (err)
{
grub_print_error ();
+ grub_wait_after_message ();
grub_errno = GRUB_ERR_NONE;
return;
}
--- a/grub-core/normal/menu_entry.c
+++ b/grub-core/normal/menu_entry.c
@@ -1256,9 +1256,13 @@
err = grub_auth_check_authentication (NULL);
+ if (err == GRUB_ERR_NONE)
+ err = grub_auth_check_cli_access ();
+
if (err)
{
grub_print_error ();
+ grub_wait_after_message ();
grub_errno = GRUB_ERR_NONE;
return;
}
--- a/include/grub/auth.h
+++ b/include/grub/auth.h
@@ -33,5 +33,6 @@
grub_err_t grub_auth_authenticate (const char *user);
grub_err_t grub_auth_deauthenticate (const char *user);
grub_err_t grub_auth_check_authentication (const char *userlist);
+grub_err_t grub_auth_check_cli_access (void);
#endif /* ! GRUB_AUTH_HEADER */
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -203,4 +203,7 @@
grub_cryptodisk_t grub_cryptodisk_get_by_uuid (const char *uuid);
grub_cryptodisk_t grub_cryptodisk_get_by_source_disk (grub_disk_t disk);
+#ifdef GRUB_MACHINE_EFI
+grub_err_t grub_cryptodisk_challenge_password (void);
+#endif
#endif
--- a/include/grub/misc.h
+++ b/include/grub/misc.h
@@ -392,6 +392,8 @@
grub_uint64_t *r);
extern bool EXPORT_FUNC(grub_is_cli_disabled) (void);
+extern bool EXPORT_FUNC(grub_is_cli_need_auth) (void);
+extern void EXPORT_FUNC(grub_cli_set_auth_needed) (void);
/* Must match softdiv group in gentpl.py. */
#if !defined(GRUB_MACHINE_EMU) && (defined(__arm__) || defined(__ia64__) || \

View File

@@ -0,0 +1,197 @@
From 912384e63c1e3b6aa9d90effb71cd535a17da1e2 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Sat, 18 Nov 2023 19:02:31 +0800
Subject: [PATCH 2/4] Restrict file access on cryptodisk print
When the encrypted partition is automatically unlocked by TPM, granting
access to the system upon validation of its known good state, there's a
potential vulnerability. Grub gains access to file systems that were
previously inaccessible to the public, enabling certain commands from
the grub console to print content. This arises due to grub lacking
restrictions similar to those imposed by password authentication, which
typically occurs before privileged access is granted.
Although the automatic unlocking process ensures system integrity and a
secure environment for grub to operate in, it doesn't directly address
the issue of authentication for viewing encrypted partition content.
This commit addresses this security loophole by implementing a file
filter upon adding a TPM key. The newly added file filter will
specifically verify if the disk is encrypted, denying access and
returning an "Access Denied: prohibited to view encrypted data" error
message to alert the user.
Since the policy to filter out unwanted commands from leaking encrypted
content is irreversible, it is advisable to make the loaded module
persistent to prevent its removal.
This enhancement aims to bolster security measures and prevent
unauthorized access to encrypted data.
Signed-Off-by Michael Chang <mchang@suse.com>
---
grub-core/commands/crypttab.c | 35 ++++++++++++++++++++++++++++++++++-
grub-core/disk/diskfilter.c | 35 +++++++++++++++++++++++++++++++++++
include/grub/disk.h | 10 ++++++++++
include/grub/file.h | 1 +
4 files changed, 80 insertions(+), 1 deletion(-)
diff --git a/grub-core/commands/crypttab.c b/grub-core/commands/crypttab.c
index 9397bede9..d3acc4b59 100644
--- a/grub-core/commands/crypttab.c
+++ b/grub-core/commands/crypttab.c
@@ -6,11 +6,39 @@
#include <grub/mm.h>
#include <grub/list.h>
#include <grub/crypttab.h>
+#include <grub/file.h>
GRUB_MOD_LICENSE ("GPLv3+");
grub_crypto_key_list_t *cryptokey_lst;
+static grub_file_t
+grub_nocat_open (grub_file_t io, enum grub_file_type type)
+{
+ grub_disk_t disk;
+
+ /* Network device */
+ if (!io->device->disk)
+ return io;
+
+ disk = io->device->disk;
+
+ if (grub_disk_is_crypto (disk))
+ {
+ switch (type & GRUB_FILE_TYPE_MASK)
+ {
+ case GRUB_FILE_TYPE_CAT:
+ case GRUB_FILE_TYPE_HEXCAT:
+ grub_error (GRUB_ERR_ACCESS_DENIED, N_("prohibited to view encrypted data"));
+ return NULL;
+ default:
+ break;
+ }
+ }
+
+ return io;
+}
+
grub_err_t
grub_cryptokey_add_or_update (const char *uuid, const char *key, grub_size_t key_len, const char *path, int is_tpmkey)
{
@@ -48,7 +76,11 @@ grub_cryptokey_add_or_update (const char *uuid, const char *key, grub_size_t key
}
if (is_tpmkey >= 0)
- cur->is_tpmkey = is_tpmkey;
+ {
+ cur->is_tpmkey = is_tpmkey;
+ if (is_tpmkey)
+ grub_file_filter_register (GRUB_FILE_FILTER_NOCAT, grub_nocat_open);
+ }
if (!cur->name)
{
@@ -121,6 +153,7 @@ GRUB_MOD_INIT(crypttab)
{
cmd = grub_register_command ("crypttab_entry", grub_cmd_crypttab_entry,
N_("VOLUME-NAME ENCRYPTED-DEVICE KEY-FILE") , N_("No description"));
+ grub_dl_set_persistent (mod);
}
GRUB_MOD_FINI(crypttab)
diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c
index 5c5fabe1a..b0c1c880d 100644
--- a/grub-core/disk/diskfilter.c
+++ b/grub-core/disk/diskfilter.c
@@ -558,6 +558,39 @@ find_lv (const char *name)
return NULL;
}
+static int
+grub_diskfilter_has_cryptodisk (const struct grub_diskfilter_lv *lv)
+{
+ struct grub_diskfilter_pv *pv;
+
+ if (!lv)
+ return 0;
+
+ if (lv->vg->pvs)
+ for (pv = lv->vg->pvs; pv; pv = pv->next)
+ {
+ if (!pv->disk)
+ {
+ grub_dprintf ("diskfilter", _("Couldn't find physical volume `%s'."
+ " Some modules may be missing from core image."),
+ pv->name);
+ continue;
+ }
+
+ switch (pv->disk->dev->id)
+ {
+ case GRUB_DISK_DEVICE_CRYPTODISK_ID:
+ return 1;
+ case GRUB_DISK_DEVICE_DISKFILTER_ID:
+ return grub_diskfilter_has_cryptodisk (pv->disk->data);
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}
+
static grub_err_t
grub_diskfilter_open (const char *name, grub_disk_t disk)
{
@@ -589,6 +622,8 @@ grub_diskfilter_open (const char *name, grub_disk_t disk)
disk->total_sectors = lv->size;
disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE;
+ disk->is_crypto_diskfilter = grub_diskfilter_has_cryptodisk (lv);
+
return 0;
}
diff --git a/include/grub/disk.h b/include/grub/disk.h
index 3b3db6222..63982f16c 100644
--- a/include/grub/disk.h
+++ b/include/grub/disk.h
@@ -147,6 +147,8 @@ struct grub_disk
/* Device-specific data. */
void *data;
+
+ int is_crypto_diskfilter;
};
typedef struct grub_disk *grub_disk_t;
@@ -314,4 +316,12 @@ void grub_mdraid1x_fini (void);
void grub_diskfilter_fini (void);
#endif
+static inline int
+grub_disk_is_crypto (grub_disk_t disk)
+{
+ return ((disk->is_crypto_diskfilter ||
+ disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID) ?
+ 1 : 0);
+}
+
#endif /* ! GRUB_DISK_HEADER */
diff --git a/include/grub/file.h b/include/grub/file.h
index fde58f0fa..fcfd32ce2 100644
--- a/include/grub/file.h
+++ b/include/grub/file.h
@@ -185,6 +185,7 @@ extern grub_disk_read_hook_t EXPORT_VAR(grub_file_progress_hook);
/* Filters with lower ID are executed first. */
typedef enum grub_file_filter_id
{
+ GRUB_FILE_FILTER_NOCAT,
GRUB_FILE_FILTER_VERIFY,
GRUB_FILE_FILTER_GZIO,
GRUB_FILE_FILTER_XZIO,
--
2.42.1

View File

@@ -1,134 +0,0 @@
From 9ad07efefe389568c2cedc77a4a6b48cb830dc0a Mon Sep 17 00:00:00 2001
From: Maxim Suhanov <dfirblog@gmail.com>
Date: Thu, 8 May 2025 19:02:08 +0200
Subject: [PATCH 2/8] commands/search: Introduce the --cryptodisk-only argument
This allows users to restrict the "search" command's scope to
encrypted disks only.
Typically, this command is used to "rebase" $root and $prefix
before loading additional configuration files via "source" or
"configfile". Unfortunately, this leads to security problems,
like CVE-2023-4001, when an unexpected, attacker-controlled
device is chosen by the "search" command.
The --cryptodisk-only argument allows users to ensure that the
file system picked is encrypted.
This feature supports the CLI authentication, blocking bypass
attempts.
Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/commands/search.c | 20 ++++++++++++++++++++
grub-core/commands/search_wrap.c | 7 ++++++-
grub-core/normal/main.c | 3 ++-
include/grub/search.h | 7 ++++---
4 files changed, 32 insertions(+), 5 deletions(-)
diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c
index 263f1501cd..f6bfef9585 100644
--- a/grub-core/commands/search.c
+++ b/grub-core/commands/search.c
@@ -86,6 +86,26 @@ iterate_device (const char *name, void *data)
grub_device_close (dev);
}
+ /* Limit to encrypted disks when requested. */
+ if (ctx->flags & SEARCH_FLAGS_CRYPTODISK_ONLY)
+ {
+ grub_device_t dev;
+
+ dev = grub_device_open (name);
+ if (dev == NULL)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ return 0;
+ }
+ if (dev->disk == NULL || dev->disk->dev->id != GRUB_DISK_DEVICE_CRYPTODISK_ID)
+ {
+ grub_device_close (dev);
+ grub_errno = GRUB_ERR_NONE;
+ return 0;
+ }
+ grub_device_close (dev);
+ }
+
#ifdef DO_SEARCH_FS_UUID
#define compare_fn grub_strcasecmp
#else
diff --git a/grub-core/commands/search_wrap.c b/grub-core/commands/search_wrap.c
index 318581f3b1..5f536006cf 100644
--- a/grub-core/commands/search_wrap.c
+++ b/grub-core/commands/search_wrap.c
@@ -41,6 +41,7 @@ static const struct grub_arg_option options[] =
ARG_TYPE_STRING},
{"no-floppy", 'n', 0, N_("Do not probe any floppy drive."), 0, 0},
{"efidisk-only", 0, 0, N_("Only probe EFI disks."), 0, 0},
+ {"cryptodisk-only", 0, 0, N_("Only probe encrypted disks."), 0, 0},
{"hint", 'h', GRUB_ARG_OPTION_REPEATABLE,
N_("First try the device HINT. If HINT ends in comma, "
"also try subpartitions"), N_("HINT"), ARG_TYPE_STRING},
@@ -75,6 +76,7 @@ enum options
SEARCH_SET,
SEARCH_NO_FLOPPY,
SEARCH_EFIDISK_ONLY,
+ SEARCH_CRYPTODISK_ONLY,
SEARCH_HINT,
SEARCH_HINT_IEEE1275,
SEARCH_HINT_BIOS,
@@ -189,6 +191,9 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args)
if (state[SEARCH_EFIDISK_ONLY].set)
flags |= SEARCH_FLAGS_EFIDISK_ONLY;
+ if (state[SEARCH_CRYPTODISK_ONLY].set)
+ flags |= SEARCH_FLAGS_CRYPTODISK_ONLY;
+
if (state[SEARCH_LABEL].set)
grub_search_label (id, var, flags, hints, nhints);
else if (state[SEARCH_FS_UUID].set)
@@ -210,7 +215,7 @@ GRUB_MOD_INIT(search)
cmd =
grub_register_extcmd ("search", grub_cmd_search,
GRUB_COMMAND_FLAG_EXTRACTOR | GRUB_COMMAND_ACCEPT_DASH,
- N_("[-f|-l|-u|-s|-n] [--hint HINT [--hint HINT] ...]"
+ N_("[-f|-l|-u|-s|-n] [--cryptodisk-only] [--hint HINT [--hint HINT] ...]"
" NAME"),
N_("Search devices by file, filesystem label"
" or filesystem UUID."
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index d1cbaa1806..320adbe337 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -647,7 +647,8 @@ static const char *features[] = {
"feature_chainloader_bpb", "feature_ntldr", "feature_platform_search_hint",
"feature_default_font_path", "feature_all_video_module",
"feature_menuentry_id", "feature_menuentry_options", "feature_200_final",
- "feature_nativedisk_cmd", "feature_timeout_style"
+ "feature_nativedisk_cmd", "feature_timeout_style",
+ "feature_search_cryptodisk_only"
};
GRUB_MOD_INIT(normal)
diff --git a/include/grub/search.h b/include/grub/search.h
index ffd2411ca1..3eabaf0ccd 100644
--- a/include/grub/search.h
+++ b/include/grub/search.h
@@ -21,9 +21,10 @@
enum search_flags
{
- SEARCH_FLAGS_NONE = 0,
- SEARCH_FLAGS_NO_FLOPPY = 1,
- SEARCH_FLAGS_EFIDISK_ONLY = 2
+ SEARCH_FLAGS_NONE = 0,
+ SEARCH_FLAGS_NO_FLOPPY = 1,
+ SEARCH_FLAGS_EFIDISK_ONLY = 2,
+ SEARCH_FLAGS_CRYPTODISK_ONLY = 4
};
void grub_search_fs_file (const char *key, const char *var,
--
2.49.0

View File

@@ -1,34 +0,0 @@
From daec67a7ea73b859e1e0b6a4e9122157c7525676 Mon Sep 17 00:00:00 2001
From: B Horn <b@horn.uk>
Date: Sun, 12 May 2024 02:03:33 +0100
Subject: [PATCH 02/20] fs/ufs: Fix a heap OOB write
grub_strcpy() was used to copy a symlink name from the filesystem
image to a heap allocated buffer. This led to a OOB write to adjacent
heap allocations. Fix by using grub_strlcpy().
Fixes: CVE-2024-45781
Reported-by: B Horn <b@horn.uk>
Signed-off-by: B Horn <b@horn.uk>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/ufs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c
index a354c92d93..01235101b4 100644
--- a/grub-core/fs/ufs.c
+++ b/grub-core/fs/ufs.c
@@ -463,7 +463,7 @@ grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino)
/* Check against zero is paylindromic, no need to swap. */
if (data->inode.nblocks == 0
&& INODE_SIZE (data) <= sizeof (data->inode.symlink))
- grub_strcpy (symlink, (char *) data->inode.symlink);
+ grub_strlcpy (symlink, (char *) data->inode.symlink, sz);
else
{
if (grub_ufs_read_file (data, 0, 0, 0, sz, symlink) < 0)
--
2.48.1

View File

@@ -1,52 +0,0 @@
From 3a69e9126d532214d940c1386f2933a124611a6c Mon Sep 17 00:00:00 2001
From: Egor Ignatov <egori@altlinux.org>
Date: Thu, 23 Jan 2025 20:44:14 +0300
Subject: [PATCH 2/3] fs/xfs: Fix grub_xfs_iterate_dir() return value in case
of failure
Commit ef7850c757 (fs/xfs: Fix issues found while fuzzing the XFS
filesystem) introduced multiple boundary checks in grub_xfs_iterate_dir()
but handled the error incorrectly returning error code instead of 0.
Fix it. Also change the error message so that it doesn't match the
message in grub_xfs_read_inode().
Fixes: ef7850c757 (fs/xfs: Fix issues found while fuzzing the XFS filesystem)
Signed-off-by: Egor Ignatov <egori@altlinux.org>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/xfs.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
index e3a69fe498..30e3e7f6d9 100644
--- a/grub-core/fs/xfs.c
+++ b/grub-core/fs/xfs.c
@@ -859,7 +859,11 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
grub_uint8_t c;
if ((inopos + (smallino ? 4 : 8)) > (grub_uint8_t *) dir + grub_xfs_fshelp_size (dir->data))
- return grub_error (GRUB_ERR_BAD_FS, "not a correct XFS inode");
+ {
+ grub_error (GRUB_ERR_BAD_FS, "invalid XFS inode");
+ return 0;
+ }
+
/* inopos might be unaligned. */
if (smallino)
@@ -968,7 +972,10 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
filename = (char *)(direntry + 1);
if (filename + direntry->len + 1 > (char *) end)
- return grub_error (GRUB_ERR_BAD_FS, "invalid XFS directory entry");
+ {
+ grub_error (GRUB_ERR_BAD_FS, "invalid XFS directory entry");
+ return 0;
+ }
/* The byte after the filename is for the filetype, padding, or
tag, which is not used by GRUB. So it can be overwritten. */
--
2.48.1

View File

@@ -1,65 +0,0 @@
From 6704d7715b6303f4b7e2cb9da7c6dcc3bfdd5726 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 14 Jul 2025 22:10:18 +0800
Subject: [PATCH 2/4] http: Return HTTP status code in http_establish
Previously, using "test -s ..." or "test -f ..." on files served via
HTTP would always return true, regardless of whether the target file
actually existed. This is incorrect behavior, whereas the same tests
work as expected with TFTP.
The issue stems from http_establish returning success (GRUB_ERR_NONE) as
long as the HTTP connection was established, without considering the
HTTP status code returned in the response. As a result, http_open would
always report success, discarding error responses such as 404 Not Found.
The patch makes http_establish to return the HTTP status code as its
return value when an error or unknown status code is encountered. It
also sets data->first_line_recv = 1 in the parse_line()'s error code
path to correctly reflect the parsing state and prevent reprocessing.
With this change, both -s and -f tests now behave correctly when used
with the HTTP protocol, as http_establish returns error for failed HTTP
status codes as well. As a result, http_open is no longer considered
successful solely based on establishing the connection, it now also
takes the HTTP status code into account.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/net/http.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/grub-core/net/http.c b/grub-core/net/http.c
index 686949c17..c5509dc45 100644
--- a/grub-core/net/http.c
+++ b/grub-core/net/http.c
@@ -125,6 +125,7 @@ parse_line (grub_file_t file, http_data_t data, char *ptr, grub_size_t len)
case 404:
data->err = GRUB_ERR_FILE_NOT_FOUND;
data->errmsg = grub_xasprintf (_("file `%s' not found"), data->filename);
+ data->first_line_recv = 1;
return GRUB_ERR_NONE;
default:
data->err = GRUB_ERR_NET_UNKNOWN_ERROR;
@@ -132,6 +133,7 @@ parse_line (grub_file_t file, http_data_t data, char *ptr, grub_size_t len)
valid answers like 403 will trigger this very generic message. */
data->errmsg = grub_xasprintf (_("unsupported HTTP error %d: %s"),
code, ptr);
+ data->first_line_recv = 1;
return GRUB_ERR_NONE;
}
data->first_line_recv = 1;
@@ -444,6 +446,10 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
}
return grub_error (GRUB_ERR_TIMEOUT, N_("time out opening `%s'"), data->filename);
}
+
+ if (data->err)
+ return grub_error (data->err, N_("%s"), data->errmsg);
+
return GRUB_ERR_NONE;
}
--
2.50.0

View File

@@ -1,216 +0,0 @@
From ec0951f742d03f585454f0a50f588fc7ea42a257 Mon Sep 17 00:00:00 2001
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Date: Mon, 24 Feb 2025 18:40:11 +0530
Subject: [PATCH 2/9] ieee1275: Platform Keystore (PKS) Support
enhancing the infrastructure to enable the Platform Keystore (PKS) feature,
which provides access to the SB VERSION, DB, and DBX secure boot variables
from PKS.
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
---
grub-core/Makefile.am | 1 +
grub-core/Makefile.core.def | 1 +
grub-core/kern/powerpc/ieee1275/ieee1275.c | 140 +++++++++++++++++++++
include/grub/powerpc/ieee1275/ieee1275.h | 14 +++
4 files changed, 156 insertions(+)
create mode 100644 grub-core/kern/powerpc/ieee1275/ieee1275.c
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index 9d3d5f5193..40ed353aba 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -241,6 +241,7 @@ KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
endif
if COND_powerpc_ieee1275
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/powerpc/ieee1275/ieee1275.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/alloc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index e1698a6923..1dfcf5f991 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -328,6 +328,7 @@ kernel = {
extra_dist = video/sis315_init.c;
mips_loongson = commands/keylayouts.c;
+ powerpc_ieee1275 = kern/powerpc/ieee1275/ieee1275.c;
powerpc_ieee1275 = kern/powerpc/cache.S;
powerpc_ieee1275 = kern/powerpc/dl.c;
powerpc_ieee1275 = kern/powerpc/compiler-rt.S;
diff --git a/grub-core/kern/powerpc/ieee1275/ieee1275.c b/grub-core/kern/powerpc/ieee1275/ieee1275.c
new file mode 100644
index 0000000000..f685afcfff
--- /dev/null
+++ b/grub-core/kern/powerpc/ieee1275/ieee1275.c
@@ -0,0 +1,140 @@
+/* of.c - Access the Open Firmware client interface. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <grub/ieee1275/ieee1275.h>
+#include <grub/powerpc/ieee1275/ieee1275.h>
+#include <grub/misc.h>
+
+#define IEEE1275_CELL_INVALID ((grub_ieee1275_cell_t) - 1)
+
+int
+grub_ieee1275_test (const char *name, grub_ieee1275_cell_t *missing)
+{
+ struct test_args
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t name;
+ grub_ieee1275_cell_t missing;
+ } args;
+
+ INIT_IEEE1275_COMMON (&args.common, "test", 1, 1);
+ args.name = (grub_ieee1275_cell_t) name;
+
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+ return -1;
+
+ if (args.missing == IEEE1275_CELL_INVALID)
+ return -1;
+
+ *missing = args.missing;
+
+ return 0;
+}
+
+int
+grub_ieee1275_pks_max_object_size (grub_size_t *result)
+{
+ struct mos_args
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t size;
+ } args;
+
+ INIT_IEEE1275_COMMON (&args.common, "pks-max-object-size", 0, 1);
+
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+ return -1;
+
+ if (args.size == IEEE1275_CELL_INVALID)
+ return -1;
+
+ *result = args.size;
+
+ return 0;
+}
+
+int
+grub_ieee1275_pks_read_object (grub_uint8_t consumer, grub_uint8_t *label,
+ grub_size_t label_len, grub_uint8_t *buffer,
+ grub_size_t buffer_len, grub_size_t *data_len,
+ grub_uint32_t *policies)
+{
+ struct pks_read_args
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t consumer;
+ grub_ieee1275_cell_t label;
+ grub_ieee1275_cell_t label_len;
+ grub_ieee1275_cell_t buffer;
+ grub_ieee1275_cell_t buffer_len;
+ grub_ieee1275_cell_t data_len;
+ grub_ieee1275_cell_t policies;
+ grub_ieee1275_cell_t rc;
+ } args;
+
+ INIT_IEEE1275_COMMON (&args.common, "pks-read-object", 5, 3);
+ args.consumer = (grub_ieee1275_cell_t) consumer;
+ args.label = (grub_ieee1275_cell_t) label;
+ args.label_len = (grub_ieee1275_cell_t) label_len;
+ args.buffer = (grub_ieee1275_cell_t) buffer;
+ args.buffer_len = (grub_ieee1275_cell_t) buffer_len;
+
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+ return -1;
+
+ if (args.data_len == IEEE1275_CELL_INVALID)
+ return -1;
+
+ *data_len = args.data_len;
+ *policies = args.policies;
+
+ return (int) args.rc;
+}
+
+int
+grub_ieee1275_pks_read_sbvar (grub_uint8_t sbvarflags, grub_uint8_t sbvartype,
+ grub_uint8_t *buffer, grub_size_t buffer_len,
+ grub_size_t *data_len)
+{
+ struct pks_read_sbvar_args
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t sbvarflags;
+ grub_ieee1275_cell_t sbvartype;
+ grub_ieee1275_cell_t buffer;
+ grub_ieee1275_cell_t buffer_len;
+ grub_ieee1275_cell_t data_len;
+ grub_ieee1275_cell_t rc;
+ } args;
+
+ INIT_IEEE1275_COMMON (&args.common, "pks-read-sbvar", 4, 2);
+ args.sbvarflags = (grub_ieee1275_cell_t) sbvarflags;
+ args.sbvartype = (grub_ieee1275_cell_t) sbvartype;
+ args.buffer = (grub_ieee1275_cell_t) buffer;
+ args.buffer_len = (grub_ieee1275_cell_t) buffer_len;
+
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+ return -1;
+
+ if (args.data_len == IEEE1275_CELL_INVALID)
+ return -1;
+
+ *data_len = args.data_len;
+
+ return (int) args.rc;
+}
diff --git a/include/grub/powerpc/ieee1275/ieee1275.h b/include/grub/powerpc/ieee1275/ieee1275.h
index 4eb2070188..0d48331c26 100644
--- a/include/grub/powerpc/ieee1275/ieee1275.h
+++ b/include/grub/powerpc/ieee1275/ieee1275.h
@@ -28,4 +28,18 @@ typedef grub_uint32_t grub_ieee1275_cell_t;
#define PRIxGRUB_IEEE1275_CELL_T PRIxGRUB_UINT32_T
#define PRIuGRUB_IEEE1275_CELL_T PRIuGRUB_UINT32_T
+int EXPORT_FUNC (grub_ieee1275_test) (const char *name,
+ grub_ieee1275_cell_t *missing);
+
+int grub_ieee1275_pks_max_object_size (grub_size_t *result);
+
+int grub_ieee1275_pks_read_object (grub_uint8_t consumer, grub_uint8_t *label,
+ grub_size_t label_len, grub_uint8_t *buffer,
+ grub_size_t buffer_len, grub_size_t *data_len,
+ grub_uint32_t *policies);
+
+int grub_ieee1275_pks_read_sbvar (grub_uint8_t sbvarflags, grub_uint8_t sbvartype,
+ grub_uint8_t *buffer, grub_size_t buffer_len,
+ grub_size_t *data_len);
+
#endif /* ! GRUB_IEEE1275_MACHINE_HEADER */
--
2.48.1

View File

@@ -1,20 +1,16 @@
From ba5fee5cdbe6fa4871419c54008a7efb87d99e23 Mon Sep 17 00:00:00 2001
From: Avnish Chouhan <avnish@linux.ibm.com>
Date: Fri, 30 Aug 2024 17:11:04 +0530
Subject: [PATCH 2/3] ieee1275: ofpath enable NVMeoF logical device translate
From 9e61624db77e5073961126457f599bc70e877fd1 Mon Sep 17 00:00:00 2001
From: Diego Domingos <diegodo@br.ibm.com>
Date: Tue, 15 Mar 2022 15:59:41 -0400
Subject: [PATCH 2/4] ieee1275/ofpath: enable NVMeoF logical device translation
This patch adds code to enable the translation of logical devices to the of NVMeoFC paths.
Signed-off-by: Diego Domingos <diegodo@br.ibm.com>
Signed-off-by: Avnish Chouhan <avnish@linux.ibm.com>
Link: https://lore.kernel.org/r/20240830114104.32234-6-avnish@linux.ibm.com
This patch add code to enable the translation of logical devices to the of NVMeoFC paths.
---
grub-core/osdep/linux/ofpath.c | 370 ++++++++++++++++++++++++++++++++-
include/grub/util/ofpath.h | 28 +++
2 files changed, 389 insertions(+), 9 deletions(-)
grub-core/osdep/linux/ofpath.c | 260 +++++++++++++++++++++++++++++++--
include/grub/util/ofpath.h | 29 ++++
2 files changed, 280 insertions(+), 9 deletions(-)
diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
index 89beceef4a..dd50d785dd 100644
index 89beceef4..212782d3f 100644
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -137,7 +137,7 @@ trim_newline (char *path)
@@ -26,358 +22,261 @@ index 89beceef4a..dd50d785dd 100644
static char *
find_obppath (const char *sysfs_path_orig)
@@ -313,6 +313,91 @@ get_basename(char *p)
@@ -313,6 +313,69 @@ get_basename(char *p)
return ret;
}
+int
+add_filename_to_pile (char *filename, struct ofpath_files_list_root* root)
+{
+ struct ofpath_files_list_node* file;
+
+ file = malloc (sizeof (struct ofpath_files_list_node));
+ if (!file)
+ return -1;
+void
+add_filename_to_pile(char *filename, struct ofpath_files_list_root* root){
+ struct ofpath_files_list_node* file;
+
+ file->filename = malloc (sizeof (char) * 1024);
+ if (!file->filename)
+ {
+ free (file);
+ return -1;
+ }
+ file = malloc(sizeof(struct ofpath_files_list_node));
+
+ grub_strcpy (file->filename, filename);
+ if (root->first == NULL)
+ {
+ file->filename = filename;
+
+ if(root->first == NULL){
+ root->items = 1;
+ root->first = file;
+ file->next = NULL;
+ }
+ else
+ {
+ } else {
+ root->items++;
+ file->next = root->first;
+ root->first = file;
+ }
+
+ return 0;
+}
+
+
+void
+find_file (char* filename, char* directory, struct ofpath_files_list_root* root, int max_depth, int depth)
+{
+ struct dirent *ep;
+ struct stat statbuf;
+ DIR *dp;
+ int ret_val=0;
+ char* full_path;
+find_file(char* filename, char* directory, struct ofpath_files_list_root* root, int max_depth, int depth){
+ struct dirent *ep;
+ struct stat statbuf;
+ DIR *dp;
+
+ if (depth > max_depth)
+ {
+ return;
+ }
+ if(depth > max_depth){
+ return;
+ }
+
+ if ((dp = opendir (directory)) == NULL)
+ {
+ return;
+ }
+
+ full_path = malloc (1024 * sizeof (char));
+ if (!full_path)
+ if((dp = opendir(directory)) == NULL){
+
+ return;
+ }
+
+ while ((ep = readdir(dp)) != NULL)
+ {
+ snprintf (full_path, 1024, "%s/%s", directory, ep->d_name);
+ lstat (full_path, &statbuf);
+ while((ep = readdir(dp)) != NULL){
+
+ if (S_ISLNK (statbuf.st_mode))
+ {
+ continue;
+ }
+ char* full_path = malloc(1024*sizeof(char));
+ snprintf(full_path,1024,"%s/%s",directory,ep->d_name);
+
+ if (!strcmp (ep->d_name, ".") || !strcmp(ep->d_name, ".."))
+ {
+ continue;
+ }
+ lstat(full_path,&statbuf);
+
+ if (!strcmp (ep->d_name, filename))
+ {
+ ret_val = add_filename_to_pile (full_path, root);
+ if (ret_val == -1)
+ continue;
+ }
+ if(S_ISLNK(statbuf.st_mode)){
+
+ continue;
+ }
+
+ find_file (filename, full_path, root, max_depth, depth+1);
+ }
+ if(!strcmp(ep->d_name,".") || !strcmp(ep->d_name,"..")){
+ continue;
+ }
+
+ free (full_path);
+ closedir (dp);
+ if(!strcmp(ep->d_name,filename)){
+ add_filename_to_pile(full_path, root);
+ }
+
+ find_file(filename, full_path, root, max_depth, depth+1);
+
+ }
+ closedir(dp);
+}
+
+
static char *
of_path_of_vdisk(const char *sys_devname __attribute__((unused)),
const char *device,
@@ -351,7 +436,200 @@ of_path_of_ide(const char *sys_devname __attribute__((unused)), const char *devi
@@ -351,7 +414,142 @@ of_path_of_ide(const char *sys_devname __attribute__((unused)), const char *devi
return ret;
}
-#ifdef __sparc__
+void
+free_ofpath_files_list (struct ofpath_files_list_root* root)
+{
+ struct ofpath_files_list_node* node = root->first;
+ struct ofpath_files_list_node* next;
+
+ while (node!=NULL)
+ {
+ next = node->next;
+ free (node->filename);
+ free (node);
+ node = next;
+ }
+
+ free (root);
+ return;
+}
+
+char*
+of_find_fc_host (char* host_wwpn)
+{
+of_find_fc_host(char* host_wwpn){
+
+ FILE* fp;
+ char *buf;
+ char *ret_val;
+ char portname_filename[sizeof ("port_name")] = "port_name";
+ char devices_path[sizeof ("/sys/devices")] = "/sys/devices";
+ char portname_filename[sizeof("port_name")] = "port_name";
+ char devices_path[sizeof("/sys/devices")] = "/sys/devices";
+
+ struct ofpath_files_list_root* portnames_file_list;
+ struct ofpath_files_list_node* node;
+
+ ret_val = malloc (sizeof (char) * 1024);
+ if (!ret_val)
+ return NULL;
+ portnames_file_list=malloc(sizeof(portnames_file_list));
+ portnames_file_list->items=0;
+ portnames_file_list->first=NULL;
+
+ portnames_file_list = malloc (sizeof (struct ofpath_files_list_root));
+ if (!portnames_file_list)
+ {
+ free (ret_val);
+ return NULL;
+ }
+
+ portnames_file_list->items = 0;
+ portnames_file_list->first = NULL;
+ find_file (portname_filename, devices_path, portnames_file_list, 10, 0);
+ node = portnames_file_list->first;
+
+ while (node != NULL)
+ {
+ fp = fopen(node->filename, "r");
+ buf = malloc (sizeof (char) * 512);
+ if (!buf)
+ break;
+
+ fscanf (fp, "%s", buf);
+ fclose (fp);
+
+ if ((strcmp (buf, host_wwpn) == 0) && grub_strstr (node->filename, "fc_host"))
+ {
+ free (buf);
+ grub_strcpy (ret_val, node->filename);
+ free_ofpath_files_list (portnames_file_list);
+ return ret_val;
+ }
+ find_file(portname_filename, devices_path, portnames_file_list, 10, 0);
+
+ struct ofpath_files_list_node* node = portnames_file_list->first;
+ while(node != NULL){
+ fp = fopen(node->filename,"r");
+ buf = malloc(sizeof(char)*512);
+ fscanf(fp, "%s", buf);
+ fclose(fp);
+ if((strcmp(buf,host_wwpn) == 0) && grub_strstr(node->filename, "fc_host")){
+ return node->filename;
+ }
+ node = node->next;
+ free (buf);
+ }
+ free_ofpath_files_list (portnames_file_list);
+ free (ret_val);
+ }
+
+ return NULL;
+}
+
+int
+of_path_get_nvmeof_adapter_info (char* sysfs_path,
+ struct ofpath_nvmeof_info* nvmeof_info)
+{
+void
+of_path_get_nvmeof_adapter_info(char* sysfs_path,
+ struct ofpath_nvmeof_info* nvmeof_info){
+
+ FILE *fp;
+ char *buf, *buf2, *buf3;
+
+ nvmeof_info->host_wwpn = malloc (sizeof (char) * 256);
+ nvmeof_info->target_wwpn = malloc (sizeof (char) * 256);
+ nvmeof_info->nqn = malloc (sizeof (char) * 256);
+ nvmeof_info->host_wwpn = malloc(sizeof(char)*256);
+ nvmeof_info->target_wwpn = malloc(sizeof(char)*256);
+ nvmeof_info->nqn = malloc(sizeof(char)*256);
+
+ if (nvmeof_info->host_wwpn == NULL || nvmeof_info->target_wwpn == NULL || nvmeof_info->nqn == NULL)
+ {
+ free (nvmeof_info->host_wwpn);
+ free (nvmeof_info->target_wwpn);
+ free (nvmeof_info->nqn);
+ return -1;
+ }
+ buf = malloc(sizeof(char)*512);
+ snprintf(buf,512,"%s/subsysnqn",sysfs_path);
+ fp = fopen(buf,"r");
+ fscanf(fp, "%s", nvmeof_info->nqn);
+ fclose(fp);
+
+ buf = malloc (sizeof (char) * 512);
+ if (!buf)
+ {
+ free (nvmeof_info->host_wwpn);
+ free (nvmeof_info->target_wwpn);
+ free (nvmeof_info->nqn);
+ return -1;
+ }
+ snprintf(buf,512,"%s/cntlid",sysfs_path);
+ fp = fopen(buf,"r");
+ fscanf(fp, "%u", &(nvmeof_info->cntlid));
+ fclose(fp);
+
+ snprintf (buf, 512, "%s/subsysnqn", sysfs_path);
+ fp = fopen (buf, "r");
+ fscanf (fp, "%s", nvmeof_info->nqn);
+ fclose (fp);
+ //snprintf(buf,512,"%s/nsid",sysfs_path);
+ //fp = fopen(buf,"r");
+ //fscanf(fp, "%u", &(nvmeof_info->nsid));
+ //fclose(fp);
+
+ snprintf (buf, 512, "%s/cntlid", sysfs_path);
+ fp = fopen (buf, "r");
+ fscanf (fp, "%u", &(nvmeof_info->cntlid));
+ fclose (fp);
+ snprintf(buf,512,"%s/address",sysfs_path);
+ fp = fopen(buf,"r");
+ buf2 = malloc(sizeof(char)*512);
+ fscanf(fp, "%s", buf2);
+ fclose(fp);
+
+ snprintf (buf, 512, "%s/address", sysfs_path);
+ fp = fopen (buf, "r");
+ buf2 = malloc (sizeof (char) * 512);
+ nvmeof_info->host_wwpn = strrchr(buf2,'-')+1;
+
+ if (!buf2)
+ {
+ free (nvmeof_info->host_wwpn);
+ free (nvmeof_info->target_wwpn);
+ free (nvmeof_info->nqn);
+ free (buf);
+ return -1;
+ }
+
+ fscanf (fp, "%s", buf2);
+ fclose (fp);
+
+ buf3 = strrchr (buf2, '-') + 1;
+ grub_memcpy (nvmeof_info->host_wwpn, buf3, 256);
+ buf3=strchr (buf2, '-') + 1;
+ buf3=strchr (buf3, '-') + 1;
+ buf3=strchr (buf3, 'x') + 1;
+ grub_memcpy (nvmeof_info->target_wwpn, buf3, 256);
+ buf3 = strchr (nvmeof_info->target_wwpn, ',');
+ buf3=strchr(buf2,'-')+1;
+ buf3=strchr(buf3,'-')+1;
+ nvmeof_info->target_wwpn = buf3;
+ buf3 = strchr(nvmeof_info->target_wwpn,',');
+ *buf3 = '\0';
+ free (buf);
+ free (buf2);
+ return 0;
+
+
+ free(buf);
+
+ return;
+}
+
+#define MAX_NVME_NSID_DIGITS 6
+
+static char *
+of_path_get_nvme_controller_name_node (const char* devname)
+of_path_get_nvme_controller_name_node(const char* devname)
+{
+ char *controller_node, *end;
+
+ controller_node = strdup (devname);
+ end = grub_strchr (controller_node + 1, 'n');
+ if (end != NULL)
+ {
+ *end = '\0';
+ }
+ controller_node = strdup(devname);
+
+ end = grub_strchr(controller_node+1, 'n');
+
+ if(end != NULL){
+ *end = '\0';
+ }
+
+ return controller_node;
+}
+
+unsigned int
+of_path_get_nvme_nsid (const char* devname)
+of_path_get_nvme_nsid(const char* devname)
+{
+ unsigned int nsid;
+ char *sysfs_path, *buf;
+ FILE *fp;
+
+ buf = malloc (sizeof(char) * 512);
+ if (!buf)
+ return 0;
+
+ buf=malloc(sizeof(char)*512);
+
+ sysfs_path = block_device_get_sysfs_path_and_link (devname);
+ snprintf (buf, 512, "%s/%s/nsid", sysfs_path, devname);
+ fp = fopen(buf, "r");
+ fscanf (fp, "%u", &(nsid));
+ fclose (fp);
+
+ free (sysfs_path);
+ free (buf);
+ snprintf(buf,512,"%s/%s/nsid",sysfs_path,devname);
+ fp = fopen(buf,"r");
+ fscanf(fp, "%u", &(nsid));
+ fclose(fp);
+
+ free(sysfs_path);
+ free(buf);
+
+ return nsid;
+
+}
+
+static char *
+nvme_get_syspath (const char *nvmedev)
+nvme_get_syspath(const char *nvmedev)
+{
+ char *sysfs_path, *controller_node;
+
+ sysfs_path = block_device_get_sysfs_path_and_link (nvmedev);
+ if (strstr (sysfs_path, "nvme-subsystem"))
+ {
+ controller_node = of_path_get_nvme_controller_name_node (nvmedev);
+ strcat (sysfs_path, "/");
+ strcat (sysfs_path, controller_node);
+ sysfs_path = xrealpath (sysfs_path);
+ }
+
+ if(strstr(sysfs_path,"nvme-subsystem")){
+ controller_node = of_path_get_nvme_controller_name_node(nvmedev);
+ strcat(sysfs_path,"/");
+ strcat(sysfs_path,controller_node);
+ sysfs_path = xrealpath(sysfs_path);
+ }
+
+ return sysfs_path;
+}
+
+
static char *
of_path_of_nvme(const char *sys_devname __attribute__((unused)),
const char *device,
@@ -360,6 +638,8 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
@@ -360,6 +558,7 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
{
char *sysfs_path, *of_path, disk[MAX_DISK_CAT];
const char *digit_string, *part_end;
+ int chars_written, ret_val;
+ struct ofpath_nvmeof_info* nvmeof_info;
+ int chars_written;
digit_string = trailing_digits (device);
part_end = devicenode + strlen (devicenode) - 1;
@@ -379,15 +659,90 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
@@ -379,15 +578,61 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
/* Remove the p. */
*end = '\0';
sscanf (digit_string, "%d", &part);
- snprintf (disk, sizeof (disk), "/disk@1:%c", 'a' + (part - 1));
- sysfs_path = block_device_get_sysfs_path_and_link (nvmedev);
+ sysfs_path = nvme_get_syspath (nvmedev);
+
+ sysfs_path = nvme_get_syspath(nvmedev);
+
+ /* If is a NVMeoF */
+ if (strstr (sysfs_path, "nvme-fabrics"))
+ {
+ nvmeof_info = malloc (sizeof (struct ofpath_nvmeof_info));
+ if (!nvmeof_info)
+ {
+ free (nvmedev);
+ return NULL;
+ }
+ if(strstr(sysfs_path,"nvme-fabrics")){
+ struct ofpath_nvmeof_info* nvmeof_info;
+ nvmeof_info = malloc(sizeof(nvmeof_info));
+
+ ret_val = of_path_get_nvmeof_adapter_info (sysfs_path, nvmeof_info);
+ if (ret_val == -1)
+ {
+ free (nvmedev);
+ free (nvmeof_info);
+ return NULL;
+ }
+ of_path_get_nvmeof_adapter_info(sysfs_path, nvmeof_info);
+
+ sysfs_path = of_find_fc_host (nvmeof_info->host_wwpn);
+ if (!sysfs_path)
+ {
+ free (nvmedev);
+ free (nvmeof_info);
+ return NULL;
+ }
+ sysfs_path = of_find_fc_host(nvmeof_info->host_wwpn);
+
+ chars_written = snprintf (disk,sizeof(disk), "/nvme-of/controller@%s,%x:nqn=%s",
+ nvmeof_info->target_wwpn,0xffff,
+ nvmeof_info->nqn);
+ unsigned int nsid = of_path_get_nvme_nsid (nvmedev);
+ if (nsid)
+ {
+ snprintf (disk+chars_written, sizeof("/namespace@") + MAX_NVME_NSID_DIGITS,
+ "/namespace@%x:%d", nsid, part);
+ }
+ free (nvmeof_info);
+ }
+ else
+ {
+ snprintf (disk, sizeof (disk), "/disk@1:%c", 'a' + (part - 1));
+ chars_written = snprintf(disk,sizeof(disk),"/nvme-of/controller@%s,%x:nqn=%s",
+ nvmeof_info->target_wwpn,
+ 0xffff,
+ nvmeof_info->nqn);
+
+ unsigned int nsid = of_path_get_nvme_nsid(nvmedev);
+
+ if(nsid){
+ snprintf(disk+chars_written,sizeof(disk) - chars_written,
+ "/namespace@%x:%d",nsid, part);
+ }
+
+ } else {
+ snprintf (disk, sizeof (disk), "/disk@1:%c", 'a' + (part - 1));
+ }
free (nvmedev);
}
else
@@ -386,45 +285,32 @@ index 89beceef4a..dd50d785dd 100644
- snprintf (disk, sizeof (disk), "/disk@1");
- sysfs_path = block_device_get_sysfs_path_and_link (device);
+ sysfs_path = nvme_get_syspath (device);
+ if (strstr (sysfs_path, "nvme-fabrics"))
+ {
+ nvmeof_info = malloc (sizeof (struct ofpath_nvmeof_info));
+ if (!nvmeof_info)
+ return NULL;
+ if(strstr(sysfs_path,"nvme-fabrics")){
+ struct ofpath_nvmeof_info* nvmeof_info;
+ nvmeof_info = malloc(sizeof(nvmeof_info));
+
+ ret_val = of_path_get_nvmeof_adapter_info (sysfs_path, nvmeof_info);
+ if (ret_val == -1)
+ {
+ free (nvmeof_info);
+ return NULL;
+ }
+ of_path_get_nvmeof_adapter_info(sysfs_path, nvmeof_info);
+
+ sysfs_path = of_find_fc_host(nvmeof_info->host_wwpn);
+
+ sysfs_path = of_find_fc_host (nvmeof_info->host_wwpn);
+ if (!sysfs_path)
+ {
+ free (nvmeof_info);
+ return NULL;
+ }
+ chars_written = snprintf(disk,sizeof(disk),"/nvme-of/controller@%s,%x:nqn=%s",
+ nvmeof_info->target_wwpn,
+ 0xffff,
+ nvmeof_info->nqn);
+
+ unsigned int nsid = of_path_get_nvme_nsid(device);
+ if(nsid){
+ snprintf(disk+chars_written,sizeof(disk) - chars_written,
+ "/namespace@%x",nsid);
+ }
+ } else {
+ snprintf (disk, sizeof (disk), "/disk@1");
+ }
+
+ chars_written = snprintf (disk,sizeof(disk), "/nvme-of/controller@%s,%x:nqn=%s",
+ nvmeof_info->target_wwpn, 0xffff,
+ nvmeof_info->nqn);
+ unsigned int nsid = of_path_get_nvme_nsid (device);
+ if (nsid)
+ {
+ snprintf (disk+chars_written,sizeof("/namespace@") + sizeof(char) * MAX_NVME_NSID_DIGITS,
+ "/namespace@%x", nsid);
+ }
+ free (nvmeof_info);
+ }
+ else
+ {
+ snprintf (disk, sizeof (disk), "/disk@1");
+ }
}
of_path = find_obppath (sysfs_path);
@@ -398,7 +753,6 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
@@ -398,7 +643,6 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
free (sysfs_path);
return of_path;
}
@@ -432,7 +318,7 @@ index 89beceef4a..dd50d785dd 100644
static void
of_fc_port_name(const char *path, const char *subpath, char *port_name)
@@ -840,11 +1194,9 @@ grub_util_devname_to_ofpath (const char *sys_devname)
@@ -840,11 +1084,9 @@ grub_util_devname_to_ofpath (const char *sys_devname)
/* All the models I've seen have a devalias "floppy".
New models have no floppy at all. */
ofpath = xstrdup ("floppy");
@@ -445,27 +331,24 @@ index 89beceef4a..dd50d785dd 100644
{
grub_util_warn (_("unknown device type %s"), device);
diff --git a/include/grub/util/ofpath.h b/include/grub/util/ofpath.h
index b43c523cb2..7ab377c7cc 100644
index b43c523cb..a0ec30620 100644
--- a/include/grub/util/ofpath.h
+++ b/include/grub/util/ofpath.h
@@ -3,4 +3,32 @@
@@ -3,4 +3,33 @@
char *grub_util_devname_to_ofpath (const char *devname);
+struct ofpath_files_list_node
+{
+struct ofpath_files_list_node {
+ char* filename;
+ struct ofpath_files_list_node* next;
+};
+
+struct ofpath_files_list_root
+{
+struct ofpath_files_list_root {
+ int items;
+ struct ofpath_files_list_node* first;
+};
+
+struct ofpath_nvmeof_info
+{
+struct ofpath_nvmeof_info {
+ char* host_wwpn;
+ char* target_wwpn;
+ char* nqn;
@@ -473,14 +356,18 @@ index b43c523cb2..7ab377c7cc 100644
+ int nsid;
+};
+
+int of_path_get_nvmeof_adapter_info (char* sysfs_path, struct ofpath_nvmeof_info* nvmeof_info);
+unsigned int of_path_get_nvme_nsid (const char* devname);
+int add_filename_to_pile (char *filename, struct ofpath_files_list_root* root);
+void find_file (char* filename, char* directory, struct ofpath_files_list_root* root, int max_depth, int depth);
+char* of_find_fc_host (char* host_wwpn);
+void free_ofpath_files_list (struct ofpath_files_list_root* root);
+void of_path_get_nvmeof_adapter_info(char* sysfs_path,
+ struct ofpath_nvmeof_info* nvmeof_info);
+
+unsigned int of_path_get_nvme_nsid(const char* devname);
+
+void add_filename_to_pile(char *filename, struct ofpath_files_list_root* root);
+
+void find_file(char* filename, char* directory, struct ofpath_files_list_root* root, int max_depth, int depth);
+
+char* of_find_fc_host(char* host_wwpn);
+
#endif /* ! GRUB_OFPATH_MACHINE_UTIL_HEADER */
--
2.48.1
2.35.3

View File

@@ -1,31 +0,0 @@
From 29d1bd2a96948bc120cb5906188117f670797fcf Mon Sep 17 00:00:00 2001
From: Stefan Berger <stefanb@linux.ibm.com>
Date: Tue, 26 Nov 2024 15:39:41 -0500
Subject: [PATCH 2/7] term/ieee1275/serial: Cast 0 to proper type
Cast 0 to proper type grub_ieee1275_ihandle_t. This type is
used for struct grub_serial_port's handle that assigns or
compares with IEEE1275_IHANDLE_INVALID.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/term/ieee1275/serial.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/term/ieee1275/serial.c b/grub-core/term/ieee1275/serial.c
index 0e4cac4c4..9bc44b306 100644
--- a/grub-core/term/ieee1275/serial.c
+++ b/grub-core/term/ieee1275/serial.c
@@ -25,7 +25,7 @@
#include <grub/i18n.h>
#include <grub/ieee1275/console.h>
-#define IEEE1275_IHANDLE_INVALID ((grub_ieee1275_cell_t) 0)
+#define IEEE1275_IHANDLE_INVALID ((grub_ieee1275_ihandle_t) 0)
struct ofserial_hash_ent
{
--
2.43.0

File diff suppressed because it is too large Load Diff

View File

@@ -1,84 +0,0 @@
From 46c9f3a8dac5274c8d117ea131ca5c5842f9276f Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Mon, 7 Apr 2025 16:29:16 +0800
Subject: [PATCH 2/7] tpm2_key_protector: Add tpm2_dump_pcr command
The user may need to inspect the TPM 2.0 PCR values with the GRUB shell,
so the new tpm2_dump_pcr command is added to print all PCRs of the
specified bank.
Also update the document for the new command.
Signed-off-by: Gary Lin <glin@suse.com>
Tested-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
docs/grub.texi | 13 +++++++
.../commands/tpm2_key_protector/module.c | 35 +++++++++++++++++++
2 files changed, 48 insertions(+)
Index: grub-2.12/grub-core/commands/tpm2_key_protector/module.c
===================================================================
--- grub-2.12.orig/grub-core/commands/tpm2_key_protector/module.c
+++ grub-2.12/grub-core/commands/tpm2_key_protector/module.c
@@ -160,6 +160,8 @@ static grub_extcmd_t tpm2_protector_init
static grub_extcmd_t tpm2_protector_clear_cmd;
static tpm2_protector_context_t tpm2_protector_ctx = {0};
+static grub_command_t tpm2_dump_pcr_cmd;
+
static grub_err_t
tpm2_protector_srk_read_file (const char *filepath, void **buffer, grub_size_t *buffer_size)
{
@@ -1327,6 +1329,33 @@ static struct grub_key_protector tpm2_ke
.recover_key = tpm2_protector_recover_key
};
+static grub_err_t
+tpm2_dump_pcr (grub_command_t cmd __attribute__((__unused__)),
+ int argc, char *argv[])
+{
+ TPM_ALG_ID_t pcr_bank;
+
+ if (argc == 0)
+ pcr_bank = TPM_ALG_SHA256;
+ else if (grub_strcmp (argv[0], "sha1") == 0)
+ pcr_bank = TPM_ALG_SHA1;
+ else if (grub_strcmp (argv[0], "sha256") == 0)
+ pcr_bank = TPM_ALG_SHA256;
+ else if (grub_strcmp (argv[0], "sha384") == 0)
+ pcr_bank = TPM_ALG_SHA384;
+ else if (grub_strcmp (argv[0], "sha512") == 0)
+ pcr_bank = TPM_ALG_SHA512;
+ else
+ {
+ grub_printf ("Unknown PCR bank\n");
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
+
+ tpm2_protector_dump_pcr (pcr_bank);
+
+ return GRUB_ERR_NONE;
+}
+
GRUB_MOD_INIT (tpm2_key_protector)
{
tpm2_protector_init_cmd =
@@ -1348,6 +1377,10 @@ GRUB_MOD_INIT (tpm2_key_protector)
N_("Clear the TPM2 key protector if previously initialized."),
NULL);
grub_key_protector_register (&tpm2_key_protector);
+
+ tpm2_dump_pcr_cmd =
+ grub_register_command ("tpm2_dump_pcr", tpm2_dump_pcr, N_("Dump TPM2 PCRs"),
+ N_("Print all PCRs of the specified TPM 2.0 bank"));
}
GRUB_MOD_FINI (tpm2_key_protector)
@@ -1357,4 +1390,6 @@ GRUB_MOD_FINI (tpm2_key_protector)
grub_key_protector_unregister (&tpm2_key_protector);
grub_unregister_extcmd (tpm2_protector_clear_cmd);
grub_unregister_extcmd (tpm2_protector_init_cmd);
+
+ grub_unregister_command (tpm2_dump_pcr_cmd);
}

View File

@@ -0,0 +1,385 @@
From 90153f1c9631498723450d84e014e25865fecc1b Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 15 Mar 2018 14:12:40 -0400
Subject: [PATCH 3/9] Add grub2-switch-to-blscfg
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
[jhlavac: Use ${etcdefaultgrub} instead of /etc/default/grub]
Signed-off-by: Jan Hlavac <jhlavac@redhat.com>
[rharwood: skip on ostree installations, migrate man to h2m]
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
---
Makefile.util.def | 7 +
docs/man/grub-switch-to-blscfg.h2m | 2 +
util/grub-switch-to-blscfg.in | 317 +++++++++++++++++++++++++++++
util/grub.d/10_linux.in | 2 +-
4 files changed, 327 insertions(+), 1 deletion(-)
create mode 100644 docs/man/grub-switch-to-blscfg.h2m
create mode 100644 util/grub-switch-to-blscfg.in
diff --git a/Makefile.util.def b/Makefile.util.def
index 6bb30c165..ffedea24a 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -1460,6 +1460,13 @@ program = {
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
};
+script = {
+ name = grub-switch-to-blscfg;
+ common = util/grub-switch-to-blscfg.in;
+ mansection = 8;
+ installdir = sbin;
+};
+
program = {
name = grub-glue-efi;
mansection = 1;
diff --git a/docs/man/grub-switch-to-blscfg.h2m b/docs/man/grub-switch-to-blscfg.h2m
new file mode 100644
index 000000000..fa341426a
--- /dev/null
+++ b/docs/man/grub-switch-to-blscfg.h2m
@@ -0,0 +1,2 @@
+[NAME]
+grub-switch-to-blscfg \- switch to using BLS config files
diff --git a/util/grub-switch-to-blscfg.in b/util/grub-switch-to-blscfg.in
new file mode 100644
index 000000000..a851424be
--- /dev/null
+++ b/util/grub-switch-to-blscfg.in
@@ -0,0 +1,317 @@
+#! /bin/sh
+#
+# Set a default boot entry for GRUB.
+# Copyright (C) 2004,2009 Free Software Foundation, Inc.
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+
+#set -eu
+
+# Initialize some variables.
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+sbindir=@sbindir@
+bindir=@bindir@
+sysconfdir="@sysconfdir@"
+PACKAGE_NAME=@PACKAGE_NAME@
+PACKAGE_VERSION=@PACKAGE_VERSION@
+datarootdir="@datarootdir@"
+datadir="@datadir@"
+if [ ! -v pkgdatadir ]; then
+ pkgdatadir="${datadir}/@PACKAGE@"
+fi
+
+self=`basename $0`
+
+grub_get_kernel_settings="${sbindir}/@grub_get_kernel_settings@"
+grub_editenv=${bindir}/@grub_editenv@
+etcdefaultgrub=/etc/default/grub
+
+eval "$("${grub_get_kernel_settings}")" || true
+
+EFIDIR=$(grep ^ID= /etc/os-release | sed -e 's/^ID=//' -e 's/rhel/redhat/' -e 's/\"//g')
+if [ -d /sys/firmware/efi/efivars/ ]; then
+ startlink=/etc/grub2-efi.cfg
+ grubdir=`echo "/@bootdirname@/efi/EFI/${EFIDIR}/" | sed 's,//*,/,g'`
+else
+ startlink=/etc/grub2.cfg
+ grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'`
+fi
+
+blsdir=`echo "/@bootdirname@/loader/entries" | sed 's,//*,/,g'`
+
+backupsuffix=.bak
+
+arch="$(uname -m)"
+
+export TEXTDOMAIN=@PACKAGE@
+export TEXTDOMAINDIR="@localedir@"
+
+. "${pkgdatadir}/grub-mkconfig_lib"
+
+# Usage: usage
+# Print the usage.
+usage () {
+ gettext_printf "Usage: %s\n" "$self"
+ gettext "Switch to BLS config files.\n"; echo
+ echo
+ print_option_help "-h, --help" "$(gettext "print this message and exit")"
+ print_option_help "-V, --version" "$(gettext "print the version information and exit")"
+ echo
+ print_option_help "--backup-suffix=$(gettext "SUFFIX")" "$backupsuffix"
+ print_option_help "--bls-directory=$(gettext "DIR")" "$blsdir"
+ print_option_help "--config-file=$(gettext "FILE")" "$startlink"
+ print_option_help "--grub-defaults=$(gettext "FILE")" "$etcdefaultgrub"
+ print_option_help "--grub-directory=$(gettext "DIR")" "$grubdir"
+ # echo
+ # gettext "Report bugs to <bug-grub@gnu.org>."; echo
+}
+
+argument () {
+ opt=$1
+ shift
+
+ if test $# -eq 0; then
+ gettext_printf "%s: option requires an argument -- \`%s'\n" "$self" "$opt" 1>&2
+ exit 1
+ fi
+ echo $1
+}
+
+# Check the arguments.
+while test $# -gt 0
+do
+ option=$1
+ shift
+
+ case "$option" in
+ -h | --help)
+ usage
+ exit 0 ;;
+ -V | --version)
+ echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}"
+ exit 0 ;;
+
+ --backup-suffix)
+ backupsuffix=`argument $option "$@"`
+ shift
+ ;;
+ --backup-suffix=*)
+ backupsuffix=`echo "$option" | sed 's/--backup-suffix=//'`
+ ;;
+
+ --bls-directory)
+ blsdir=`argument $option "$@"`
+ shift
+ ;;
+ --bls-directory=*)
+ blsdir=`echo "$option" | sed 's/--bls-directory=//'`
+ ;;
+
+ --config-file)
+ startlink=`argument $option "$@"`
+ shift
+ ;;
+ --config-file=*)
+ startlink=`echo "$option" | sed 's/--config-file=//'`
+ ;;
+
+ --grub-defaults)
+ etcdefaultgrub=`argument $option "$@"`
+ shift
+ ;;
+ --grub-defaults=*)
+ etcdefaultgrub=`echo "$option" | sed 's/--grub-defaults=//'`
+ ;;
+
+ --grub-directory)
+ grubdir=`argument $option "$@"`
+ shift
+ ;;
+ --grub-directory=*)
+ grubdir=`echo "$option" | sed 's/--grub-directory=//'`
+ ;;
+
+ *)
+ gettext_printf "Unrecognized option \`%s'\n" "$option" 1>&2
+ usage
+ exit 1
+ ;;
+ esac
+done
+
+find_grub_cfg() {
+ local candidate=""
+ while [ -e "${candidate}" -o $# -gt 0 ]
+ do
+ if [ ! -e "${candidate}" ] ; then
+ candidate="$1"
+ shift
+ fi
+
+ if [ -L "${candidate}" ]; then
+ candidate="$(realpath "${candidate}")"
+ fi
+
+ if [ -f "${candidate}" ]; then
+ export GRUB_CONFIG_FILE="${candidate}"
+ return 0
+ fi
+ done
+ return 1
+}
+
+if ! find_grub_cfg ${startlink} ${grubdir}/grub.cfg ; then
+ gettext_printf "Couldn't find config file\n" 1>&2
+ exit 1
+fi
+
+if [ ! -d "${blsdir}" ]; then
+ install -m 700 -d "${blsdir}"
+fi
+
+if [ -f /etc/machine-id ]; then
+ MACHINE_ID=$(cat /etc/machine-id)
+else
+ MACHINE_ID=$(dmesg | sha256sum)
+fi
+
+mkbls() {
+ local kernelver=$1 && shift
+ local datetime=$1 && shift
+ local kernelopts=$1 && shift
+
+ local debugname=""
+ local debugid=""
+ local flavor=""
+
+ if [ "$kernelver" == *\+* ] ; then
+ local flavor=-"${kernelver##*+}"
+ if [ "${flavor}" == "-debug" ]; then
+ local debugname=" with debugging"
+ local debugid="-debug"
+ fi
+ fi
+ (
+ source /etc/os-release
+
+ cat <<EOF
+title ${NAME} (${kernelver}) ${VERSION}${debugname}
+version ${kernelver}${debugid}
+linux /vmlinuz-${kernelver}
+initrd /initramfs-${kernelver}.img
+options ${kernelopts}
+grub_users \$grub_users
+grub_arg --unrestricted
+grub_class kernel${flavor}
+EOF
+ ) | cat
+}
+
+copy_bls() {
+ for kernelver in $(cd /lib/modules/ ; ls -1) "" ; do
+ bls_target="${blsdir}/${MACHINE_ID}-${kernelver}.conf"
+ linux="/vmlinuz-${kernelver}"
+ linux_path="/boot${linux}"
+ kernel_dir="/lib/modules/${kernelver}"
+
+ if [ ! -d "${kernel_dir}" ] ; then
+ continue
+ fi
+ if [ ! -f "${linux_path}" ]; then
+ continue
+ fi
+
+ linux_relpath="$("${grub_mkrelpath}" "${linux_path}")"
+ bootprefix="${linux_relpath%%"${linux}"}"
+ cmdline="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
+
+ mkbls "${kernelver}" \
+ "$(date -u +%Y%m%d%H%M%S -d "$(stat -c '%y' "${kernel_dir}")")" \
+ "${bootprefix}" "${cmdline}" >"${bls_target}"
+
+ if [ "x$GRUB_LINUX_MAKE_DEBUG" = "xtrue" ]; then
+ bls_debug="$(echo ${bls_target} | sed -e "s/${kernelver}/${kernelver}~debug/")"
+ cp -aT "${bls_target}" "${bls_debug}"
+ title="$(grep '^title[ \t]' "${bls_debug}" | sed -e 's/^title[ \t]*//')"
+ options="$(echo "${cmdline} ${GRUB_CMDLINE_LINUX_DEBUG}" | sed -e 's/\//\\\//g')"
+ sed -i -e "s/^title.*/title ${title}${GRUB_LINUX_DEBUG_TITLE_POSTFIX}/" "${bls_debug}"
+ sed -i -e "s/^options.*/options ${options}/" "${bls_debug}"
+ fi
+ done
+
+ if [ -f "/boot/vmlinuz-0-rescue-${MACHINE_ID}" ]; then
+ mkbls "0-rescue-${MACHINE_ID}" "0" "${bootprefix}" >"${blsdir}/${MACHINE_ID}-0-rescue.conf"
+ fi
+}
+
+# The grub2 EFI binary is not copied to the ESP as a part of an ostree
+# transaction. Make sure a grub2 version with BLS support is installed
+# but only do this if the blsdir is not set, to make sure that the BLS
+# parsing module will search for the BLS snippets in the default path.
+if test -f /run/ostree-booted && test -d /sys/firmware/efi/efivars && \
+ ! ${grub_editenv} - list | grep -q blsdir && \
+ mountpoint -q /boot; then
+ grub_binary="$(find /usr/lib/ostree-boot/efi/EFI/${EFIDIR}/ -name grub*.efi)"
+ install -m 700 ${grub_binary} ${grubdir} || exit 1
+ # Create a hidden file to indicate that grub2 now has BLS support.
+ touch /boot/grub2/.grub2-blscfg-supported
+fi
+
+GENERATE=0
+if grep '^GRUB_ENABLE_BLSCFG=.*' "${etcdefaultgrub}" \
+ | grep -vq '^GRUB_ENABLE_BLSCFG="*true"*\s*$' ; then
+ if ! sed -i"${backupsuffix}" \
+ -e 's,^GRUB_ENABLE_BLSCFG=.*,GRUB_ENABLE_BLSCFG=true,' \
+ "${etcdefaultgrub}" ; then
+ gettext_printf "Updating %s failed\n" "${etcdefaultgrub}"
+ exit 1
+ fi
+ GENERATE=1
+elif ! grep -q '^GRUB_ENABLE_BLSCFG=.*' "${etcdefaultgrub}" ; then
+ if ! echo 'GRUB_ENABLE_BLSCFG=true' >> "${etcdefaultgrub}" ; then
+ gettext_printf "Updating %s failed\n" "${etcdefaultgrub}"
+ exit 1
+ fi
+ GENERATE=1
+fi
+
+if [ "${GENERATE}" -eq 1 ] ; then
+ copy_bls
+
+ if [ $arch = "x86_64" ] && [ ! -d /sys/firmware/efi ]; then
+ mod_dir="i386-pc"
+ elif [ $arch = "ppc64" -o $arch = "ppc64le" ] && [ ! -d /sys/firmware/opal ]; then
+ mod_dir="powerpc-ieee1275"
+ fi
+
+ if [ -n "${mod_dir}" ]; then
+ for mod in blscfg increment; do
+ install -m 700 ${prefix}/lib/grub/${mod_dir}/${mod}.mod ${grubdir}/$mod_dir/ || exit 1
+ done
+ fi
+
+ cp -af "${GRUB_CONFIG_FILE}" "${GRUB_CONFIG_FILE}${backupsuffix}"
+ if ! grub2-mkconfig -o "${GRUB_CONFIG_FILE}" ; then
+ install -m 700 "${GRUB_CONFIG_FILE}${backupsuffix}" "${GRUB_CONFIG_FILE}"
+ sed -i"${backupsuffix}" \
+ -e 's,^GRUB_ENABLE_BLSCFG=.*,GRUB_ENABLE_BLSCFG=false,' \
+ "${etcdefaultgrub}"
+ gettext_printf "Updating %s failed\n" "${GRUB_CONFIG_FILE}"
+ exit 1
+ fi
+fi
+
+# Bye.
+exit 0
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 49eccbeaf..45eefb332 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -147,7 +147,7 @@ blsdir="/boot/loader/entries"
get_sorted_bls()
{
- if ! [ -d "${blsdir}" ]; then
+ if ! [ -d "${blsdir}" ] || [ -f /run/ostree-booted ] || [ -d /ostree/repo ]; then
return
fi
--
2.44.0

View File

@@ -0,0 +1,117 @@
From 6c8d390809956d355fed8bc830f64e86838e3e82 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Sat, 18 Nov 2023 21:42:00 +0800
Subject: [PATCH 3/4] Restrict 'ls' and auto file completion on cryptodisk
print
The 'ls' command allows file listing, while file completion assists in
providing matched file names by partially inputting via the TAB key.
Both functionalities should be restricted when the disk is automatically
unlocked for the same reasons as highlighted in the previous patch
addressing the limitation on file access to the cryptodisk.
Given that no file is explicitly opened for listing, employing file
filters becomes impractical. Consequently, this patch focuses on
modifying relevant routines separately to incorporate necessary checks.
The objective is to introduce measures that prevent 'ls' and auto file
completion from accessing encrypted data when the disk is automatically
unlocked.
By implementing these modifications, any attempt to utilize 'ls' or file
completion on the cryptodisk will result in an "Access Denied:
prohibited to browse encrypted data" error message, thus effectively
alerting the user about the restricted access.
While protecting content within disk files from viewing is essential,
it's equally crucial to restrict access to in-memory content. This
includes prohibiting access to the decrypted in-memory copies of disk
files.
This enhancement aims to fortify security protocols by extending
restrictions to additional functionalities beyond direct file access.
Signed-Off-by Michael Chang <mchang@suse.com>
---
grub-core/commands/ls.c | 8 ++++++++
grub-core/commands/minicmd.c | 6 ++++++
grub-core/kern/corecmd.c | 8 ++++++++
grub-core/normal/completion.c | 8 ++++++++
4 files changed, 30 insertions(+)
diff --git a/grub-core/commands/ls.c b/grub-core/commands/ls.c
index 8e98c73cc..aeb336a73 100644
--- a/grub-core/commands/ls.c
+++ b/grub-core/commands/ls.c
@@ -183,6 +183,14 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
if (! dev)
goto fail;
+ if (dev->disk &&
+ grub_disk_is_crypto (dev->disk) &&
+ grub_file_filters[GRUB_FILE_FILTER_NOCAT])
+ {
+ grub_error (GRUB_ERR_ACCESS_DENIED, N_("prohibited to browse encrypted content"));
+ goto fail;
+ }
+
fs = grub_fs_probe (dev);
path = grub_strchr (dirname, ')');
if (! path)
diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c
index fa498931e..8f2ac0539 100644
--- a/grub-core/commands/minicmd.c
+++ b/grub-core/commands/minicmd.c
@@ -101,6 +101,12 @@ grub_mini_cmd_dump (struct grub_command *cmd __attribute__ ((unused)),
if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no address specified");
+ /* NOCAT filter is applied to prevent cat alike command from revealing file
+ * content, the dump command should also be prohibited to revealing memory
+ * content as well */
+ if (grub_file_filters[GRUB_FILE_FILTER_NOCAT])
+ return grub_error (GRUB_ERR_ACCESS_DENIED, N_("prohibited by security policy"));
+
#if GRUB_CPU_SIZEOF_VOID_P == GRUB_CPU_SIZEOF_LONG
#define grub_strtoaddr grub_strtoul
#else
diff --git a/grub-core/kern/corecmd.c b/grub-core/kern/corecmd.c
index 62d434ba9..b639bc3ae 100644
--- a/grub-core/kern/corecmd.c
+++ b/grub-core/kern/corecmd.c
@@ -135,6 +135,14 @@ grub_core_cmd_ls (struct grub_command *cmd __attribute__ ((unused)),
if (! dev)
goto fail;
+ if (dev->disk &&
+ grub_disk_is_crypto (dev->disk) &&
+ grub_file_filters[GRUB_FILE_FILTER_NOCAT])
+ {
+ grub_error (GRUB_ERR_ACCESS_DENIED, N_("prohibited to browse encrypted content"));
+ goto fail;
+ }
+
fs = grub_fs_probe (dev);
path = grub_strchr (argv[0], ')');
if (! path)
diff --git a/grub-core/normal/completion.c b/grub-core/normal/completion.c
index 18cadfa85..d003ec37d 100644
--- a/grub-core/normal/completion.c
+++ b/grub-core/normal/completion.c
@@ -259,6 +259,14 @@ complete_file (void)
goto fail;
}
+ if (dev->disk &&
+ grub_disk_is_crypto (dev->disk) &&
+ grub_file_filters[GRUB_FILE_FILTER_NOCAT])
+ {
+ grub_error (GRUB_ERR_ACCESS_DENIED, N_("prohibited to browse encrypted content"));
+ goto fail;
+ }
+
fs = grub_fs_probe (dev);
if (! fs)
{
--
2.42.1

View File

@@ -1,136 +0,0 @@
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

View File

@@ -1,34 +0,0 @@
From a0bcce49bc285fb71c572963e662db3d88bcd563 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Wed, 16 Jul 2025 17:52:03 +0800
Subject: [PATCH 3/4] docs: Clarify test for files on TFTP and HTTP
---
docs/grub.texi | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/docs/grub.texi b/docs/grub.texi
index 9aaea7282..4b947e942 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -5887,13 +5887,13 @@ the strings are not equal
@item @var{prefix}@var{integer1} @code{-plt} @var{prefix}@var{integer2}
@var{integer1} is less than @var{integer2} after stripping off common non-numeric @var{prefix}.
@item @var{file1} @code{-nt} @var{file2}
-@var{file1} is newer than @var{file2} (modification time). Optionally numeric @var{bias} may be directly appended to @code{-nt} in which case it is added to the first file modification time.
+@var{file1} is newer than @var{file2} (modification time). Optionally numeric @var{bias} may be directly appended to @code{-nt} in which case it is added to the first file modification time. For @var{file} on TFTP or HTTP servers, this operation may not work as expected.
@item @var{file1} @code{-ot} @var{file2}
-@var{file1} is older than @var{file2} (modification time). Optionally numeric @var{bias} may be directly appended to @code{-ot} in which case it is added to the first file modification time.
+@var{file1} is older than @var{file2} (modification time). Optionally numeric @var{bias} may be directly appended to @code{-ot} in which case it is added to the first file modification time. For @var{file} on TFTP or HTTP servers, this operation may not work as expected.
@item @code{-d} @var{file}
-@var{file} exists and is a directory
+@var{file} exists and is a directory. For @var{file} on TFTP or HTTP servers, the test is unreliable because these protocols are designed for file transport, and GRUBs netfs does not implement directory listing for them.
@item @code{-e} @var{file}
-@var{file} exists
+@var{file} exists. For @var{file} on TFTP or HTTP servers, the result is the same as @code{-f} because these protocols are designed for file transport, and GRUBs netfs lacks directory support to distinguish between files and directories.
@item @code{-f} @var{file}
@var{file} exists and is not a directory
@item @code{-s} @var{file}
--
2.50.0

View File

@@ -1,34 +0,0 @@
From 96f51e8fb8daf43da636f6475827d697829fdb8b Mon Sep 17 00:00:00 2001
From: B Horn <b@horn.uk>
Date: Sun, 12 May 2024 02:48:33 +0100
Subject: [PATCH 03/20] fs/hfs: Fix stack OOB write with grub_strcpy()
Replaced with grub_strlcpy().
Fixes: CVE-2024-45782
Fixes: CVE-2024-56737
Fixes: https://savannah.gnu.org/bugs/?66599
Reported-by: B Horn <b@horn.uk>
Signed-off-by: B Horn <b@horn.uk>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/hfs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c
index 91dc0e69c3..920112b03e 100644
--- a/grub-core/fs/hfs.c
+++ b/grub-core/fs/hfs.c
@@ -379,7 +379,7 @@ grub_hfs_mount (grub_disk_t disk)
volume name. */
key.parent_dir = grub_cpu_to_be32_compile_time (1);
key.strlen = data->sblock.volname[0];
- grub_strcpy ((char *) key.str, (char *) (data->sblock.volname + 1));
+ grub_strlcpy ((char *) key.str, (char *) (data->sblock.volname + 1), sizeof (key.str));
if (grub_hfs_find_node (data, (char *) &key, data->cat_root,
0, (char *) &dir, sizeof (dir)) == 0)
--
2.48.1

View File

@@ -1,49 +0,0 @@
From 846b1d8bebd316a18fae9fb90efb3e8451ec70cc Mon Sep 17 00:00:00 2001
From: Eric Sandeen <sandeen@redhat.com>
Date: Wed, 4 Dec 2024 07:50:28 -0600
Subject: [PATCH 3/3] fs/xfs: fix large extent counters incompat feature
support
When large extent counter / NREXT64 support was added to grub, it missed
a couple of direct reads of nextents which need to be changed to the new
NREXT64-aware helper as well. Without this, we'll have mis-reads of some
directories with this feature enabled.
(The large extent counter fix likely raced on merge with
07318ee7e ("fs/xfs: Fix XFS directory extent parsing") which added the new
direct nextents reads just prior, causing this issue.)
Fixes: aa7c1322671e ("fs/xfs: Add large extent counters incompat feature support")
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Reviewed-by: Anthony Iliopoulos <ailiop@suse.com>
Reviewed-by: Jon DeVree <nuxi@vault24.org>
Link: https://lore.kernel.org/r/985816b8-35e6-4083-994f-ec9138bd35d2@redhat.com
---
grub-core/fs/xfs.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
index 30e3e7f6d9..3ba232436e 100644
--- a/grub-core/fs/xfs.c
+++ b/grub-core/fs/xfs.c
@@ -937,7 +937,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
* Leaf and tail information are only in the data block if the number
* of extents is 1.
*/
- if (dir->inode.nextents == grub_cpu_to_be32_compile_time (1))
+ if (grub_xfs_get_inode_nextents(&dir->inode) == 1)
{
end = (char *) tail;
@@ -992,7 +992,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
* The expected number of directory entries is only tracked for the
* single extent case.
*/
- if (dir->inode.nextents == grub_cpu_to_be32_compile_time (1))
+ if (grub_xfs_get_inode_nextents(&dir->inode) == 1)
{
/* Check if last direntry in this block is reached. */
entries--;
--
2.48.1

View File

@@ -1,95 +0,0 @@
From 7344b3c7cee8dea94dbc97211c5e6d1925848865 Mon Sep 17 00:00:00 2001
From: Stefan Berger <stefanb@linux.ibm.com>
Date: Tue, 26 Nov 2024 15:39:42 -0500
Subject: [PATCH 3/7] ieee1275: Consolidate repeated definitions of
IEEE1275_IHANDLE_INVALID
Consolidate repeated definitions of IEEE1275_IHANDLE_INVALID that are cast
to the type grub_ieee1275_ihandle_t. On the occasion add "GRUB_" prefix to
the constant name.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/commands/ieee1275/ibmvtpm.c | 4 +---
grub-core/term/ieee1275/serial.c | 8 +++-----
include/grub/ieee1275/ieee1275.h | 1 +
3 files changed, 5 insertions(+), 8 deletions(-)
diff --git a/grub-core/commands/ieee1275/ibmvtpm.c b/grub-core/commands/ieee1275/ibmvtpm.c
index a6fee5c51..dd30c7432 100644
--- a/grub-core/commands/ieee1275/ibmvtpm.c
+++ b/grub-core/commands/ieee1275/ibmvtpm.c
@@ -29,8 +29,6 @@
static grub_ieee1275_ihandle_t tpm_ihandle;
static grub_uint8_t tpm_version;
-#define IEEE1275_IHANDLE_INVALID ((grub_ieee1275_ihandle_t) 0)
-
static void
tpm_get_tpm_version (void)
{
@@ -53,7 +51,7 @@ tpm_init (void)
{
if (grub_ieee1275_open ("/vdevice/vtpm", &tpm_ihandle) < 0)
{
- tpm_ihandle = IEEE1275_IHANDLE_INVALID;
+ tpm_ihandle = GRUB_IEEE1275_IHANDLE_INVALID;
return GRUB_ERR_UNKNOWN_DEVICE;
}
diff --git a/grub-core/term/ieee1275/serial.c b/grub-core/term/ieee1275/serial.c
index 9bc44b306..ac2a8f827 100644
--- a/grub-core/term/ieee1275/serial.c
+++ b/grub-core/term/ieee1275/serial.c
@@ -25,8 +25,6 @@
#include <grub/i18n.h>
#include <grub/ieee1275/console.h>
-#define IEEE1275_IHANDLE_INVALID ((grub_ieee1275_ihandle_t) 0)
-
struct ofserial_hash_ent
{
char *devpath;
@@ -44,7 +42,7 @@ do_real_config (struct grub_serial_port *port)
if (grub_ieee1275_open (port->elem->devpath, &port->handle)
|| port->handle == (grub_ieee1275_ihandle_t) -1)
- port->handle = IEEE1275_IHANDLE_INVALID;
+ port->handle = GRUB_IEEE1275_IHANDLE_INVALID;
port->configured = 1;
}
@@ -58,7 +56,7 @@ serial_hw_fetch (struct grub_serial_port *port)
do_real_config (port);
- if (port->handle == IEEE1275_IHANDLE_INVALID)
+ if (port->handle == GRUB_IEEE1275_IHANDLE_INVALID)
return -1;
grub_ieee1275_read (port->handle, &c, 1, &actual);
@@ -76,7 +74,7 @@ serial_hw_put (struct grub_serial_port *port, const int c)
do_real_config (port);
- if (port->handle == IEEE1275_IHANDLE_INVALID)
+ if (port->handle == GRUB_IEEE1275_IHANDLE_INVALID)
return;
grub_ieee1275_write (port->handle, &c0, 1, &actual);
diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h
index dddb38514..c445d0499 100644
--- a/include/grub/ieee1275/ieee1275.h
+++ b/include/grub/ieee1275/ieee1275.h
@@ -60,6 +60,7 @@ struct grub_ieee1275_common_hdr
typedef grub_uint32_t grub_ieee1275_ihandle_t;
typedef grub_uint32_t grub_ieee1275_phandle_t;
+#define GRUB_IEEE1275_IHANDLE_INVALID ((grub_ieee1275_ihandle_t) 0)
#define GRUB_IEEE1275_PHANDLE_INVALID ((grub_ieee1275_phandle_t) -1)
struct grub_ieee1275_devalias
--
2.43.0

View File

@@ -1,693 +0,0 @@
From 07b675536e5ae8a0f34d65c40027458d0474d802 Mon Sep 17 00:00:00 2001
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Date: Mon, 24 Feb 2025 20:01:51 +0530
Subject: [PATCH 3/9] ieee1275: Read the DB and DBX secure boot variables
If secure boot is enabled with PKS, it will read secure boot variables
such as db and dbx from PKS and extract ESL's from it.
The ESL's would be saved in the platform keystore buffer, and
the appendedsig (module) would read it later to extract
the certificate's details from ESL.
In the following scenarios, static key mode will be activated:
1. When Secure Boot is enabled with static keys
2. When SB Version is unavailable but Secure Boot is enabled
3. When PKS support is unavailable but Secure Boot is enabled
Note:-
SB Version - Secure Boot mode
1 - PKS
0 - static key (embeded key)
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
---
grub-core/Makefile.am | 1 +
grub-core/Makefile.core.def | 1 +
grub-core/kern/ieee1275/init.c | 15 +-
.../kern/powerpc/ieee1275/platform_keystore.c | 335 ++++++++++++++++++
.../grub/powerpc/ieee1275/platform_keystore.h | 225 ++++++++++++
include/grub/types.h | 9 +
6 files changed, 584 insertions(+), 2 deletions(-)
create mode 100644 grub-core/kern/powerpc/ieee1275/platform_keystore.c
create mode 100644 include/grub/powerpc/ieee1275/platform_keystore.h
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index 40ed353aba..999e62788f 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -247,6 +247,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/alloc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/powerpc/ieee1275/platform_keystore.h
endif
if COND_sparc64_ieee1275
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 1dfcf5f991..85e717c122 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -333,6 +333,7 @@ kernel = {
powerpc_ieee1275 = kern/powerpc/dl.c;
powerpc_ieee1275 = kern/powerpc/compiler-rt.S;
powerpc_ieee1275 = kern/lockdown.c;
+ powerpc_ieee1275 = kern/powerpc/ieee1275/platform_keystore.c;
sparc64_ieee1275 = kern/sparc64/cache.S;
sparc64_ieee1275 = kern/sparc64/dl.c;
diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
index 0e1cbf24c3..45f787eff4 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -50,6 +50,8 @@
#include <grub/ieee1275/alloc.h>
#endif
#include <grub/lockdown.h>
+#include <grub/powerpc/ieee1275/ieee1275.h>
+#include <grub/powerpc/ieee1275/platform_keystore.h>
/* The maximum heap size we're going to claim at boot. Not used by sparc. */
#ifdef __i386__
@@ -985,7 +987,7 @@ grub_get_ieee1275_secure_boot (void)
{
grub_ieee1275_phandle_t root;
int rc;
- grub_uint32_t is_sb;
+ grub_uint32_t is_sb = 0;
if (grub_ieee1275_finddevice ("/", &root))
{
@@ -1009,7 +1011,16 @@ grub_get_ieee1275_secure_boot (void)
* We only support enforce.
*/
if (is_sb >= 2)
- grub_lockdown ();
+ {
+ grub_printf ("Secure Boot Enabled\n");
+ rc = grub_pks_keystore_init ();
+ if (rc != GRUB_ERR_NONE)
+ grub_printf ("Initialization of the Platform Keystore failed!\n");
+
+ grub_lockdown ();
+ }
+ else
+ grub_printf ("Secure Boot Disabled\n");
}
grub_addr_t grub_modbase;
diff --git a/grub-core/kern/powerpc/ieee1275/platform_keystore.c b/grub-core/kern/powerpc/ieee1275/platform_keystore.c
new file mode 100644
index 0000000000..ea9f27eb22
--- /dev/null
+++ b/grub-core/kern/powerpc/ieee1275/platform_keystore.c
@@ -0,0 +1,335 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2024 Free Software Foundation, Inc.
+ * Copyright (C) 2024 IBM Corporation
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/mm.h>
+#include <grub/powerpc/ieee1275/ieee1275.h>
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/lockdown.h>
+#include <grub/powerpc/ieee1275/platform_keystore.h>
+
+#define PKS_CONSUMER_FW 1
+#define SB_VERSION_KEY_NAME ((grub_uint8_t *) "SB_VERSION")
+#define SB_VERSION_KEY_LEN 10
+#define DB 1
+#define DBX 2
+#define PKS_OBJECT_NOT_FOUND ((grub_err_t) - 7)
+
+/* Platform Keystore */
+static grub_size_t pks_max_object_size;
+grub_uint8_t grub_pks_use_keystore = 0;
+grub_pks_t grub_pks_keystore = { .db = NULL, .dbx = NULL, .db_entries = 0, .dbx_entries = 0 };
+
+/* Convert the esl data into the ESL */
+static grub_esl_t *
+convert_to_esl (const grub_uint8_t *esl_data, const grub_size_t esl_data_size)
+{
+ grub_esl_t *esl = NULL;
+
+ if (esl_data_size < sizeof (grub_esl_t) || esl_data == NULL)
+ return esl;
+
+ esl = (grub_esl_t *) esl_data;
+
+ return esl;
+}
+
+/*
+ * Import the GUID, esd, and its size into the pks sd buffer and
+ * pks sd entries from the EFI signature list.
+ */
+static grub_err_t
+esd_from_esl (const grub_uint8_t *esl_data, grub_size_t esl_size,
+ const grub_size_t signature_size, const grub_uuid_t *guid,
+ grub_pks_sd_t **pks_sd, grub_size_t *pks_sd_entries)
+{
+ grub_esd_t *esd = NULL;
+ grub_pks_sd_t *signature = *pks_sd;
+ grub_size_t entries = *pks_sd_entries;
+ grub_size_t data_size = 0, offset = 0;
+
+ /* reads the esd from esl */
+ while (esl_size > 0)
+ {
+ esd = (grub_esd_t *) (esl_data + offset);
+ data_size = signature_size - sizeof (grub_esd_t);
+
+ signature = grub_realloc (signature, (entries + 1) * sizeof (grub_pks_sd_t));
+ if (signature == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
+
+ signature[entries].data = grub_malloc (data_size * sizeof (grub_uint8_t));
+ if (signature[entries].data == NULL)
+ {
+ /*
+ * allocated memory will be freed by
+ * grub_free_platform_keystore
+ */
+ *pks_sd = signature;
+ *pks_sd_entries = entries + 1;
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
+ }
+
+ grub_memcpy (signature[entries].data, esd->signaturedata, data_size);
+ signature[entries].data_size = data_size;
+ signature[entries].guid = *guid;
+ entries++;
+ esl_size -= signature_size;
+ offset += signature_size;
+ }
+
+ *pks_sd = signature;
+ *pks_sd_entries = entries;
+
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * Extract the esd after removing the esl header from esl.
+ */
+static grub_err_t
+esl_to_esd (const grub_uint8_t *esl_data, grub_size_t *next_esl,
+ grub_pks_sd_t **pks_sd, grub_size_t *pks_sd_entries)
+{
+ grub_uuid_t guid = { 0 };
+ grub_esl_t *esl = NULL;
+ grub_size_t offset = 0, esl_size = 0,
+ signature_size = 0, signature_header_size = 0;
+
+ esl = convert_to_esl (esl_data, *next_esl);
+ if (esl == NULL)
+ return grub_error (GRUB_ERR_BUG, "invalid ESL");
+
+ esl_size = grub_le_to_cpu32 (esl->signaturelistsize);
+ signature_header_size = grub_le_to_cpu32 (esl->signatureheadersize);
+ signature_size = grub_le_to_cpu32 (esl->signaturesize);
+ guid = esl->signaturetype;
+
+ if (esl_size < sizeof (grub_esl_t) || esl_size > *next_esl)
+ return grub_error (GRUB_ERR_BUG, "invalid ESL size (%u)\n", esl_size);
+
+ *next_esl = esl_size;
+ offset = sizeof (grub_esl_t) + signature_header_size;
+ esl_size = esl_size - offset;
+
+ return esd_from_esl (esl_data + offset, esl_size, signature_size, &guid,
+ pks_sd, pks_sd_entries);
+}
+
+/*
+ * Import the EFI signature data and the number of esd from the esl
+ * into the pks sd buffer and pks sd entries.
+ */
+static grub_err_t
+pks_sd_from_esl (const grub_uint8_t *esl_data, grub_size_t esl_size,
+ grub_pks_sd_t **pks_sd, grub_size_t *pks_sd_entries)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_size_t next_esl = esl_size;
+
+ do
+ {
+ rc = esl_to_esd (esl_data, &next_esl, pks_sd, pks_sd_entries);
+ if (rc != GRUB_ERR_NONE)
+ break;
+
+ esl_data += next_esl;
+ esl_size -= next_esl;
+ next_esl = esl_size;
+ }
+ while (esl_size > 0);
+
+ return rc;
+}
+
+/*
+ * Read the secure boot version from PKS as an object.
+ * caller must free result
+ */
+static grub_err_t
+read_sbversion_from_pks (grub_uint8_t **out, grub_size_t *outlen, grub_size_t *policy)
+{
+ *out = grub_malloc (pks_max_object_size);
+ if (*out == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
+
+ return grub_ieee1275_pks_read_object (PKS_CONSUMER_FW, SB_VERSION_KEY_NAME,
+ SB_VERSION_KEY_LEN, *out, pks_max_object_size,
+ outlen, policy);
+}
+
+/*
+ * reads the secure boot variable from PKS.
+ * caller must free result
+ */
+static grub_err_t
+read_sbvar_from_pks (const grub_uint8_t sbvarflags, const grub_uint8_t sbvartype,
+ grub_uint8_t **out, grub_size_t *outlen)
+{
+ *out = grub_malloc (pks_max_object_size);
+ if (*out == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
+
+ return grub_ieee1275_pks_read_sbvar (sbvarflags, sbvartype, *out,
+ pks_max_object_size, outlen);
+}
+
+/* Test the availability of PKS support. */
+static int
+is_support_pks (void)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_ieee1275_cell_t missing = 0;
+
+ rc = grub_ieee1275_test ("pks-max-object-size", &missing);
+ if (rc != GRUB_ERR_NONE || (int) missing == -1)
+ grub_printf ("Firmware doesn't have PKS support!\n");
+ else
+ {
+ rc = grub_ieee1275_pks_max_object_size (&pks_max_object_size);
+ if (rc != GRUB_ERR_NONE)
+ grub_printf ("PKS support is there but it has zero objects!\n");
+ }
+
+ return rc;
+}
+
+/*
+ * Retrieve the secure boot variable from PKS, unpacks it, read the esd
+ * from ESL, and store the information in the pks sd buffer.
+ */
+static grub_err_t
+read_secure_boot_variables (const grub_uint8_t sbvarflags, const grub_uint8_t sbvartype,
+ grub_pks_sd_t **pks_sd, grub_size_t *pks_sd_entries)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_uint8_t *esl_data = NULL;
+ grub_size_t esl_data_size = 0;
+
+ rc = read_sbvar_from_pks (sbvarflags, sbvartype, &esl_data, &esl_data_size);
+ /*
+ * at this point we have SB_VERSION, so any error is worth
+ * at least some user-visible info
+ */
+ if (rc != GRUB_ERR_NONE)
+ rc = grub_error (rc, "secure boot variable %s reading (%d)",
+ (sbvartype == DB ? "db" : "dbx"), rc);
+ else if (esl_data_size != 0)
+ rc = pks_sd_from_esl ((const grub_uint8_t *) esl_data, esl_data_size,
+ pks_sd, pks_sd_entries);
+ grub_free (esl_data);
+
+ return rc;
+}
+
+/* reads secure boot version (SB_VERSION) and it supports following
+ * SB_VERSION
+ * 1 - PKS
+ * 0 - static key (embeded key)
+ */
+static grub_err_t
+get_secure_boot_version (void)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_uint8_t *data = NULL;
+ grub_size_t len = 0, policy = 0;
+
+ rc = read_sbversion_from_pks (&data, &len, &policy);
+ if (rc != GRUB_ERR_NONE)
+ grub_printf ("SB version read failed! (%d)\n", rc);
+ else if (len != 1 || (*data != 1 && *data != 0))
+ {
+ grub_printf ("found unexpected SB version! (%d)\n", *data);
+ rc = GRUB_ERR_INVALID_COMMAND;
+ }
+
+ if (rc != GRUB_ERR_NONE)
+ {
+ grub_printf ("Switch to Static Key!\n");
+ if (grub_is_lockdown () == GRUB_LOCKDOWN_ENABLED)
+ grub_fatal ("Secure Boot locked down");
+ }
+ else
+ grub_pks_use_keystore = *data;
+
+ grub_free (data);
+
+ return rc;
+}
+
+/* Free allocated memory */
+void
+grub_pks_free_keystore (void)
+{
+ grub_size_t i = 0;
+
+ for (i = 0; i < grub_pks_keystore.db_entries; i++)
+ grub_free (grub_pks_keystore.db[i].data);
+
+ for (i = 0; i < grub_pks_keystore.dbx_entries; i++)
+ grub_free (grub_pks_keystore.dbx[i].data);
+
+ grub_free (grub_pks_keystore.db);
+ grub_free (grub_pks_keystore.dbx);
+ grub_memset (&grub_pks_keystore, 0, sizeof (grub_pks_t));
+}
+
+/* Initialization of the Platform Keystore */
+grub_err_t
+grub_pks_keystore_init (void)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+
+ grub_printf ("trying to load Platform Keystore\n");
+
+ rc = is_support_pks ();
+ if (rc != GRUB_ERR_NONE)
+ {
+ grub_printf ("Switch to Static Key!\n");
+ return rc;
+ }
+
+ /* SB_VERSION */
+ rc = get_secure_boot_version ();
+ if (rc != GRUB_ERR_NONE)
+ return rc;
+
+ if (grub_pks_use_keystore)
+ {
+ grub_memset (&grub_pks_keystore, 0, sizeof (grub_pks_t));
+ /* DB */
+ rc = read_secure_boot_variables (0, DB, &grub_pks_keystore.db, &grub_pks_keystore.db_entries);
+ if (rc == GRUB_ERR_NONE)
+ {
+ /* DBX */
+ rc = read_secure_boot_variables (0, DBX, &grub_pks_keystore.dbx, &grub_pks_keystore.dbx_entries);
+ if (rc == PKS_OBJECT_NOT_FOUND)
+ {
+ grub_printf ("dbx is not found!\n");
+ rc = GRUB_ERR_NONE;
+ }
+ }
+
+ }
+
+ if (rc != GRUB_ERR_NONE)
+ grub_pks_free_keystore ();
+
+ return rc;
+}
diff --git a/include/grub/powerpc/ieee1275/platform_keystore.h b/include/grub/powerpc/ieee1275/platform_keystore.h
new file mode 100644
index 0000000000..0641adb0f1
--- /dev/null
+++ b/include/grub/powerpc/ieee1275/platform_keystore.h
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved. This
+ * program and the accompanying materials are licensed and made available
+ * under the terms and conditions of the 2-Clause BSD License which
+ * accompanies this distribution.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * https://github.com/tianocore/edk2-staging (edk2-staging repo of tianocore),
+ * the ImageAuthentication.h file under it, and here's the copyright and license.
+ *
+ * MdePkg/Include/Guid/ImageAuthentication.h
+ *
+ * Copyright 2024 IBM Corp.
+ */
+
+#ifndef __PLATFORM_KEYSTORE_H__
+#define __PLATFORM_KEYSTORE_H__
+
+#include <grub/symbol.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+
+#if __GNUC__ >= 9
+#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
+#endif
+
+#define GRUB_MAX_HASH_SIZE 64
+
+typedef struct grub_esd grub_esd_t;
+typedef struct grub_esl grub_esl_t;
+
+/*
+ * It is derived from EFI_SIGNATURE_DATA
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
+ *
+ * The structure of an EFI signature database (ESD).*/
+struct grub_esd
+{
+ /*
+ * An identifier which identifies the agent which added
+ * the signature to the list.
+ */
+ grub_uuid_t signatureowner;
+ /* The format of the signature is defined by the SignatureType.*/
+ grub_uint8_t signaturedata[];
+} GRUB_PACKED;
+
+/*
+ * It is derived from EFI_SIGNATURE_LIST
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
+ *
+ * The structure of an EFI signature list (ESL).*/
+struct grub_esl
+{
+ /* Type of the signature. GUID signature types are defined in below.*/
+ grub_uuid_t signaturetype;
+ /* Total size of the signature list, including this header.*/
+ grub_uint32_t signaturelistsize;
+ /*
+ * Size of the signature header which precedes
+ * the array of signatures.
+ */
+ grub_uint32_t signatureheadersize;
+ /* Size of each signature.*/
+ grub_uint32_t signaturesize;
+} GRUB_PACKED;
+
+/*
+ * It is derived from EFI_CERT_X509_GUID
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
+ */
+#define GRUB_PKS_CERT_X509_GUID \
+ (grub_uuid_t) \
+ { \
+ { \
+ 0xa1, 0x59, 0xc0, 0xa5, 0xe4, 0x94, \
+ 0xa7, 0x4a, 0x87, 0xb5, 0xab, 0x15, \
+ 0x5c, 0x2b, 0xf0, 0x72 \
+ } \
+ }
+
+/*
+ * It is derived from EFI_CERT_SHA256_GUID
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
+ */
+#define GRUB_PKS_CERT_SHA256_GUID \
+ (grub_uuid_t) \
+ { \
+ { \
+ 0x26, 0x16, 0xc4, 0xc1, 0x4c, 0x50, \
+ 0x92, 0x40, 0xac, 0xa9, 0x41, 0xf9, \
+ 0x36, 0x93, 0x43, 0x28 \
+ } \
+ }
+
+/*
+ * It is derived from EFI_CERT_SHA384_GUID
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
+ */
+#define GRUB_PKS_CERT_SHA384_GUID \
+ (grub_uuid_t) \
+ { \
+ { \
+ 0x07, 0x53, 0x3e, 0xff, 0xd0, 0x9f, \
+ 0xc9, 0x48, 0x85, 0xf1, 0x8a, 0xd5, \
+ 0x6c, 0x70, 0x1e, 0x1 \
+ } \
+ }
+
+/*
+ * It is derived from EFI_CERT_SHA512_GUID
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
+ */
+#define GRUB_PKS_CERT_SHA512_GUID \
+ (grub_uuid_t) \
+ { \
+ { \
+ 0xae, 0x0f, 0x3e, 0x09, 0xc4, 0xa6, \
+ 0x50, 0x4f, 0x9f, 0x1b, 0xd4, 0x1e, \
+ 0x2b, 0x89, 0xc1, 0x9a \
+ } \
+ }
+
+/*
+ * It is derived from EFI_CERT_X509_SHA256_GUID
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
+ */
+#define GRUB_PKS_CERT_X509_SHA256_GUID \
+ (grub_uuid_t) \
+ { \
+ { \
+ 0x92, 0xa4, 0xd2, 0x3b, 0xc0, 0x96, \
+ 0x79, 0x40, 0xb4, 0x20, 0xfc, 0xf9, \
+ 0x8e, 0xf1, 0x03, 0xed \
+ } \
+ }
+
+/*
+ * It is derived from EFI_CERT_X509_SHA384_GUID
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
+ */
+#define GRUB_PKS_CERT_X509_SHA384_GUID \
+ (grub_uuid_t) \
+ { \
+ { \
+ 0x6e, 0x87, 0x76, 0x70, 0xc2, 0x80, \
+ 0xe6, 0x4e, 0xaa, 0xd2, 0x28, 0xb3, \
+ 0x49, 0xa6, 0x86, 0x5b \
+ } \
+ }
+
+/*
+ * It is derived from EFI_CERT_X509_SHA512_GUID
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
+ */
+#define GRUB_PKS_CERT_X509_SHA512_GUID \
+ (grub_uuid_t) \
+ { \
+ { \
+ 0x63, 0xbf, 0x6d, 0x44, 0x02, 0x25, \
+ 0xda, 0x4c, 0xbc, 0xfa, 0x24, 0x65, \
+ 0xd2, 0xb0, 0xfe, 0x9d \
+ } \
+ }
+
+typedef struct grub_pks_sd grub_pks_sd_t;
+typedef struct grub_pks grub_pks_t;
+
+/* The structure of a PKS signature data.*/
+struct grub_pks_sd
+{
+ grub_uuid_t guid; /* signature type */
+ grub_uint8_t *data; /* signature data */
+ grub_size_t data_size; /* size of signature data */
+} GRUB_PACKED;
+
+/* The structure of a PKS.*/
+struct grub_pks
+{
+ grub_pks_sd_t *db; /* signature database */
+ grub_pks_sd_t *dbx; /* forbidden signature database */
+ grub_size_t db_entries; /* size of signature database */
+ grub_size_t dbx_entries; /* size of forbidden signature database */
+} GRUB_PACKED;
+
+#ifdef __powerpc__
+
+/* Initialization of the Platform Keystore */
+grub_err_t grub_pks_keystore_init (void);
+/* Free allocated memory */
+void EXPORT_FUNC(grub_pks_free_keystore) (void);
+extern grub_uint8_t EXPORT_VAR(grub_pks_use_keystore);
+extern grub_pks_t EXPORT_VAR(grub_pks_keystore);
+
+#else
+
+#define grub_pks_use_keystore 0
+grub_pks_t grub_pks_keystore = {NULL, NULL, 0, 0};
+void grub_pks_free_keystore (void);
+
+#endif
+
+#endif
diff --git a/include/grub/types.h b/include/grub/types.h
index 064066e2e1..5542b9aa09 100644
--- a/include/grub/types.h
+++ b/include/grub/types.h
@@ -388,4 +388,13 @@ struct grub_packed_guid
} GRUB_PACKED;
typedef struct grub_packed_guid grub_packed_guid_t;
+
+#define GRUB_UUID_SIZE 16
+typedef struct grub_uuid grub_uuid_t;
+/* The structure of a UUID.*/
+struct grub_uuid
+{
+ grub_uint8_t b[GRUB_UUID_SIZE];
+};
+
#endif /* ! GRUB_TYPES_HEADER */
--
2.48.1

View File

@@ -1,66 +0,0 @@
From 041164d00e79ffd2433675a5dd5b824833b9fc6a Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Mon, 7 Apr 2025 16:29:17 +0800
Subject: [PATCH 3/7] tss2: Fix the missing authCommand
grub_tpm2_readpublic() and grub_tpm2_testparms() didn't check
authCommand when marshaling the input data buffer. Currently, there is
no caller using non-NULL authCommand. However, to avoid the potential
issue, the conditional check is added to insert authCommand into the
input buffer if necessary.
Also fix a few pointer checks.
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/lib/tss2/tpm2_cmd.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/grub-core/lib/tss2/tpm2_cmd.c b/grub-core/lib/tss2/tpm2_cmd.c
index cd0c6fd31..211d807d5 100644
--- a/grub-core/lib/tss2/tpm2_cmd.c
+++ b/grub-core/lib/tss2/tpm2_cmd.c
@@ -341,6 +341,8 @@ grub_tpm2_readpublic (const TPMI_DH_OBJECT_t objectHandle,
/* Marshal */
grub_tpm2_buffer_init (&in);
grub_tpm2_buffer_pack_u32 (&in, objectHandle);
+ if (authCommand != NULL)
+ grub_Tss2_MU_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
if (in.error != 0)
return TPM_RC_FAILURE;
@@ -398,7 +400,7 @@ grub_tpm2_load (const TPMI_DH_OBJECT_t parent_handle,
/* Marshal */
grub_tpm2_buffer_init (&in);
grub_tpm2_buffer_pack_u32 (&in, parent_handle);
- if (authCommand)
+ if (authCommand != NULL)
grub_Tss2_MU_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
grub_Tss2_MU_TPM2B_Marshal (&in, inPrivate->size, inPrivate->buffer);
grub_Tss2_MU_TPM2B_PUBLIC_Marshal (&in, inPublic);
@@ -461,9 +463,9 @@ grub_tpm2_loadexternal (const TPMS_AUTH_COMMAND_t *authCommand,
/* Marshal */
grub_tpm2_buffer_init (&in);
- if (authCommand)
+ if (authCommand != NULL)
grub_Tss2_MU_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
- if (inPrivate)
+ if (inPrivate != NULL)
grub_Tss2_MU_TPM2B_SENSITIVE_Marshal (&in, inPrivate);
else
grub_tpm2_buffer_pack_u16 (&in, 0);
@@ -1023,6 +1025,8 @@ grub_tpm2_testparms (const TPMT_PUBLIC_PARMS_t *parms,
/* Marshal */
grub_tpm2_buffer_init (&in);
grub_Tss2_MU_TPMT_PUBLIC_PARMS_Marshal (&in, parms);
+ if (authCommand != NULL)
+ grub_Tss2_MU_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
if (in.error != 0)
return TPM_RC_FAILURE;
--
2.43.0

View File

@@ -1,7 +1,7 @@
From 977f8c63d9d85fd101e989310ac0ba011f252df1 Mon Sep 17 00:00:00 2001
From 6547d22fc9e20720d1a896be82b2d50d842f86b0 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 20 Nov 2023 09:25:53 +0800
Subject: [PATCH 2/2] Key revocation on out of bound file access
Subject: [PATCH 4/4] Key revocation on out of bound file access
After successful disk unlocking, grub now takes on the responsibility of
safeguarding passwords or TPM keys exclusively within authenticated
@@ -14,71 +14,17 @@ system boot files, except for essential internal processes like memdisk
and procfs, ensuring key protection against potential breaches due to
inadvertent customizations in grub.cfg.
v2: use cryptocheck command
The grub_disk_is_crypto() function duplicates the purpose of the
cryptocheck command and is therefore removed. A new check function now
calls cryptocheck directly to improve code reuse.
Signed-Off-by: Michael Chang <mchang@suse.com>
Signed-Off-by Michael Chang <mchang@suse.com>
---
grub-core/commands/crypttab.c | 76 +++++++++++++++++++++++++++++++++++
grub-core/disk/diskfilter.c | 1 +
grub-core/commands/crypttab.c | 36 +++++++++++++++++++++++++++++++++++
include/grub/file.h | 1 +
3 files changed, 78 insertions(+)
2 files changed, 37 insertions(+)
diff --git a/grub-core/commands/crypttab.c b/grub-core/commands/crypttab.c
index 9397bede9e..f104154e23 100644
index d3acc4b59..e09296c57 100644
--- a/grub-core/commands/crypttab.c
+++ b/grub-core/commands/crypttab.c
@@ -6,11 +6,47 @@
#include <grub/mm.h>
#include <grub/list.h>
#include <grub/crypttab.h>
+#include <grub/file.h>
GRUB_MOD_LICENSE ("GPLv3+");
grub_crypto_key_list_t *cryptokey_lst;
+static int
+is_unencrypted_disk (grub_disk_t disk)
+{
+ grub_command_t cmd;
+ char *disk_str;
+ int disk_str_len;
+ int res;
+
+ if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
+ return 0; /* This is (crypto*) disk */
+
+ if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID)
+ {
+ char opt[] = "--quiet";
+ char *args[2];
+
+ cmd = grub_command_find ("cryptocheck");
+ if (!cmd) /* No diskfilter module loaded for some reason */
+ return 1;
+
+ disk_str_len = grub_strlen (disk->name) + 2 + 1;
+ disk_str = grub_malloc (disk_str_len);
+ if (!disk_str) /* Something is wrong, better report as unencrypted */
+ return 1;
+
+ grub_snprintf (disk_str, disk_str_len, "(%s)", disk->name);
+ args[0] = opt;
+ args[1] = disk_str;
+ res = cmd->func (cmd, 2, args);
+ grub_free (disk_str);
+ return (res != GRUB_ERR_NONE); /* GRUB_ERR_NONE for encrypted */
+ }
+ return 1;
+}
+
grub_err_t
grub_cryptokey_add_or_update (const char *uuid, const char *key, grub_size_t key_len, const char *path, int is_tpmkey)
{
@@ -89,6 +125,44 @@ grub_cryptokey_tpmkey_discard (void)
@@ -121,6 +121,41 @@ grub_cryptokey_tpmkey_discard (void)
grub_cryptokey_discard();
}
@@ -107,11 +53,8 @@ index 9397bede9e..f104154e23 100644
+ case GRUB_FILE_TYPE_LINUX_INITRD:
+ case GRUB_FILE_TYPE_LOADENV:
+ case GRUB_FILE_TYPE_THEME:
+ if (!disk || is_unencrypted_disk (disk))
+ {
+ grub_cryptokey_discard ();
+ grub_errno = GRUB_ERR_NONE;
+ }
+ if (!disk || !grub_disk_is_crypto (disk))
+ grub_cryptokey_discard ();
+ break;
+ default:
+ break;
@@ -123,29 +66,16 @@ index 9397bede9e..f104154e23 100644
static grub_err_t
grub_cmd_crypttab_entry (grub_command_t cmd __attribute__ ((unused)),
int argc, char **argv)
@@ -121,6 +195,8 @@ GRUB_MOD_INIT(crypttab)
@@ -153,6 +188,7 @@ GRUB_MOD_INIT(crypttab)
{
cmd = grub_register_command ("crypttab_entry", grub_cmd_crypttab_entry,
N_("VOLUME-NAME ENCRYPTED-DEVICE KEY-FILE") , N_("No description"));
+ grub_file_filter_register (GRUB_FILE_FILTER_DISTRUST, grub_distrust_open);
+ grub_dl_set_persistent (mod);
}
GRUB_MOD_FINI(crypttab)
diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c
index b1d5d464f5..e23215486d 100644
--- a/grub-core/disk/diskfilter.c
+++ b/grub-core/disk/diskfilter.c
@@ -590,6 +590,7 @@ grub_diskfilter_open (const char *name, grub_disk_t disk)
disk->total_sectors = lv->size;
disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE;
+
return 0;
grub_dl_set_persistent (mod);
}
diff --git a/include/grub/file.h b/include/grub/file.h
index c463e4f992..804d512231 100644
index fcfd32ce2..daf23a9c9 100644
--- a/include/grub/file.h
+++ b/include/grub/file.h
@@ -185,6 +185,7 @@ extern grub_disk_read_hook_t EXPORT_VAR(grub_file_progress_hook);
@@ -153,9 +83,9 @@ index c463e4f992..804d512231 100644
typedef enum grub_file_filter_id
{
+ GRUB_FILE_FILTER_DISTRUST,
GRUB_FILE_FILTER_NOCAT,
GRUB_FILE_FILTER_VERIFY,
GRUB_FILE_FILTER_GZIO,
GRUB_FILE_FILTER_XZIO,
--
2.49.0
2.42.1

View File

@@ -1,798 +0,0 @@
From eb82056864ac03155a9dd18adbf1ca1c60dc69b5 Mon Sep 17 00:00:00 2001
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Date: Tue, 25 Feb 2025 00:06:18 +0530
Subject: [PATCH 4/9] appendedsig: The creation of trusted and distrusted lists
The trusted certificates and binary hashes, distrusted certificates and
binary/certificate hashes will be extracted from the platform keystore buffer
if Secure Boot is enabled with PKS.
In order to verify the integrity of the kernel, the extracted data
needs to be stored stored in the buffer db and dbx.
The trusted certificates will be extracted from the grub ELFNOTE if Secure Boot is
enabled with static key. In order to verify the integerity of the kernel,
the extracted data needs to be stored in the buffer db.
Note:-
If neither the trusted certificate nor binary hash exists in the distrusted list (dbx),
rejects it while extracting certificate/binary hash from the platform keystore buffer.
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
---
grub-core/commands/appendedsig/appendedsig.c | 617 +++++++++++++++++--
grub-core/kern/file.c | 34 +
include/grub/file.h | 1 +
3 files changed, 590 insertions(+), 62 deletions(-)
diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c
index e63ad1ac64..3df950c00b 100644
--- a/grub-core/commands/appendedsig/appendedsig.c
+++ b/grub-core/commands/appendedsig/appendedsig.c
@@ -33,7 +33,7 @@
#include <grub/libtasn1.h>
#include <grub/env.h>
#include <grub/lockdown.h>
-
+#include <grub/powerpc/ieee1275/platform_keystore.h>
#include "appendedsig.h"
GRUB_MOD_LICENSE ("GPLv3+");
@@ -66,8 +66,23 @@ struct grub_appended_signature
struct pkcs7_signedData pkcs7; /* Parsed PKCS#7 data */
};
-/* Trusted certificates for verifying appended signatures */
-struct x509_certificate *grub_trusted_key;
+/* This represents a trusted/distrusted list*/
+struct grub_database
+{
+ struct x509_certificate *keys; /* Certificates */
+ grub_size_t key_entries; /* Number of certificates */
+ grub_uint8_t **signatures; /* Certificate/binary hashes */
+ grub_size_t *signature_size; /* Size of certificate/binary hashes */
+ grub_size_t signature_entries; /* Number of certificate/binary hashes */
+};
+
+/* Trusted list */
+struct grub_database db = {.keys = NULL, .key_entries = 0, .signatures = NULL,
+ .signature_size = NULL, .signature_entries = 0};
+
+/* Distrusted list */
+struct grub_database dbx = {.signatures = NULL, .signature_size = NULL,
+ .signature_entries = 0};
/*
* Force gcry_rsa to be a module dependency.
@@ -89,6 +104,13 @@ struct x509_certificate *grub_trusted_key;
* also resolves our concerns about loading from the filesystem.
*/
extern gcry_pk_spec_t _gcry_pubkey_spec_rsa;
+extern gcry_md_spec_t _gcry_digest_spec_sha224;
+extern gcry_md_spec_t _gcry_digest_spec_sha384;
+
+/* Free trusted list memory */
+static void free_trusted_list (void);
+/* Free distrusted list memory */
+static void free_distrusted_list (void);
static enum
{ check_sigs_no = 0,
@@ -96,6 +118,204 @@ static enum
check_sigs_forced = 2
} check_sigs = check_sigs_no;
+/*
+ * GUID can be used to determine the hashing function and
+ * generate the hash using determined hashing function.
+ */
+static grub_err_t
+get_hash (const grub_uuid_t *guid, const grub_uint8_t *data, const grub_size_t data_size,
+ grub_uint8_t *hash, grub_size_t *hash_size)
+{
+ gcry_md_spec_t *hash_func = NULL;
+
+ if (guid == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "GUID is null");
+
+ if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA256_GUID, GRUB_UUID_SIZE) == 0 ||
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA256_GUID, GRUB_UUID_SIZE) == 0)
+ hash_func = &_gcry_digest_spec_sha256;
+ else if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA384_GUID, GRUB_UUID_SIZE) == 0 ||
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA384_GUID, GRUB_UUID_SIZE) == 0)
+ hash_func = &_gcry_digest_spec_sha384;
+ else if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA512_GUID, GRUB_UUID_SIZE) == 0 ||
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA512_GUID, GRUB_UUID_SIZE) == 0)
+ hash_func = &_gcry_digest_spec_sha512;
+ else
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "Unsupported GUID for hash");
+
+ grub_memset (hash, 0, GRUB_MAX_HASH_SIZE);
+ grub_crypto_hash (hash_func, hash, data, data_size);
+ *hash_size = hash_func->mdlen;
+
+ return GRUB_ERR_NONE;
+}
+
+/* Add the certificate/binary hash into the trusted/distrusted list */
+static grub_err_t
+add_hash (const grub_uint8_t **data, const grub_size_t data_size,
+ grub_uint8_t ***signature_list, grub_size_t **signature_size_list,
+ grub_size_t *signature_list_entries)
+{
+ grub_uint8_t **signatures = *signature_list;
+ grub_size_t *signature_size = *signature_size_list;
+ grub_size_t signature_entries = *signature_list_entries;
+
+ if (*data == NULL || data_size == 0)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "certificate/binary hash data/size is null");
+
+ signatures = grub_realloc (signatures, sizeof (grub_uint8_t *) * (signature_entries + 1));
+ signature_size = grub_realloc (signature_size,
+ sizeof (grub_size_t) * (signature_entries + 1));
+
+ if (signatures == NULL || signature_size == NULL)
+ {
+ /*
+ * allocated memory will be freed by
+ * free_trusted_list/free_distrusted_list
+ */
+ if (signatures != NULL)
+ {
+ *signature_list = signatures;
+ *signature_list_entries = signature_entries + 1;
+ }
+
+ if (signature_size != NULL)
+ *signature_size_list = signature_size;
+
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
+ }
+
+ signatures[signature_entries] = (grub_uint8_t *) *data;
+ signature_size[signature_entries] = data_size;
+ signature_entries++;
+ *data = NULL;
+
+ *signature_list = signatures;
+ *signature_size_list = signature_size;
+ *signature_list_entries = signature_entries;
+
+ return GRUB_ERR_NONE;
+}
+
+static int
+is_x509 (const grub_uuid_t *guid)
+{
+ if (grub_memcmp (guid, &GRUB_PKS_CERT_X509_GUID, GRUB_UUID_SIZE) == 0)
+ return GRUB_ERR_NONE;
+
+ return GRUB_ERR_UNKNOWN_COMMAND;
+}
+
+static int
+is_cert_match (const struct x509_certificate *distrusted_cert,
+ const struct x509_certificate *db_cert)
+{
+
+ if (grub_memcmp (distrusted_cert->subject, db_cert->subject, db_cert->subject_len) == 0
+ && grub_memcmp (distrusted_cert->serial, db_cert->serial, db_cert->serial_len) == 0
+ && grub_memcmp (distrusted_cert->mpis[0], db_cert->mpis[0], sizeof (db_cert->mpis[0])) == 0
+ && grub_memcmp (distrusted_cert->mpis[1], db_cert->mpis[1], sizeof (db_cert->mpis[1])) == 0)
+ return GRUB_ERR_NONE;
+
+ return GRUB_ERR_UNKNOWN_COMMAND;
+}
+
+/*
+ * Verify the certificate against the certificate from platform keystore buffer's
+ * distrusted list.
+ */
+static grub_err_t
+is_distrusted_cert (const struct x509_certificate *db_cert)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_size_t i = 0;
+ struct x509_certificate *distrusted_cert = NULL;
+
+ for (i = 0; i < grub_pks_keystore.dbx_entries; i++)
+ {
+ if (grub_pks_keystore.dbx[i].data == NULL)
+ continue;
+
+ if (is_x509 (&grub_pks_keystore.dbx[i].guid) == GRUB_ERR_NONE)
+ {
+ distrusted_cert = grub_zalloc (sizeof (struct x509_certificate));
+ if (distrusted_cert == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
+
+ rc = parse_x509_certificate (grub_pks_keystore.dbx[i].data,
+ grub_pks_keystore.dbx[i].data_size, distrusted_cert);
+ if (rc != GRUB_ERR_NONE)
+ {
+ grub_free (distrusted_cert);
+ continue;
+ }
+
+ if (is_cert_match (distrusted_cert, db_cert) == GRUB_ERR_NONE)
+ {
+ grub_printf ("Warning: a trusted certificate CN='%s' is ignored "
+ "because it is on the distrusted list (dbx).\n", db_cert->subject);
+ grub_free (grub_pks_keystore.dbx[i].data);
+ grub_memset (&grub_pks_keystore.dbx[i], 0, sizeof (grub_pks_sd_t));
+ certificate_release (distrusted_cert);
+ grub_free (distrusted_cert);
+ return GRUB_ERR_ACCESS_DENIED;
+ }
+
+ certificate_release (distrusted_cert);
+ grub_free (distrusted_cert);
+ }
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+/* Add the certificate into the trusted/distrusted list */
+static grub_err_t
+add_certificate (const grub_uint8_t *data, const grub_size_t data_size,
+ struct grub_database *database, const grub_size_t is_db)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_size_t key_entries = database->key_entries;
+ struct x509_certificate *cert = NULL;
+
+ if (data == NULL || data_size == 0)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "certificate data/size is null");
+
+ cert = grub_zalloc (sizeof (struct x509_certificate));
+ if (cert == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
+
+ rc = parse_x509_certificate (data, data_size, cert);
+ if (rc != GRUB_ERR_NONE)
+ {
+ grub_dprintf ("appendedsig", "skipping %s certificate (%d)\n",
+ (is_db ? "trusted":"distrusted"), rc);
+ grub_free (cert);
+ return rc;
+ }
+
+ if (is_db)
+ {
+ rc = is_distrusted_cert (cert);
+ if (rc != GRUB_ERR_NONE)
+ {
+ certificate_release (cert);
+ grub_free (cert);
+ return rc;
+ }
+ }
+
+ grub_dprintf ("appendedsig", "add a %s certificate CN='%s'\n",
+ (is_db ? "trusted":"distrusted"), cert->subject);
+
+ key_entries++;
+ cert->next = database->keys;
+ database->keys = cert;
+ database->key_entries = key_entries;
+
+ return rc;
+}
+
static const char *
grub_env_read_sec (struct grub_env_var *var __attribute__((unused)),
const char *val __attribute__((unused)))
@@ -267,9 +487,8 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize)
struct pkcs7_signerInfo *si;
int i;
- if (!grub_trusted_key)
- return grub_error (GRUB_ERR_BAD_SIGNATURE,
- N_("No trusted keys to verify against"));
+ if (!db.key_entries)
+ return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("No trusted keys to verify against"));
err = extract_appended_signature (buf, bufsize, &sig);
if (err != GRUB_ERR_NONE)
@@ -299,17 +518,16 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize)
datasize, i, hash[0], hash[1], hash[2], hash[3]);
err = GRUB_ERR_BAD_SIGNATURE;
- for (pk = grub_trusted_key; pk; pk = pk->next)
- {
- rc = grub_crypto_rsa_pad (&hashmpi, hash, si->hash, pk->mpis[0]);
- if (rc)
- {
- err = grub_error (GRUB_ERR_BAD_SIGNATURE,
- N_("Error padding hash for RSA verification: %d"),
- rc);
- grub_free (context);
- goto cleanup;
- }
+ for (pk = db.keys; pk; pk = pk->next)
+ {
+ rc = grub_crypto_rsa_pad (&hashmpi, hash, si->hash, pk->mpis[0]);
+ if (rc)
+ {
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE,
+ N_("Error padding hash for RSA verification: %d"), rc);
+ grub_free (context);
+ goto cleanup;
+ }
rc = _gcry_pubkey_spec_rsa.verify (0, hashmpi, &si->sig_mpi,
pk->mpis, NULL, NULL);
@@ -402,16 +620,16 @@ grub_cmd_distrust (grub_command_t cmd __attribute__((unused)),
if (cert_num == 1)
{
- cert = grub_trusted_key;
- grub_trusted_key = cert->next;
+ cert = db.keys;
+ db.keys = cert->next;
certificate_release (cert);
grub_free (cert);
return GRUB_ERR_NONE;
}
i = 2;
- prev = grub_trusted_key;
- cert = grub_trusted_key->next;
+ prev = db.keys;
+ cert = db.keys->next;
while (cert)
{
if (i == cert_num)
@@ -464,8 +682,8 @@ grub_cmd_trust (grub_command_t cmd __attribute__((unused)),
grub_dprintf ("appendedsig", "Loaded certificate with CN: %s\n",
cert->subject);
- cert->next = grub_trusted_key;
- grub_trusted_key = cert;
+ cert->next = db.keys;
+ db.keys = cert;
return GRUB_ERR_NONE;
}
@@ -479,7 +697,7 @@ grub_cmd_list (grub_command_t cmd __attribute__((unused)),
int cert_num = 1;
grub_size_t i;
- for (cert = grub_trusted_key; cert; cert = cert->next)
+ for (cert = db.keys; cert; cert = cert->next)
{
grub_printf (N_("Certificate %d:\n"), cert_num);
@@ -579,6 +797,274 @@ static struct grub_fs pseudo_fs = {
static grub_command_t cmd_verify, cmd_list, cmd_distrust, cmd_trust;
+/*
+ * Verify the trusted certificate against the certificate hashes from platform keystore buffer's
+ * distrusted list.
+ */
+static grub_err_t
+is_distrusted_cert_hash (const grub_uint8_t *data, const grub_size_t data_size)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_size_t i = 0, cert_hash_size = 0;
+ grub_uint8_t cert_hash[GRUB_MAX_HASH_SIZE] = { 0 };
+
+ if (data == NULL || data_size == 0)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "trusted certificate data/size is null");
+
+ for (i = 0; i < grub_pks_keystore.dbx_entries; i++)
+ {
+ if (grub_pks_keystore.dbx[i].data == NULL ||
+ grub_pks_keystore.dbx[i].data_size == 0)
+ continue;
+
+ rc = get_hash (&grub_pks_keystore.dbx[i].guid, data, data_size,
+ cert_hash, &cert_hash_size);
+ if (rc != GRUB_ERR_NONE)
+ continue;
+
+ if (cert_hash_size == grub_pks_keystore.dbx[i].data_size &&
+ grub_memcmp (grub_pks_keystore.dbx[i].data, cert_hash, cert_hash_size) == 0)
+ {
+ grub_printf ("Warning: a trusted certificate (%02x%02x%02x%02x) is ignored "
+ "because this certificate hash is on the distrusted list (dbx).\n",
+ cert_hash[0], cert_hash[1], cert_hash[2], cert_hash[3]);
+ grub_free (grub_pks_keystore.dbx[i].data);
+ grub_memset (&grub_pks_keystore.dbx[i], 0, sizeof (grub_pks_keystore.dbx[i]));
+ return GRUB_ERR_BAD_SIGNATURE;
+ }
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * Verify the trusted binary hash against the platform keystore buffer's
+ * distrusted list.
+ */
+static grub_err_t
+is_distrusted_binary_hash (const grub_uint8_t *binary_hash,
+ const grub_size_t binary_hash_size)
+{
+ grub_size_t i = 0;
+
+ for (i = 0; i < grub_pks_keystore.dbx_entries; i++)
+ {
+ if (grub_pks_keystore.dbx[i].data == NULL ||
+ grub_pks_keystore.dbx[i].data_size == 0)
+ continue;
+
+ if (binary_hash_size == grub_pks_keystore.dbx[i].data_size &&
+ grub_memcmp (grub_pks_keystore.dbx[i].data, binary_hash, binary_hash_size) == 0)
+ {
+ grub_printf ("Warning: a trusted binary hash (%02x%02x%02x%02x) is ignored"
+ " because it is on the distrusted list (dbx).\n",
+ binary_hash[0], binary_hash[1], binary_hash[2], binary_hash[3]);
+ grub_free (grub_pks_keystore.dbx[i].data);
+ grub_memset (&grub_pks_keystore.dbx[i], 0, sizeof(grub_pks_keystore.dbx[i]));
+ return GRUB_ERR_BAD_SIGNATURE;
+ }
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * Extract the binary hashes from the platform keystore buffer,
+ * and add it to the trusted list if it does not exist in the distrusted list.
+ */
+static grub_err_t
+add_trusted_binary_hash (const grub_uint8_t **data, const grub_size_t data_size)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+
+ if (*data == NULL || data_size == 0)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "trusted binary hash data/size is null");
+
+ rc = is_distrusted_binary_hash (*data, data_size);
+ if (rc != GRUB_ERR_NONE)
+ return rc;
+
+ rc = add_hash (data, data_size, &db.signatures, &db.signature_size,
+ &db.signature_entries);
+ return rc;
+}
+
+static int
+is_hash (const grub_uuid_t *guid)
+{
+ /* GUID type of the binary hash */
+ if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA256_GUID, GRUB_UUID_SIZE) == 0 ||
+ grub_memcmp (guid, &GRUB_PKS_CERT_SHA384_GUID, GRUB_UUID_SIZE) == 0 ||
+ grub_memcmp (guid, &GRUB_PKS_CERT_SHA512_GUID, GRUB_UUID_SIZE) == 0)
+ return GRUB_ERR_NONE;
+
+ /* GUID type of the certificate hash */
+ if (grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA256_GUID, GRUB_UUID_SIZE) == 0 ||
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA384_GUID, GRUB_UUID_SIZE) == 0 ||
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA512_GUID, GRUB_UUID_SIZE) == 0)
+ return GRUB_ERR_NONE;
+
+ return GRUB_ERR_UNKNOWN_COMMAND;
+}
+
+/*
+ * Extract the x509 certificates/binary hashes from the platform keystore buffer,
+ * parse it, and add it to the trusted list.
+ */
+static grub_err_t
+create_trusted_list (void)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_size_t i = 0;
+
+ for (i = 0; i < grub_pks_keystore.db_entries; i++)
+ {
+ if (is_hash (&grub_pks_keystore.db[i].guid) == GRUB_ERR_NONE)
+ {
+ rc = add_trusted_binary_hash ((const grub_uint8_t **)
+ &grub_pks_keystore.db[i].data,
+ grub_pks_keystore.db[i].data_size);
+ if (rc == GRUB_ERR_OUT_OF_MEMORY)
+ return rc;
+ }
+ else if (is_x509 (&grub_pks_keystore.db[i].guid) == GRUB_ERR_NONE)
+ {
+ rc = is_distrusted_cert_hash (grub_pks_keystore.db[i].data,
+ grub_pks_keystore.db[i].data_size);
+ if (rc != GRUB_ERR_NONE)
+ continue;
+
+ rc = add_certificate (grub_pks_keystore.db[i].data,
+ grub_pks_keystore.db[i].data_size, &db, 1);
+ if (rc == GRUB_ERR_OUT_OF_MEMORY)
+ return rc;
+ else if (rc != GRUB_ERR_NONE)
+ continue;
+ }
+ else
+ grub_dprintf ("appendedsig", "unsupported signature data type and "
+ "skipping trusted data (%" PRIuGRUB_SIZE ")\n", i + 1);
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * Extract the certificates, certificate/binary hashes out of the platform keystore buffer,
+ * and add it to the distrusted list.
+ */
+static grub_err_t
+create_distrusted_list (void)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_size_t i = 0;
+
+ for (i = 0; i < grub_pks_keystore.dbx_entries; i++)
+ {
+ if (grub_pks_keystore.dbx[i].data != NULL ||
+ grub_pks_keystore.dbx[i].data_size > 0)
+ {
+ if (is_x509 (&grub_pks_keystore.dbx[i].guid) == GRUB_ERR_NONE)
+ {
+ rc = add_certificate (grub_pks_keystore.dbx[i].data,
+ grub_pks_keystore.dbx[i].data_size, &dbx, 0);
+ if (rc == GRUB_ERR_OUT_OF_MEMORY)
+ return rc;
+ }
+ else if (is_hash (&grub_pks_keystore.dbx[i].guid) == GRUB_ERR_NONE)
+ {
+ rc = add_hash ((const grub_uint8_t **) &grub_pks_keystore.dbx[i].data,
+ grub_pks_keystore.dbx[i].data_size,
+ &dbx.signatures, &dbx.signature_size,
+ &dbx.signature_entries);
+ if (rc != GRUB_ERR_NONE)
+ return rc;
+ }
+ else
+ grub_dprintf ("appendedsig", "unsupported signature data type and "
+ "skipping distrusted data (%" PRIuGRUB_SIZE ")\n", i + 1);
+ }
+ }
+
+ return rc;
+}
+
+/*
+ * Extract the x509 certificates from the ELF note header,
+ * parse it, and add it to the trusted list.
+ */
+static grub_err_t
+build_static_trusted_list (const struct grub_module_header *header)
+{
+ grub_err_t err = GRUB_ERR_NONE;
+ struct grub_file pseudo_file;
+ grub_uint8_t *cert_data = NULL;
+ grub_ssize_t cert_data_size = 0;
+
+ grub_memset (&pseudo_file, 0, sizeof (pseudo_file));
+ pseudo_file.fs = &pseudo_fs;
+ pseudo_file.size = header->size - sizeof (struct grub_module_header);
+ pseudo_file.data = (char *) header + sizeof (struct grub_module_header);
+
+ grub_dprintf ("appendedsig", "found an x509 key, size=%" PRIuGRUB_UINT64_T "\n",
+ pseudo_file.size);
+
+ err = grub_read_file (&pseudo_file, &cert_data, &cert_data_size);
+ if (err != GRUB_ERR_NONE)
+ return err;
+
+ err = add_certificate (cert_data, cert_data_size, &db, 1);
+ grub_free (cert_data);
+
+ return err;
+}
+
+/* releasing memory */
+static void
+free_trusted_list (void)
+{
+ struct x509_certificate *cert;
+ grub_size_t i = 0;
+
+ while (db.keys != NULL)
+ {
+ cert = db.keys;
+ db.keys = db.keys->next;
+ certificate_release (cert);
+ grub_free (cert);
+ }
+
+ for (i = 0; i < db.signature_entries; i++)
+ grub_free (db.signatures[i]);
+
+ grub_free (db.signatures);
+ grub_free (db.signature_size);
+ grub_memset (&db, 0, sizeof (db));
+}
+
+/* releasing memory */
+static void
+free_distrusted_list (void)
+{
+ struct x509_certificate *cert;
+ grub_size_t i = 0;
+
+ while (dbx.keys != NULL)
+ {
+ cert = dbx.keys;
+ dbx.keys = dbx.keys->next;
+ certificate_release (cert);
+ grub_free (cert);
+ }
+
+ for (i = 0; i < dbx.signature_entries; i++)
+ grub_free (dbx.signatures[i]);
+
+ grub_free (dbx.signatures);
+ grub_free (dbx.signature_size);
+ grub_memset (&dbx, 0, sizeof (dbx));
+}
+
GRUB_MOD_INIT (appendedsig)
{
int rc;
@@ -588,10 +1074,7 @@ GRUB_MOD_INIT (appendedsig)
if (grub_is_lockdown () == GRUB_LOCKDOWN_ENABLED)
check_sigs = check_sigs_forced;
- grub_trusted_key = NULL;
-
- grub_register_variable_hook ("check_appended_signatures",
- grub_env_read_sec, grub_env_write_sec);
+ grub_register_variable_hook ("check_appended_signatures", grub_env_read_sec, grub_env_write_sec);
grub_env_export ("check_appended_signatures");
rc = asn1_init ();
@@ -599,40 +1082,50 @@ GRUB_MOD_INIT (appendedsig)
grub_fatal ("Error initing ASN.1 data structures: %d: %s\n", rc,
asn1_strerror (rc));
- FOR_MODULES (header)
- {
- struct grub_file pseudo_file;
- struct x509_certificate *pk = NULL;
- grub_err_t err;
-
- /* Not an ELF module, skip. */
- if (header->type != OBJ_TYPE_X509_PUBKEY)
- continue;
-
- grub_memset (&pseudo_file, 0, sizeof (pseudo_file));
- pseudo_file.fs = &pseudo_fs;
- pseudo_file.size = header->size - sizeof (struct grub_module_header);
- pseudo_file.data = (char *) header + sizeof (struct grub_module_header);
-
- grub_dprintf ("appendedsig",
- "Found an x509 key, size=%" PRIuGRUB_UINT64_T "\n",
- pseudo_file.size);
-
- pk = grub_zalloc (sizeof (struct x509_certificate));
- if (!pk)
- {
- grub_fatal ("Out of memory loading initial certificates");
- }
-
- err = read_cert_from_file (&pseudo_file, pk);
- if (err != GRUB_ERR_NONE)
- grub_fatal ("Error loading initial key: %s", grub_errmsg);
-
- grub_dprintf ("appendedsig", "loaded certificate CN='%s'\n", pk->subject);
-
- pk->next = grub_trusted_key;
- grub_trusted_key = pk;
- }
+ if (!grub_pks_use_keystore && check_sigs == check_sigs_forced)
+ {
+ FOR_MODULES (header)
+ {
+ /* Not an ELF module, skip. */
+ if (header->type != OBJ_TYPE_X509_PUBKEY)
+ continue;
+
+ rc = build_static_trusted_list (header);
+ if (rc != GRUB_ERR_NONE)
+ {
+ free_trusted_list ();
+ grub_error (rc, "static trusted list creation failed");
+ }
+ else
+ grub_printf ("appendedsig: the trusted list now has %" PRIuGRUB_SIZE " static keys\n",
+ db.key_entries);
+ }
+ }
+ else if (grub_pks_use_keystore && check_sigs == check_sigs_forced)
+ {
+ rc = create_trusted_list ();
+ if (rc != GRUB_ERR_NONE)
+ {
+ free_trusted_list ();
+ grub_error (rc, "trusted list creation failed");
+ }
+ else
+ {
+ rc = create_distrusted_list ();
+ if (rc != GRUB_ERR_NONE)
+ {
+ free_trusted_list ();
+ free_distrusted_list ();
+ grub_error (rc, "distrusted list creation failed");
+ }
+ else
+ grub_printf ("appendedsig: the trusted list now has %" PRIuGRUB_SIZE " keys.\n"
+ "appendedsig: the distrusted list now has %" PRIuGRUB_SIZE " keys.\n",
+ db.signature_entries + db.key_entries, dbx.signature_entries);
+ }
+
+ grub_pks_free_keystore ();
+ }
cmd_trust =
grub_register_command ("trust_certificate", grub_cmd_trust,
diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c
index 6e7efe89ab..7217a6ea7f 100644
--- a/grub-core/kern/file.c
+++ b/grub-core/kern/file.c
@@ -231,3 +231,37 @@ grub_file_seek (grub_file_t file, grub_off_t offset)
return old;
}
+
+grub_err_t
+grub_read_file (const grub_file_t file, grub_uint8_t **data, grub_ssize_t *data_size)
+{
+ grub_uint8_t *buffer = NULL;
+ grub_ssize_t read_size = 0;
+ grub_off_t total_read_size = 0;
+ grub_off_t file_size = grub_file_size (file);
+
+ if (file_size == GRUB_FILE_SIZE_UNKNOWN)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("could not determine the size of the file."));
+
+ buffer = grub_zalloc (file_size);
+ if (buffer == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+
+ while (total_read_size < file_size)
+ {
+ read_size = grub_file_read (file, &buffer[total_read_size], file_size - total_read_size);
+ if (read_size < 0)
+ {
+ grub_free (buffer);
+ return grub_error (GRUB_ERR_READ_ERROR, N_("unable to read the file"));
+ }
+
+ total_read_size += read_size;
+ }
+
+ *data = buffer;
+ *data_size = total_read_size;
+
+ return GRUB_ERR_NONE;
+}
diff --git a/include/grub/file.h b/include/grub/file.h
index f9484f8d69..804d512231 100644
--- a/include/grub/file.h
+++ b/include/grub/file.h
@@ -219,6 +219,7 @@ grub_ssize_t EXPORT_FUNC(grub_file_read) (grub_file_t file, void *buf,
grub_size_t len);
grub_off_t EXPORT_FUNC(grub_file_seek) (grub_file_t file, grub_off_t offset);
grub_err_t EXPORT_FUNC(grub_file_close) (grub_file_t file);
+grub_err_t EXPORT_FUNC(grub_read_file) (const grub_file_t file, grub_uint8_t **data, grub_ssize_t *data_size);
/* Return value of grub_file_size() in case file size is unknown. */
#define GRUB_FILE_SIZE_UNKNOWN 0xffffffffffffffffULL
--
2.48.1

View File

@@ -1,70 +0,0 @@
From 13ae8a054a4a0b871ce3fd8ddaaff7a4f2ba2478 Mon Sep 17 00:00:00 2001
From: Maxim Suhanov <dfirblog@gmail.com>
Date: Thu, 8 May 2025 19:02:10 +0200
Subject: [PATCH 4/8] commands/search: Add the diskfilter support
When the --cryptodisk-only argument is given, also check the target
device using the "cryptocheck" command, if available.
This extends the checks to common layouts like LVM-on-LUKS, so the
--cryptodisk-only argument transparently handles such setups.
Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/commands/search.c | 32 +++++++++++++++++++++++++++++++-
1 file changed, 31 insertions(+), 1 deletion(-)
diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c
index f6bfef9585..185c1e70f7 100644
--- a/grub-core/commands/search.c
+++ b/grub-core/commands/search.c
@@ -54,6 +54,36 @@ struct search_ctx
int is_cache;
};
+static bool
+is_unencrypted_disk (grub_disk_t disk)
+{
+ grub_command_t cmd;
+ char *disk_str;
+ int disk_str_len;
+ int res;
+
+ if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
+ return false; /* This is (crypto) disk. */
+
+ if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID)
+ {
+ cmd = grub_command_find ("cryptocheck");
+ if (cmd == NULL) /* No diskfilter module loaded for some reason. */
+ return true;
+
+ disk_str_len = grub_strlen (disk->name) + 2 + 1;
+ disk_str = grub_malloc (disk_str_len);
+ if (disk_str == NULL) /* Something is wrong, better report as unencrypted. */
+ return true;
+
+ grub_snprintf (disk_str, disk_str_len, "(%s)", disk->name);
+ res = cmd->func (cmd, 1, &disk_str);
+ grub_free (disk_str);
+ return (res != GRUB_ERR_NONE) ? true : false; /* GRUB_ERR_NONE for encrypted. */
+ }
+ return true;
+}
+
/* Helper for FUNC_NAME. */
static int
iterate_device (const char *name, void *data)
@@ -97,7 +127,7 @@ iterate_device (const char *name, void *data)
grub_errno = GRUB_ERR_NONE;
return 0;
}
- if (dev->disk == NULL || dev->disk->dev->id != GRUB_DISK_DEVICE_CRYPTODISK_ID)
+ if (dev->disk == NULL || is_unencrypted_disk (dev->disk) == true)
{
grub_device_close (dev);
grub_errno = GRUB_ERR_NONE;
--
2.49.0

View File

@@ -1,92 +0,0 @@
From 8f99c43384b9122eedeab1411ab5076ca5878ef9 Mon Sep 17 00:00:00 2001
From: Lidong Chen <lidong.chen@oracle.com>
Date: Fri, 22 Nov 2024 06:27:58 +0000
Subject: [PATCH 04/20] fs/tar: Integer overflow leads to heap OOB write
Both namesize and linksize are derived from hd.size, a 12-digit octal
number parsed by read_number(). Later direct arithmetic calculation like
"namesize + 1" and "linksize + 1" may exceed the maximum value of
grub_size_t leading to heap OOB write. This patch fixes the issue by
using grub_add() and checking for an overflow.
Fixes: CVE-2024-45780
Reported-by: Nils Langius <nils@langius.de>
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Alec Brown <alec.r.brown@oracle.com>
---
grub-core/fs/tar.c | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/grub-core/fs/tar.c b/grub-core/fs/tar.c
index c551ed6b52..a9e39b0eb6 100644
--- a/grub-core/fs/tar.c
+++ b/grub-core/fs/tar.c
@@ -25,6 +25,7 @@
#include <grub/mm.h>
#include <grub/dl.h>
#include <grub/i18n.h>
+#include <grub/safemath.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -76,6 +77,7 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
{
struct head hd;
int reread = 0, have_longname = 0, have_longlink = 0;
+ grub_size_t sz;
data->hofs = data->next_hofs;
@@ -97,7 +99,11 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
{
grub_err_t err;
grub_size_t namesize = read_number (hd.size, sizeof (hd.size));
- *name = grub_malloc (namesize + 1);
+
+ if (grub_add (namesize, 1, &sz))
+ return grub_error (GRUB_ERR_BAD_FS, N_("name size overflow"));
+
+ *name = grub_malloc (sz);
if (*name == NULL)
return grub_errno;
err = grub_disk_read (data->disk, 0,
@@ -117,15 +123,19 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
{
grub_err_t err;
grub_size_t linksize = read_number (hd.size, sizeof (hd.size));
- if (data->linkname_alloc < linksize + 1)
+
+ if (grub_add (linksize, 1, &sz))
+ return grub_error (GRUB_ERR_BAD_FS, N_("link size overflow"));
+
+ if (data->linkname_alloc < sz)
{
char *n;
- n = grub_calloc (2, linksize + 1);
+ n = grub_calloc (2, sz);
if (!n)
return grub_errno;
grub_free (data->linkname);
data->linkname = n;
- data->linkname_alloc = 2 * (linksize + 1);
+ data->linkname_alloc = 2 * (sz);
}
err = grub_disk_read (data->disk, 0,
@@ -148,7 +158,10 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
while (extra_size < sizeof (hd.prefix)
&& hd.prefix[extra_size])
extra_size++;
- *name = grub_malloc (sizeof (hd.name) + extra_size + 2);
+
+ if (grub_add (sizeof (hd.name) + 2, extra_size, &sz))
+ return grub_error (GRUB_ERR_BAD_FS, N_("long name size overflow"));
+ *name = grub_malloc (sz);
if (*name == NULL)
return grub_errno;
if (hd.prefix[0])
--
2.48.1

View File

@@ -1,218 +0,0 @@
From 8c0b5f200352603e53b799fca7b63f845a978f19 Mon Sep 17 00:00:00 2001
From: Stefan Berger <stefanb@linux.ibm.com>
Date: Tue, 26 Nov 2024 15:39:43 -0500
Subject: [PATCH 4/7] ieee1275/ibmvpm: Move TPM initialization functions to own
file
Move common initialization functions from the ibmvtpm driver module into
tcg2.c that will be moved into the new TCG2 driver in a subsequent patch.
Make the functions available to the ibmvtpm driver as public functions
and variables.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/Makefile.core.def | 1 +
grub-core/commands/ieee1275/ibmvtpm.c | 44 ++-----------------
grub-core/lib/ieee1275/tcg2.c | 61 +++++++++++++++++++++++++++
include/grub/ieee1275/tpm.h | 31 ++++++++++++++
4 files changed, 97 insertions(+), 40 deletions(-)
create mode 100644 grub-core/lib/ieee1275/tcg2.c
create mode 100644 include/grub/ieee1275/tpm.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 40427165e..c5fd796d4 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1155,6 +1155,7 @@ module = {
name = tpm;
common = commands/tpm.c;
ieee1275 = commands/ieee1275/ibmvtpm.c;
+ ieee1275 = lib/ieee1275/tcg2.c;
enable = powerpc_ieee1275;
};
diff --git a/grub-core/commands/ieee1275/ibmvtpm.c b/grub-core/commands/ieee1275/ibmvtpm.c
index dd30c7432..284673217 100644
--- a/grub-core/commands/ieee1275/ibmvtpm.c
+++ b/grub-core/commands/ieee1275/ibmvtpm.c
@@ -23,46 +23,10 @@
#include <grub/types.h>
#include <grub/tpm.h>
#include <grub/ieee1275/ieee1275.h>
+#include <grub/ieee1275/tpm.h>
#include <grub/mm.h>
#include <grub/misc.h>
-static grub_ieee1275_ihandle_t tpm_ihandle;
-static grub_uint8_t tpm_version;
-
-static void
-tpm_get_tpm_version (void)
-{
- grub_ieee1275_phandle_t vtpm;
- char buffer[20];
-
- if (!grub_ieee1275_finddevice ("/vdevice/vtpm", &vtpm) &&
- !grub_ieee1275_get_property (vtpm, "compatible", buffer,
- sizeof (buffer), NULL) &&
- !grub_strcmp (buffer, "IBM,vtpm20"))
- tpm_version = 2;
-}
-
-static grub_err_t
-tpm_init (void)
-{
- static int init_success = 0;
-
- if (!init_success)
- {
- if (grub_ieee1275_open ("/vdevice/vtpm", &tpm_ihandle) < 0)
- {
- tpm_ihandle = GRUB_IEEE1275_IHANDLE_INVALID;
- return GRUB_ERR_UNKNOWN_DEVICE;
- }
-
- init_success = 1;
-
- tpm_get_tpm_version ();
- }
-
- return GRUB_ERR_NONE;
-}
-
static int
ibmvtpm_2hash_ext_log (grub_uint8_t pcrindex,
grub_uint32_t eventtype,
@@ -88,7 +52,7 @@ ibmvtpm_2hash_ext_log (grub_uint8_t pcrindex,
INIT_IEEE1275_COMMON (&args.common, "call-method", 8, 2);
args.method = (grub_ieee1275_cell_t) "2hash-ext-log";
- args.ihandle = tpm_ihandle;
+ args.ihandle = grub_ieee1275_tpm_ihandle;
args.pcrindex = pcrindex;
args.eventtype = eventtype;
args.description = (grub_ieee1275_cell_t) description;
@@ -136,7 +100,7 @@ grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr,
grub_dprintf ("tpm", "log_event, pcr = %d, size = 0x%" PRIxGRUB_SIZE ", %s\n",
pcr, size, description);
- if (tpm_version == 2)
+ if (grub_ieee1275_tpm_version == 2)
return tpm2_log_event (buf, size, pcr, description);
return GRUB_ERR_NONE;
@@ -149,5 +113,5 @@ grub_tpm_present (void)
* Call tpm_init() "late" rather than from GRUB_MOD_INIT() so that device nodes
* can be found.
*/
- return tpm_init() == GRUB_ERR_NONE;
+ return grub_ieee1275_tpm_init() == GRUB_ERR_NONE;
}
diff --git a/grub-core/lib/ieee1275/tcg2.c b/grub-core/lib/ieee1275/tcg2.c
new file mode 100644
index 000000000..1819d1447
--- /dev/null
+++ b/grub-core/lib/ieee1275/tcg2.c
@@ -0,0 +1,61 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2024 IBM Corporation
+ * Copyright (C) 2024 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/tpm.h>
+#include <grub/ieee1275/tpm.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+
+grub_ieee1275_ihandle_t grub_ieee1275_tpm_ihandle;
+grub_uint8_t grub_ieee1275_tpm_version;
+
+static void
+tpm_get_tpm_version (void)
+{
+ grub_ieee1275_phandle_t vtpm;
+ char buffer[20];
+
+ if (!grub_ieee1275_finddevice ("/vdevice/vtpm", &vtpm) &&
+ !grub_ieee1275_get_property (vtpm, "compatible", buffer,
+ sizeof (buffer), NULL) &&
+ !grub_strcmp (buffer, "IBM,vtpm20"))
+ grub_ieee1275_tpm_version = 2;
+}
+
+grub_err_t
+grub_ieee1275_tpm_init (void)
+{
+ static int init_success = 0;
+
+ if (!init_success)
+ {
+ if (grub_ieee1275_open ("/vdevice/vtpm", &grub_ieee1275_tpm_ihandle) < 0)
+ {
+ grub_ieee1275_tpm_ihandle = GRUB_IEEE1275_IHANDLE_INVALID;
+ return GRUB_ERR_UNKNOWN_DEVICE;
+ }
+
+ init_success = 1;
+
+ tpm_get_tpm_version ();
+ }
+
+ return GRUB_ERR_NONE;
+}
diff --git a/include/grub/ieee1275/tpm.h b/include/grub/ieee1275/tpm.h
new file mode 100644
index 000000000..9575c1c68
--- /dev/null
+++ b/include/grub/ieee1275/tpm.h
@@ -0,0 +1,31 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2024 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_IEEE1275_TPM_HEADER
+#define GRUB_IEEE1275_TPM_HEADER 1
+
+#include <grub/err.h>
+#include <grub/types.h>
+#include <grub/ieee1275/ieee1275.h>
+
+extern grub_ieee1275_ihandle_t grub_ieee1275_tpm_ihandle;
+extern grub_uint8_t grub_ieee1275_tpm_version;
+
+extern grub_err_t grub_ieee1275_tpm_init (void);
+
+#endif
--
2.43.0

View File

@@ -0,0 +1,28 @@
From 7717cd9c27f18703287403af1a955588e3d0261f Mon Sep 17 00:00:00 2001
From: mamatha <mainamdar@in.ibm.com>
Date: Sat, 24 Sep 2022 11:22:39 +0530
Subject: [PATCH 4/4] ofpath controller name update
patch to update ofpath controller name
Signed-off-by: mamatha <mainamdar@in.ibm.com>
---
grub-core/osdep/linux/ofpath.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
index 212782d3f..7d31cfd0f 100644
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -483,6 +483,8 @@ of_path_get_nvmeof_adapter_info(char* sysfs_path,
buf3=strchr(buf2,'-')+1;
buf3=strchr(buf3,'-')+1;
nvmeof_info->target_wwpn = buf3;
+ buf3=strchr(buf3,'x')+1;
+ nvmeof_info->target_wwpn = buf3;
buf3 = strchr(nvmeof_info->target_wwpn,',');
*buf3 = '\0';
--
2.35.3

View File

@@ -1,59 +0,0 @@
From 9f8f5e0d45165b99d0f3ce9bf37382738e0bddb7 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 17 Jul 2025 13:29:48 +0800
Subject: [PATCH 4/4] tftp: Fix hang when file is a directory
We observed an issue when accessing a remote directory via TFTP: GRUB
hangs indefinitely instead of returning an error immediately.
The packet capture [1] shows that the server doesn't send an error
packet right after the RRQ. Instead, it first replies with an OACK
indicating tsize=22, as if the target were a regular file. After GRUB
sends its ACK, the server then sends an error "Is a directory". GRUB
ignores this delayed error and hangs while waiting for data that never
arrives.
This happens because GRUB currently assumes any error must follow the
RRQ immediately, before data transfer begins. Once it receives an OACK,
it switches to expecting data packets and neglects any error that
arrives afterward.
To work around this, we detect an error on block 0 immediately after
OACK, set the eof and stall flags to break out of the receive loop, and
close the socket (so that tftp_close() won't send another error). GRUB
will then report the error and exit properly.
[1]
Source Destination Info
192.168.100.122 192.168.100.2 Read Request, File: /grub/i386-pc, Transfer type: octet, blksize=1024, tsize=0
192.168.100.2 192.168.100.122 Option Acknowledgement, blksize=1024, tsize=22
192.168.100.122 192.168.100.2 Acknowledgement, Block: 0
192.168.100.2 192.168.100.122 Error Code, Code: Not defined, Message: Is a directory
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/net/tftp.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
index 409b1d09b..93452fe3b 100644
--- a/grub-core/net/tftp.c
+++ b/grub-core/net/tftp.c
@@ -250,6 +250,14 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)),
grub_netbuff_free (nb);
return GRUB_ERR_NONE;
case TFTP_ERROR:
+ if (data->have_oack == 1 && data->block == 0)
+ {
+ file->device->net->eof = 1;
+ file->device->net->stall = 1;
+ /* Do not send closed error code back to server in tftp_close() */
+ grub_net_udp_close (data->sock);
+ data->sock = NULL;
+ }
data->have_oack = 1;
grub_error (GRUB_ERR_IO, "%s", tftph->u.err.errmsg);
grub_error_save (&data->save_err);
--
2.50.0

View File

@@ -1,413 +0,0 @@
From 75c480885ab00fb9bc046fe214df60007116aef2 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Mon, 7 Apr 2025 16:29:18 +0800
Subject: [PATCH 4/7] tss2: Add TPM 2.0 NV index commands
The following TPM 2.0 commands are introduced to tss2 to access the
TPM non-volatile memory associated with the NV index handles:
- TPM2_NV_DefineSpace,
- TPM2_NV_UndefineSpace,
- TPM2_NV_ReadPublic,
- TPM2_NV_Read,
- TPM2_NV_Write.
The related marshal/unmarshal functions are also introduced.
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/lib/tss2/tpm2_cmd.c | 201 ++++++++++++++++++++++++++++++++
grub-core/lib/tss2/tpm2_cmd.h | 32 +++++
grub-core/lib/tss2/tss2_mu.c | 39 +++++++
grub-core/lib/tss2/tss2_mu.h | 12 ++
grub-core/lib/tss2/tss2_types.h | 6 +
5 files changed, 290 insertions(+)
diff --git a/grub-core/lib/tss2/tpm2_cmd.c b/grub-core/lib/tss2/tpm2_cmd.c
index 211d807d5..6d25db1ab 100644
--- a/grub-core/lib/tss2/tpm2_cmd.c
+++ b/grub-core/lib/tss2/tpm2_cmd.c
@@ -1045,3 +1045,204 @@ grub_tpm2_testparms (const TPMT_PUBLIC_PARMS_t *parms,
return TPM_RC_SUCCESS;
}
+
+TPM_RC_t
+grub_tpm2_nv_definespace (const TPMI_RH_PROVISION_t authHandle,
+ const TPMS_AUTH_COMMAND_t *authCommand,
+ const TPM2B_AUTH_t *auth,
+ const TPM2B_NV_PUBLIC_t *publicInfo)
+{
+ TPM_RC_t rc;
+ struct grub_tpm2_buffer in;
+ struct grub_tpm2_buffer out;
+ TPMI_ST_COMMAND_TAG_t tag = authCommand ? TPM_ST_SESSIONS : TPM_ST_NO_SESSIONS;
+ TPM_RC_t responseCode;
+
+ if (publicInfo == NULL)
+ return TPM_RC_VALUE;
+
+ /* Marshal */
+ grub_tpm2_buffer_init (&in);
+ grub_tpm2_buffer_pack_u32 (&in, authHandle);
+ if (authCommand != NULL)
+ grub_Tss2_MU_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
+ if (auth != NULL)
+ grub_Tss2_MU_TPM2B_Marshal (&in, auth->size, auth->buffer);
+ else
+ grub_tpm2_buffer_pack_u16 (&in, 0);
+ grub_Tss2_MU_TPM2B_NV_PUBLIC_Marshal (&in, publicInfo);
+ if (in.error != 0)
+ return TPM_RC_FAILURE;
+
+ /* Submit */
+ grub_tpm2_buffer_init (&out);
+ rc = tpm2_submit_command (tag, TPM_CC_NV_DefineSpace, &responseCode, &in, &out);
+ if (rc != TPM_RC_SUCCESS)
+ return rc;
+ if (responseCode != TPM_RC_SUCCESS)
+ return responseCode;
+
+ /* Unmarshal */
+ if (out.error != 0)
+ return TPM_RC_FAILURE;
+
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC_t
+grub_tpm2_nv_undefinespace (const TPMI_RH_PROVISION_t authHandle,
+ const TPMI_RH_NV_INDEX_t nvIndex,
+ const TPMS_AUTH_COMMAND_t *authCommand)
+{
+ TPM_RC_t rc;
+ struct grub_tpm2_buffer in;
+ struct grub_tpm2_buffer out;
+ TPMI_ST_COMMAND_TAG_t tag = authCommand ? TPM_ST_SESSIONS : TPM_ST_NO_SESSIONS;
+ TPM_RC_t responseCode;
+
+ /* Marshal */
+ grub_tpm2_buffer_init (&in);
+ grub_tpm2_buffer_pack_u32 (&in, authHandle);
+ grub_tpm2_buffer_pack_u32 (&in, nvIndex);
+ if (authCommand != NULL)
+ grub_Tss2_MU_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
+ if (in.error != 0)
+ return TPM_RC_FAILURE;
+
+ /* Submit */
+ grub_tpm2_buffer_init (&out);
+ rc = tpm2_submit_command (tag, TPM_CC_NV_UndefineSpace, &responseCode, &in, &out);
+ if (rc != TPM_RC_SUCCESS)
+ return rc;
+ if (responseCode != TPM_RC_SUCCESS)
+ return responseCode;
+
+ /* Unmarshal */
+ if (out.error != 0)
+ return TPM_RC_FAILURE;
+
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC_t
+grub_tpm2_nv_readpublic (const TPMI_RH_NV_INDEX_t nvIndex,
+ const TPMS_AUTH_COMMAND_t *authCommand,
+ TPM2B_NV_PUBLIC_t *nvPublic,
+ TPM2B_NAME_t *nvName)
+{
+ TPM_RC_t rc;
+ struct grub_tpm2_buffer in;
+ struct grub_tpm2_buffer out;
+ TPMI_ST_COMMAND_TAG_t tag = authCommand ? TPM_ST_SESSIONS : TPM_ST_NO_SESSIONS;
+ TPM_RC_t responseCode;
+ grub_uint32_t param_size;
+
+ /* Marshal */
+ grub_tpm2_buffer_init (&in);
+ grub_tpm2_buffer_pack_u32 (&in, nvIndex);
+ if (authCommand != NULL)
+ grub_Tss2_MU_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
+ if (in.error != 0)
+ return TPM_RC_FAILURE;
+
+ /* Submit */
+ grub_tpm2_buffer_init (&out);
+ rc = tpm2_submit_command (tag, TPM_CC_NV_ReadPublic, &responseCode, &in, &out);
+ if (rc != TPM_RC_SUCCESS)
+ return rc;
+ if (responseCode != TPM_RC_SUCCESS)
+ return responseCode;
+
+ /* Unmarshal */
+ if (tag == TPM_ST_SESSIONS)
+ grub_tpm2_buffer_unpack_u32 (&out, &param_size);
+ grub_Tss2_MU_TPM2B_NV_PUBLIC_Unmarshal (&out, nvPublic);
+ grub_Tss2_MU_TPM2B_NAME_Unmarshal (&out, nvName);
+ if (out.error != 0)
+ return TPM_RC_FAILURE;
+
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC_t
+grub_tpm2_nv_read (const TPMI_RH_NV_AUTH_t authHandle,
+ const TPMI_RH_NV_INDEX_t nvIndex,
+ const TPMS_AUTH_COMMAND_t *authCommand,
+ const grub_uint16_t size,
+ const grub_uint16_t offset,
+ TPM2B_MAX_NV_BUFFER_t *data)
+{
+ TPM_RC_t rc;
+ struct grub_tpm2_buffer in;
+ struct grub_tpm2_buffer out;
+ TPMI_ST_COMMAND_TAG_t tag = authCommand ? TPM_ST_SESSIONS : TPM_ST_NO_SESSIONS;
+ TPM_RC_t responseCode;
+ grub_uint32_t param_size;
+
+ /* Marshal */
+ grub_tpm2_buffer_init (&in);
+ grub_tpm2_buffer_pack_u32 (&in, authHandle);
+ grub_tpm2_buffer_pack_u32 (&in, nvIndex);
+ if (authCommand != NULL)
+ grub_Tss2_MU_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
+ grub_tpm2_buffer_pack_u16 (&in, size);
+ grub_tpm2_buffer_pack_u16 (&in, offset);
+ if (in.error != 0)
+ return TPM_RC_FAILURE;
+
+ /* Submit */
+ grub_tpm2_buffer_init (&out);
+ rc = tpm2_submit_command (tag, TPM_CC_NV_Read, &responseCode, &in, &out);
+ if (rc != TPM_RC_SUCCESS)
+ return rc;
+ if (responseCode != TPM_RC_SUCCESS)
+ return responseCode;
+
+ /* Unmarshal */
+ if (tag == TPM_ST_SESSIONS)
+ grub_tpm2_buffer_unpack_u32 (&out, &param_size);
+ grub_Tss2_MU_TPM2B_NAX_NV_BUFFER_Unmarshal (&out, data);
+ if (out.error != 0)
+ return TPM_RC_FAILURE;
+
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC_t
+grub_tpm2_nv_write (const TPMI_RH_NV_AUTH_t authHandle,
+ const TPMI_RH_NV_INDEX_t nvIndex,
+ const TPMS_AUTH_COMMAND_t *authCommand,
+ const TPM2B_MAX_NV_BUFFER_t *data,
+ const grub_uint16_t offset)
+{
+ TPM_RC_t rc;
+ struct grub_tpm2_buffer in;
+ struct grub_tpm2_buffer out;
+ TPMI_ST_COMMAND_TAG_t tag = authCommand ? TPM_ST_SESSIONS : TPM_ST_NO_SESSIONS;
+ TPM_RC_t responseCode;
+
+ /* Marshal */
+ grub_tpm2_buffer_init (&in);
+ grub_tpm2_buffer_pack_u32 (&in, authHandle);
+ grub_tpm2_buffer_pack_u32 (&in, nvIndex);
+ if (authCommand != NULL)
+ grub_Tss2_MU_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
+ grub_Tss2_MU_TPM2B_Marshal (&in, data->size, data->buffer);
+ grub_tpm2_buffer_pack_u16 (&in, offset);
+ if (in.error != 0)
+ return TPM_RC_FAILURE;
+
+ /* Submit */
+ grub_tpm2_buffer_init (&out);
+ rc = tpm2_submit_command (tag, TPM_CC_NV_Write, &responseCode, &in, &out);
+ if (rc != TPM_RC_SUCCESS)
+ return rc;
+ if (responseCode != TPM_RC_SUCCESS)
+ return responseCode;
+
+ /* Unmarshal */
+ if (out.error != 0)
+ return TPM_RC_FAILURE;
+
+ return TPM_RC_SUCCESS;
+}
diff --git a/grub-core/lib/tss2/tpm2_cmd.h b/grub-core/lib/tss2/tpm2_cmd.h
index d313cba00..90b42efec 100644
--- a/grub-core/lib/tss2/tpm2_cmd.h
+++ b/grub-core/lib/tss2/tpm2_cmd.h
@@ -154,4 +154,36 @@ extern TPM_RC_t
grub_tpm2_testparms (const TPMT_PUBLIC_PARMS_t *parms,
const TPMS_AUTH_COMMAND_t *authCommand);
+extern TPM_RC_t
+grub_tpm2_nv_definespace (const TPMI_RH_PROVISION_t authHandle,
+ const TPMS_AUTH_COMMAND_t *authCommand,
+ const TPM2B_AUTH_t *auth,
+ const TPM2B_NV_PUBLIC_t *publicInfo);
+
+extern TPM_RC_t
+grub_tpm2_nv_undefinespace (const TPMI_RH_PROVISION_t authHandle,
+ const TPMI_RH_NV_INDEX_t nvIndex,
+ const TPMS_AUTH_COMMAND_t *authCommand);
+
+extern TPM_RC_t
+grub_tpm2_nv_readpublic (const TPMI_RH_NV_INDEX_t nvIndex,
+ const TPMS_AUTH_COMMAND_t *authCommand,
+ TPM2B_NV_PUBLIC_t *nvPublic,
+ TPM2B_NAME_t *nvName);
+
+extern TPM_RC_t
+grub_tpm2_nv_read (const TPMI_RH_NV_AUTH_t authHandle,
+ const TPMI_RH_NV_INDEX_t nvIndex,
+ const TPMS_AUTH_COMMAND_t *authCommand,
+ const grub_uint16_t size,
+ const grub_uint16_t offset,
+ TPM2B_MAX_NV_BUFFER_t *data);
+
+extern TPM_RC_t
+grub_tpm2_nv_write (const TPMI_RH_NV_AUTH_t authHandle,
+ const TPMI_RH_NV_INDEX_t nvIndex,
+ const TPMS_AUTH_COMMAND_t *authCommand,
+ const TPM2B_MAX_NV_BUFFER_t *data,
+ const grub_uint16_t offset);
+
#endif /* ! GRUB_TPM2_COMMANDS_HEADER */
diff --git a/grub-core/lib/tss2/tss2_mu.c b/grub-core/lib/tss2/tss2_mu.c
index 86134cc0a..816e5b37f 100644
--- a/grub-core/lib/tss2/tss2_mu.c
+++ b/grub-core/lib/tss2/tss2_mu.c
@@ -17,6 +17,7 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <grub/mm.h>
#include <grub/misc.h>
#include <tss2_mu.h>
@@ -572,6 +573,37 @@ grub_Tss2_MU_TPMT_TK_VERIFIED_Marshal (grub_tpm2_buffer_t buffer,
grub_Tss2_MU_TPM2B_Marshal (buffer, p->digest.size, p->digest.buffer);
}
+void
+grub_Tss2_MU_TPMS_NV_PUBLIC_Marshal (grub_tpm2_buffer_t buffer,
+ const TPMS_NV_PUBLIC_t *p)
+{
+ grub_tpm2_buffer_pack_u32 (buffer, p->nvIndex);
+ grub_tpm2_buffer_pack_u16 (buffer, p->nameAlg);
+ grub_tpm2_buffer_pack_u32 (buffer, p->attributes);
+ grub_Tss2_MU_TPM2B_Marshal (buffer, p->authPolicy.size, p->authPolicy.buffer);
+ grub_tpm2_buffer_pack_u16 (buffer, p->dataSize);
+}
+
+void
+grub_Tss2_MU_TPM2B_NV_PUBLIC_Marshal (grub_tpm2_buffer_t buffer,
+ const TPM2B_NV_PUBLIC_t *p)
+{
+ grub_uint32_t start;
+ grub_uint16_t size;
+
+ if (p != NULL)
+ {
+ grub_tpm2_buffer_pack_u16 (buffer, p->size);
+
+ start = buffer->size;
+ grub_Tss2_MU_TPMS_NV_PUBLIC_Marshal (buffer, &p->nvPublic);
+ size = grub_cpu_to_be16 (buffer->size - start);
+ grub_memcpy (&buffer->data[start - sizeof (grub_uint16_t)], &size, sizeof (size));
+ }
+ else
+ grub_tpm2_buffer_pack_u16 (buffer, 0);
+}
+
static void
__Tss2_MU_TPM2B_BUFFER_Unmarshal (grub_tpm2_buffer_t buffer,
TPM2B_t *p, grub_uint16_t bound)
@@ -982,6 +1014,13 @@ grub_Tss2_MU_TPM2B_NV_PUBLIC_Unmarshal (grub_tpm2_buffer_t buffer,
grub_Tss2_MU_TPMS_NV_PUBLIC_Unmarshal (buffer, &p->nvPublic);
}
+void
+grub_Tss2_MU_TPM2B_NAX_NV_BUFFER_Unmarshal (grub_tpm2_buffer_t buffer,
+ TPM2B_MAX_NV_BUFFER_t *p)
+{
+ TPM2B_BUFFER_UNMARSHAL (buffer, TPM2B_MAX_NV_BUFFER_t, p);
+}
+
void
grub_Tss2_MU_TPM2B_NAME_Unmarshal (grub_tpm2_buffer_t buffer,
TPM2B_NAME_t *n)
diff --git a/grub-core/lib/tss2/tss2_mu.h b/grub-core/lib/tss2/tss2_mu.h
index 8f82126e1..6440de57c 100644
--- a/grub-core/lib/tss2/tss2_mu.h
+++ b/grub-core/lib/tss2/tss2_mu.h
@@ -193,6 +193,14 @@ extern void
grub_Tss2_MU_TPMT_TK_VERIFIED_Marshal (grub_tpm2_buffer_t buffer,
const TPMT_TK_VERIFIED_t *p);
+extern void
+grub_Tss2_MU_TPMS_NV_PUBLIC_Marshal (grub_tpm2_buffer_t buffer,
+ const TPMS_NV_PUBLIC_t *p);
+
+extern void
+grub_Tss2_MU_TPM2B_NV_PUBLIC_Marshal (grub_tpm2_buffer_t buffer,
+ const TPM2B_NV_PUBLIC_t *p);
+
extern void
grub_Tss2_MU_TPMS_AUTH_RESPONSE_Unmarshal (grub_tpm2_buffer_t buffer,
TPMS_AUTH_RESPONSE_t *p);
@@ -336,6 +344,10 @@ extern void
grub_Tss2_MU_TPM2B_NV_PUBLIC_Unmarshal (grub_tpm2_buffer_t buffer,
TPM2B_NV_PUBLIC_t *p);
+extern void
+grub_Tss2_MU_TPM2B_NAX_NV_BUFFER_Unmarshal (grub_tpm2_buffer_t buffer,
+ TPM2B_MAX_NV_BUFFER_t *p);
+
extern void
grub_Tss2_MU_TPM2B_NAME_Unmarshal (grub_tpm2_buffer_t buffer,
TPM2B_NAME_t *n);
diff --git a/grub-core/lib/tss2/tss2_types.h b/grub-core/lib/tss2/tss2_types.h
index 5b1a7947d..bddde7191 100644
--- a/grub-core/lib/tss2/tss2_types.h
+++ b/grub-core/lib/tss2/tss2_types.h
@@ -270,6 +270,7 @@ typedef TPM_HANDLE_t TPMI_RH_NV_INDEX_t;
/* TPM_HT_t Constants */
typedef grub_uint8_t TPM_HT_t;
+#define TPM_HT_NV_INDEX ((TPM_HT_t) 0x01)
#define TPM_HT_PERMANENT ((TPM_HT_t) 0x40)
#define TPM_HT_PERSISTENT ((TPM_HT_t) 0x81)
@@ -300,6 +301,7 @@ typedef TPM_HANDLE_t TPM_HC_t;
#define TPM_HR_HANDLE_MASK ((TPM_HC_t) 0x00FFFFFF)
#define TPM_HR_RANGE_MASK ((TPM_HC_t) 0xFF000000)
#define TPM_HR_SHIFT ((TPM_HC_t) 24)
+#define TPM_HR_NV_INDEX ((TPM_HC_t) (TPM_HT_NV_INDEX << TPM_HR_SHIFT))
#define TPM_HR_PERSISTENT ((TPM_HC_t) (TPM_HT_PERSISTENT << TPM_HR_SHIFT))
#define TPM_HR_PERMANENT ((TPM_HC_t) (TPM_HT_PERMANENT << TPM_HR_SHIFT))
#define TPM_PERSISTENT_FIRST ((TPM_HC_t) (TPM_HR_PERSISTENT + 0))
@@ -308,6 +310,7 @@ typedef TPM_HANDLE_t TPM_HC_t;
#define TPM_PERMANENT_LAST ((TPM_HC_t) TPM_RH_LAST)
/* TPM Handle Type Checks */
+#define TPM_HT_IS_NVINDEX(HANDLE) (((HANDLE) >> TPM_HR_SHIFT) == TPM_HT_NV_INDEX)
#define TPM_HT_IS_PERMANENT(HANDLE) (((HANDLE) >> TPM_HR_SHIFT) == TPM_HT_PERMANENT)
#define TPM_HT_IS_PERSISTENT(HANDLE) (((HANDLE) >> TPM_HR_SHIFT) == TPM_HT_PERSISTENT)
@@ -334,8 +337,11 @@ typedef grub_uint32_t TPM_CC_t;
#define TPM_CC_ReadPublic ((TPM_CC_t) 0x00000173)
#define TPM_CC_StartAuthSession ((TPM_CC_t) 0x00000176)
#define TPM_CC_PolicyPCR ((TPM_CC_t) 0x0000017f)
+#define TPM_CC_NV_DefineSpace ((TPM_CC_t) 0x0000012a)
#define TPM_CC_NV_Read ((TPM_CC_t) 0x0000014e)
#define TPM_CC_NV_ReadPublic ((TPM_CC_t) 0x00000169)
+#define TPM_CC_NV_Write ((TPM_CC_t) 0x00000137)
+#define TPM_CC_NV_UndefineSpace ((TPM_CC_t) 0x00000122)
#define TPM_CC_GetCapability ((TPM_CC_t) 0x0000017a)
#define TPM_CC_PCR_Read ((TPM_CC_t) 0x0000017e)
#define TPM_CC_Load ((TPM_CC_t) 0x00000157)
--
2.43.0

View File

@@ -1,255 +0,0 @@
From bd776f35de3afbbe818c0531be9c9754797f2c08 Mon Sep 17 00:00:00 2001
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Date: Tue, 25 Feb 2025 01:18:35 +0530
Subject: [PATCH 5/9] appendedsig: While verifying the kernel, use trusted and
distrusted lists
To verify the kernel's signature: verify the kernel binary against lists of binary hashes
that are either distrusted or trusted. If it is not list in either trusted or distrusted hashes list
then the trusted keys from the trusted key list are used to verify the signature.
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
---
grub-core/commands/appendedsig/appendedsig.c | 199 +++++++++++++------
1 file changed, 139 insertions(+), 60 deletions(-)
diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c
index 3df950c00b..b6daccd3d7 100644
--- a/grub-core/commands/appendedsig/appendedsig.c
+++ b/grub-core/commands/appendedsig/appendedsig.c
@@ -473,6 +473,83 @@ extract_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize,
return GRUB_ERR_NONE;
}
+static grub_err_t
+get_binary_hash (const grub_size_t binary_hash_size, const grub_uint8_t *data,
+ const grub_size_t data_size, grub_uint8_t *hash, grub_size_t *hash_size)
+{
+ grub_uuid_t guid = { 0 };
+
+ /* support SHA256, SHA384 and SHA512 for binary hash */
+ if (binary_hash_size == 32)
+ grub_memcpy (&guid, &GRUB_PKS_CERT_SHA256_GUID, GRUB_UUID_SIZE);
+ else if (binary_hash_size == 48)
+ grub_memcpy (&guid, &GRUB_PKS_CERT_SHA384_GUID, GRUB_UUID_SIZE);
+ else if (binary_hash_size == 64)
+ grub_memcpy (&guid, &GRUB_PKS_CERT_SHA512_GUID, GRUB_UUID_SIZE);
+ else
+ {
+ grub_dprintf ("appendedsig", "unsupported hash type (%" PRIuGRUB_SIZE ") and skipping binary hash\n",
+ binary_hash_size);
+ return GRUB_ERR_UNKNOWN_COMMAND;
+ }
+
+ return get_hash (&guid, data, data_size, hash, hash_size);
+}
+
+/*
+ * Verify binary hash against the list of binary hashes that are distrusted
+ * and trusted.
+ * The following errors can occur:
+ * - GRUB_ERR_BAD_SIGNATURE: indicates that the hash is distrusted.
+ * - GRUB_ERR_NONE: the hash is trusted, since it was found in the trusted hashes list
+ * - GRUB_ERR_EOF: the hash could not be found in the hashes list
+ */
+static grub_err_t
+verify_binary_hash (const grub_uint8_t *data, const grub_size_t data_size)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_size_t i = 0, hash_size = 0;
+ grub_uint8_t hash[GRUB_MAX_HASH_SIZE] = { 0 };
+
+ for (i = 0; i < dbx.signature_entries; i++)
+ {
+ rc = get_binary_hash (dbx.signature_size[i], data, data_size, hash, &hash_size);
+ if (rc != GRUB_ERR_NONE)
+ continue;
+
+ if (hash_size == dbx.signature_size[i] &&
+ grub_memcmp (dbx.signatures[i], hash, hash_size) == 0)
+ {
+ grub_dprintf ("appendedsig", "the binary hash (%02x%02x%02x%02x) was listed as distrusted\n",
+ hash[0], hash[1], hash[2], hash[3]);
+ return GRUB_ERR_BAD_SIGNATURE;
+ }
+ }
+
+ for (i = 0; i < db.signature_entries; i++)
+ {
+ rc = get_binary_hash (db.signature_size[i], data, data_size, hash, &hash_size);
+ if (rc != GRUB_ERR_NONE)
+ continue;
+
+ if (hash_size == db.signature_size[i] &&
+ grub_memcmp (db.signatures[i], hash, hash_size) == 0)
+ {
+ grub_dprintf ("appendedsig", "verified with a trusted binary hash (%02x%02x%02x%02x)\n",
+ hash[0], hash[1], hash[2], hash[3]);
+ return GRUB_ERR_NONE;
+ }
+ }
+
+ return GRUB_ERR_EOF;
+}
+
+
+/*
+ * Verify the kernel's integrity, the trusted key will be used from
+ * the trusted key list. If it fails, verify it against the list of binary hashes
+ * that are distrusted and trusted.
+ */
static grub_err_t
grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize)
{
@@ -482,12 +559,12 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize)
unsigned char *hash;
gcry_mpi_t hashmpi;
gcry_err_code_t rc;
- struct x509_certificate *pk;
+ struct x509_certificate *cert;
struct grub_appended_signature sig;
struct pkcs7_signerInfo *si;
int i;
- if (!db.key_entries)
+ if (!db.key_entries && !db.signature_entries)
return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("No trusted keys to verify against"));
err = extract_appended_signature (buf, bufsize, &sig);
@@ -495,71 +572,73 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize)
return err;
datasize = bufsize - sig.signature_len;
-
- for (i = 0; i < sig.pkcs7.signerInfo_count; i++)
+ err = verify_binary_hash (buf, datasize);
+ if (err != GRUB_ERR_EOF && err != GRUB_ERR_NONE)
+ {
+ err = grub_error (err, N_("failed to verify binary-hash/signature with any trusted binary-hash/key\n"));
+ return err;
+ }
+ else if (err == GRUB_ERR_EOF)
{
- /* This could be optimised in a couple of ways:
- - we could only compute hashes once per hash type
- - we could track signer information and only verify where IDs match
- For now we do the naive O(trusted keys * pkcs7 signers) approach.
- */
- si = &sig.pkcs7.signerInfos[i];
- context = grub_zalloc (si->hash->contextsize);
- if (!context)
- return grub_errno;
-
- si->hash->init (context);
- si->hash->write (context, buf, datasize);
- si->hash->final (context);
- hash = si->hash->read (context);
-
- grub_dprintf ("appendedsig",
- "data size %" PRIxGRUB_SIZE ", signer %d hash %02x%02x%02x%02x...\n",
- datasize, i, hash[0], hash[1], hash[2], hash[3]);
-
- err = GRUB_ERR_BAD_SIGNATURE;
- for (pk = db.keys; pk; pk = pk->next)
+ /* Binary hash was not found in trusted and distrusted list: check signature now */
+ for (i = 0; i < sig.pkcs7.signerInfo_count; i++)
{
- rc = grub_crypto_rsa_pad (&hashmpi, hash, si->hash, pk->mpis[0]);
- if (rc)
+ /*
+ * This could be optimised in a couple of ways:
+ * - we could only compute hashes once per hash type
+ * - we could track signer information and only verify where IDs match
+ * For now we do the naive O(db.keys * pkcs7 signers) approach.
+ */
+ si = &sig.pkcs7.signerInfos[i];
+ context = grub_zalloc (si->hash->contextsize);
+ if (context == NULL)
+ return grub_errno;
+
+ si->hash->init (context);
+ si->hash->write (context, buf, datasize);
+ si->hash->final (context);
+ hash = si->hash->read (context);
+
+ grub_dprintf ("appendedsig",
+ "data size %" PRIxGRUB_SIZE ", signer %d hash %02x%02x%02x%02x...\n",
+ datasize, i, hash[0], hash[1], hash[2], hash[3]);
+
+ err = GRUB_ERR_BAD_SIGNATURE;
+ for (cert = db.keys; cert; cert = cert->next)
{
- err = grub_error (GRUB_ERR_BAD_SIGNATURE,
- N_("Error padding hash for RSA verification: %d"), rc);
- grub_free (context);
- goto cleanup;
+ rc = grub_crypto_rsa_pad (&hashmpi, hash, si->hash, cert->mpis[0]);
+ if (rc != 0)
+ {
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE,
+ N_("Error padding hash for RSA verification: %d"), rc);
+ grub_free (context);
+ pkcs7_signedData_release (&sig.pkcs7);
+ return err;
+ }
+
+ rc = _gcry_pubkey_spec_rsa.verify (0, hashmpi, &si->sig_mpi, cert->mpis, NULL, NULL);
+ gcry_mpi_release (hashmpi);
+ if (rc == 0)
+ {
+ grub_dprintf ("appendedsig", "verify signer %d with key '%s' succeeded\n",
+ i, cert->subject);
+ err = GRUB_ERR_NONE;
+ break;
+ }
+
+ grub_dprintf ("appendedsig", "verify signer %d with key '%s' failed with %d\n",
+ i, cert->subject, rc);
}
-
- rc = _gcry_pubkey_spec_rsa.verify (0, hashmpi, &si->sig_mpi,
- pk->mpis, NULL, NULL);
- gcry_mpi_release (hashmpi);
-
- if (rc == 0)
- {
- grub_dprintf ("appendedsig",
- "verify signer %d with key '%s' succeeded\n", i,
- pk->subject);
- err = GRUB_ERR_NONE;
- break;
- }
-
- grub_dprintf ("appendedsig",
- "verify signer %d with key '%s' failed with %d\n", i,
- pk->subject, rc);
- }
-
- grub_free (context);
-
- if (err == GRUB_ERR_NONE)
- break;
+ grub_free (context);
+ if (err == GRUB_ERR_NONE)
+ break;
+ }
}
- /* If we didn't verify, provide a neat message */
if (err != GRUB_ERR_NONE)
- err = grub_error (GRUB_ERR_BAD_SIGNATURE,
- N_("Failed to verify signature against a trusted key"));
-
-cleanup:
- pkcs7_signedData_release (&sig.pkcs7);
+ err = grub_error (err, N_("failed to verify signature with any trusted key\n"));
+ else
+ grub_printf ("appendedsig: successfully verified the signature with a trusted key\n");
return err;
}
--
2.48.1

View File

@@ -1,71 +0,0 @@
From 45fffe05e9c33582258a88b4a722a5a561dbfa6e Mon Sep 17 00:00:00 2001
From: Maxim Suhanov <dfirblog@gmail.com>
Date: Thu, 8 May 2025 19:02:11 +0200
Subject: [PATCH 5/8] docs: Document available crypto disks checks
Document the --cryptodisk-only argument. Also, document the
"cryptocheck" command invoked when that argument is processed.
Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
docs/grub.texi | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/docs/grub.texi b/docs/grub.texi
index 9aaea72826..1c078c5c5b 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -4368,6 +4368,7 @@ you forget a command, you can run the command @command{help}
* configfile:: Load a configuration file
* cpuid:: Check for CPU features
* crc:: Compute or check CRC32 checksums
+* cryptocheck:: Check if a device is encrypted
* cryptomount:: Mount a crypto device
* cutmem:: Remove memory regions
* date:: Display or set current date and time
@@ -4680,6 +4681,16 @@ Alias for @code{hashsum --hash crc32 arg @dots{}}. See command @command{hashsum}
(@pxref{hashsum}) for full description.
@end deffn
+@node cryptocheck
+@subsection cryptocheck
+
+@deffn Command cryptocheck device
+Check if a given diskfilter device is backed by encrypted devices
+(@pxref{cryptomount} for additional information).
+
+The command examines all backing devices, physical volumes, of a specified
+logical volume, like LVM2, and fails when at least one of them is unencrypted.
+@end deffn
@node cryptomount
@subsection cryptomount
@@ -5531,7 +5542,8 @@ unbootable. @xref{Using GPG-style digital signatures}, for more information.
@deffn Command search @
[@option{--file}|@option{--label}|@option{--fs-uuid}] @
- [@option{--set} [var]] [@option{--no-floppy}|@option{--efidisk-only}] name
+ [@option{--set} [var]] [@option{--no-floppy}|@option{--efidisk-only}|@option{--cryptodisk-only}] @
+ name
Search devices by file (@option{-f}, @option{--file}), filesystem label
(@option{-l}, @option{--label}), or filesystem UUID (@option{-u},
@option{--fs-uuid}).
@@ -5546,6 +5558,14 @@ devices, which can be slow.
The (@option{--efidisk-only}) option prevents searching any other devices then
EFI disks. This is typically used when chainloading to local EFI partition.
+The (@option{--cryptodisk-only}) option prevents searching any devices other
+than encrypted disks. This is typically used when booting from an encrypted
+file system to ensure that no code gets executed from an unencrypted device
+having the same filesystem UUID or label.
+
+This option implicitly invokes the command @command{cryptocheck}, if it is
+available (@pxref{cryptocheck} for additional information).
+
The @samp{search.file}, @samp{search.fs_label}, and @samp{search.fs_uuid}
commands are aliases for @samp{search --file}, @samp{search --label}, and
@samp{search --fs-uuid} respectively.
--
2.49.0

View File

@@ -1,38 +0,0 @@
From 3f1980191c693670380aa9aa5a949c5574a3bd04 Mon Sep 17 00:00:00 2001
From: B Horn <b@horn.uk>
Date: Sun, 12 May 2024 06:22:51 +0100
Subject: [PATCH 05/20] fs/hfsplus: Set a grub_errno if mount fails
It was possible for mount to fail but not set grub_errno. This led to
a possible double decrement of the module reference count if the NULL
page was mapped.
Fixing in general as a similar bug was fixed in commit 61b13c187
(fs/hfsplus: Set grub_errno to prevent NULL pointer access) and there
are likely more variants around.
Fixes: CVE-2024-45783
Reported-by: B Horn <b@horn.uk>
Signed-off-by: B Horn <b@horn.uk>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/hfsplus.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c
index 295822f694..de71fd486b 100644
--- a/grub-core/fs/hfsplus.c
+++ b/grub-core/fs/hfsplus.c
@@ -405,7 +405,7 @@ grub_hfsplus_mount (grub_disk_t disk)
fail:
- if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
+ if (grub_errno == GRUB_ERR_OUT_OF_RANGE || grub_errno == GRUB_ERR_NONE)
grub_error (GRUB_ERR_BAD_FS, "not a HFS+ filesystem");
grub_free (data);
--
2.48.1

View File

@@ -1,109 +0,0 @@
From 72092a8641958af95402fa0e3e74cc57c36feefa Mon Sep 17 00:00:00 2001
From: Stefan Berger <stefanb@linux.ibm.com>
Date: Tue, 26 Nov 2024 15:39:44 -0500
Subject: [PATCH 5/7] ieee1275/tcg2: Refactor grub_ieee1275_tpm_init()
Move tpm_get_tpm_version() into grub_ieee1275_tpm_init() and invalidate
grub_ieee1275_tpm_ihandle in case no TPM 2 could be detected. Try the
initialization only once so that grub_tpm_present() will always return
the same result. Use the grub_ieee1275_tpm_ihandle as indicator for an
available TPM instead of grub_ieee1275_tpm_version, which can now be
removed.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/commands/ieee1275/ibmvtpm.c | 2 +-
grub-core/lib/ieee1275/tcg2.c | 40 ++++++++++++---------------
include/grub/ieee1275/tpm.h | 1 -
3 files changed, 18 insertions(+), 25 deletions(-)
diff --git a/grub-core/commands/ieee1275/ibmvtpm.c b/grub-core/commands/ieee1275/ibmvtpm.c
index 284673217..4958b04a9 100644
--- a/grub-core/commands/ieee1275/ibmvtpm.c
+++ b/grub-core/commands/ieee1275/ibmvtpm.c
@@ -100,7 +100,7 @@ grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr,
grub_dprintf ("tpm", "log_event, pcr = %d, size = 0x%" PRIxGRUB_SIZE ", %s\n",
pcr, size, description);
- if (grub_ieee1275_tpm_version == 2)
+ if (grub_ieee1275_tpm_ihandle != GRUB_IEEE1275_IHANDLE_INVALID)
return tpm2_log_event (buf, size, pcr, description);
return GRUB_ERR_NONE;
diff --git a/grub-core/lib/ieee1275/tcg2.c b/grub-core/lib/ieee1275/tcg2.c
index 1819d1447..ea01a30eb 100644
--- a/grub-core/lib/ieee1275/tcg2.c
+++ b/grub-core/lib/ieee1275/tcg2.c
@@ -23,39 +23,33 @@
#include <grub/mm.h>
#include <grub/misc.h>
-grub_ieee1275_ihandle_t grub_ieee1275_tpm_ihandle;
-grub_uint8_t grub_ieee1275_tpm_version;
-
-static void
-tpm_get_tpm_version (void)
-{
- grub_ieee1275_phandle_t vtpm;
- char buffer[20];
-
- if (!grub_ieee1275_finddevice ("/vdevice/vtpm", &vtpm) &&
- !grub_ieee1275_get_property (vtpm, "compatible", buffer,
- sizeof (buffer), NULL) &&
- !grub_strcmp (buffer, "IBM,vtpm20"))
- grub_ieee1275_tpm_version = 2;
-}
+grub_ieee1275_ihandle_t grub_ieee1275_tpm_ihandle = GRUB_IEEE1275_IHANDLE_INVALID;
grub_err_t
grub_ieee1275_tpm_init (void)
{
- static int init_success = 0;
+ static bool init_tried = false;
+ grub_ieee1275_phandle_t vtpm;
+ char buffer[20];
- if (!init_success)
+ if (init_tried == false)
{
- if (grub_ieee1275_open ("/vdevice/vtpm", &grub_ieee1275_tpm_ihandle) < 0)
+ init_tried = true;
+
+ if (grub_ieee1275_open ("/vdevice/vtpm", &grub_ieee1275_tpm_ihandle) < 0 ||
+ grub_ieee1275_finddevice ("/vdevice/vtpm", &vtpm) ||
+ grub_ieee1275_get_property (vtpm, "compatible", buffer, sizeof (buffer), NULL) ||
+ grub_strcmp (buffer, "IBM,vtpm20"))
{
+ if (grub_ieee1275_tpm_ihandle != GRUB_IEEE1275_IHANDLE_INVALID)
+ grub_ieee1275_close (grub_ieee1275_tpm_ihandle);
+
grub_ieee1275_tpm_ihandle = GRUB_IEEE1275_IHANDLE_INVALID;
- return GRUB_ERR_UNKNOWN_DEVICE;
}
-
- init_success = 1;
-
- tpm_get_tpm_version ();
}
+ if (grub_ieee1275_tpm_ihandle == GRUB_IEEE1275_IHANDLE_INVALID)
+ return GRUB_ERR_UNKNOWN_DEVICE;
+
return GRUB_ERR_NONE;
}
diff --git a/include/grub/ieee1275/tpm.h b/include/grub/ieee1275/tpm.h
index 9575c1c68..fe5cb4713 100644
--- a/include/grub/ieee1275/tpm.h
+++ b/include/grub/ieee1275/tpm.h
@@ -24,7 +24,6 @@
#include <grub/ieee1275/ieee1275.h>
extern grub_ieee1275_ihandle_t grub_ieee1275_tpm_ihandle;
-extern grub_uint8_t grub_ieee1275_tpm_version;
extern grub_err_t grub_ieee1275_tpm_init (void);
--
2.43.0

View File

@@ -1,200 +0,0 @@
From fa69deac565e5d5015ca396b017239cd96900673 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Mon, 7 Apr 2025 16:29:19 +0800
Subject: [PATCH 5/7] tpm2_key_protector: Unseal key from a buffer
Extract the logic to handle the file buffer from the SRK recover
function to prepare to load the sealed key from the NV index handle,
so the NV index mode can share the same code path in the later patch.
The SRK recover function now only reads the file and sends the file
buffer to the new function.
Besides this, to avoid introducing more options for the NV index mode,
the file format is detected automatically before unmarshaling the data,
so there is no need to use the command option to specify the file format
anymore. In other words, "-T" and "-k" are the same now.
Also update grub.text to address the change.
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
docs/grub.texi | 13 +-
.../commands/tpm2_key_protector/module.c | 122 +++++++++++++-----
2 files changed, 96 insertions(+), 39 deletions(-)
Index: grub-2.12/grub-core/commands/tpm2_key_protector/module.c
===================================================================
--- grub-2.12.orig/grub-core/commands/tpm2_key_protector/module.c
+++ grub-2.12/grub-core/commands/tpm2_key_protector/module.c
@@ -218,10 +218,51 @@ tpm2_protector_srk_read_file (const char
return err;
}
+/* Check if the data is in TPM 2.0 Key File format */
+static bool
+tpm2_protector_is_tpm2key (grub_uint8_t *buffer, grub_size_t buffer_size)
+{
+ /* id-sealedkey OID (2.23.133.10.1.5) in DER */
+ const grub_uint8_t sealed_key_oid[] = {0x06, 0x06, 0x67, 0x81, 0x05, 0x0a};
+ grub_size_t skip = 0;
+
+ /* Need at least the first two bytes to check the tag and the length */
+ if (buffer_size < 2)
+ return false;
+
+ /* The first byte is always 0x30 (SEQUENCE). */
+ if (buffer[0] != 0x30)
+ return false;
+
+ /*
+ * Get the bytes of the length
+ *
+ * If the bit 8 of the second byte is 0, it is in the short form, so the second byte
+ * alone represents the length. Thus, the first two bytes are skipped.
+ *
+ * Otherwise, it is in the long form, and bits 1~7 indicate how many more bytes are in
+ * the length field, so we skip the first two bytes plus the bytes for the length.
+ */
+ if ((buffer[1] & 0x80) == 0)
+ skip = 2;
+ else
+ skip = (buffer[1] & 0x7F) + 2;
+
+ /* Make sure the buffer is large enough to contain id-sealedkey OID */
+ if (buffer_size < skip + sizeof (sealed_key_oid))
+ return false;
+
+ /* Check id-sealedkey OID */
+ if (grub_memcmp (buffer + skip, sealed_key_oid, sizeof (sealed_key_oid)) != 0)
+ return false;
+
+ return true;
+}
+
static grub_err_t
-tpm2_protector_srk_unmarshal_keyfile (void *sealed_key,
- grub_size_t sealed_key_size,
- tpm2_sealed_key_t *sk)
+tpm2_protector_unmarshal_raw (void *sealed_key,
+ grub_size_t sealed_key_size,
+ tpm2_sealed_key_t *sk)
{
struct grub_tpm2_buffer buf;
@@ -242,13 +283,13 @@ tpm2_protector_srk_unmarshal_keyfile (vo
}
static grub_err_t
-tpm2_protector_srk_unmarshal_tpm2key (void *sealed_key,
- grub_size_t sealed_key_size,
- tpm2key_policy_t *policy_seq,
- tpm2key_authpolicy_t *authpol_seq,
- grub_uint8_t *rsaparent,
- grub_uint32_t *parent,
- tpm2_sealed_key_t *sk)
+tpm2_protector_unmarshal_tpm2key (void *sealed_key,
+ grub_size_t sealed_key_size,
+ tpm2key_policy_t *policy_seq,
+ tpm2key_authpolicy_t *authpol_seq,
+ grub_uint8_t *rsaparent,
+ grub_uint32_t *parent,
+ tpm2_sealed_key_t *sk)
{
asn1_node tpm2key = NULL;
grub_uint8_t rsaparent_tmp;
@@ -954,12 +995,11 @@ tpm2_protector_dump_pcr (const TPM_ALG_I
}
static grub_err_t
-tpm2_protector_srk_recover (const tpm2_protector_context_t *ctx,
- grub_uint8_t **key, grub_size_t *key_size)
+tpm2_protector_key_from_buffer (const tpm2_protector_context_t *ctx,
+ void *buffer, grub_size_t buf_size,
+ grub_uint8_t **key, grub_size_t *key_size)
{
tpm2_sealed_key_t sealed_key = {0};
- void *file_bytes = NULL;
- grub_size_t file_size = 0;
grub_uint8_t rsaparent = 0;
TPM_HANDLE_t parent_handle = 0;
TPM_HANDLE_t srk_handle = 0;
@@ -972,22 +1012,17 @@ tpm2_protector_srk_recover (const tpm2_p
/*
* Retrieve sealed key, parent handle, policy sequence, and authpolicy
- * sequence from the key file
+ * sequence from the buffer
*/
- if (ctx->tpm2key != NULL)
+ if (tpm2_protector_is_tpm2key (buffer, buf_size) == true)
{
- err = tpm2_protector_srk_read_file (ctx->tpm2key, &file_bytes,
- &file_size);
- if (err != GRUB_ERR_NONE)
- return err;
-
- err = tpm2_protector_srk_unmarshal_tpm2key (file_bytes,
- file_size,
- &policy_seq,
- &authpol_seq,
- &rsaparent,
- &parent_handle,
- &sealed_key);
+ err = tpm2_protector_unmarshal_tpm2key (buffer,
+ buf_size,
+ &policy_seq,
+ &authpol_seq,
+ &rsaparent,
+ &parent_handle,
+ &sealed_key);
if (err != GRUB_ERR_NONE)
goto exit1;
@@ -1003,12 +1038,8 @@ tpm2_protector_srk_recover (const tpm2_p
}
else
{
- err = tpm2_protector_srk_read_file (ctx->keyfile, &file_bytes, &file_size);
- if (err != GRUB_ERR_NONE)
- return err;
-
parent_handle = TPM_RH_OWNER;
- err = tpm2_protector_srk_unmarshal_keyfile (file_bytes, file_size, &sealed_key);
+ err = tpm2_protector_unmarshal_raw (buffer, buf_size, &sealed_key);
if (err != GRUB_ERR_NONE)
goto exit1;
}
@@ -1084,6 +1115,31 @@ tpm2_protector_srk_recover (const tpm2_p
exit1:
grub_tpm2key_free_policy_seq (policy_seq);
grub_tpm2key_free_authpolicy_seq (authpol_seq);
+ return err;
+}
+
+static grub_err_t
+tpm2_protector_srk_recover (const tpm2_protector_context_t *ctx,
+ grub_uint8_t **key, grub_size_t *key_size)
+{
+ const char *filepath;
+ void *file_bytes = NULL;
+ grub_size_t file_size = 0;
+ grub_err_t err;
+
+ if (ctx->tpm2key != NULL)
+ filepath = ctx->tpm2key;
+ else if (ctx->keyfile != NULL)
+ filepath = ctx->keyfile;
+ else
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("key file not specified"));
+
+ err = tpm2_protector_srk_read_file (filepath, &file_bytes, &file_size);
+ if (err != GRUB_ERR_NONE)
+ return err;
+
+ err = tpm2_protector_key_from_buffer (ctx, file_bytes, file_size, key, key_size);
+
grub_free (file_bytes);
return err;
}

View File

@@ -1,150 +0,0 @@
From 0a11bc48ea60f7611df2c5b640cecc325c7c4fd9 Mon Sep 17 00:00:00 2001
From: Maxim Suhanov <dfirblog@gmail.com>
Date: Thu, 8 May 2025 19:02:12 +0200
Subject: [PATCH 6/8] disk/cryptodisk: Add the "erase secrets" function
This commit adds the grub_cryptodisk_erasesecrets() function to wipe
master keys from all cryptodisks. This function is EFI-only.
Since there is no easy way to "force unmount" a given encrypted disk,
this function renders all mounted cryptodisks unusable. An attempt to
read them will return garbage.
This is why this function must be used in "no way back" conditions.
Currently, it is used when unloading the cryptodisk module and when
performing the "exit" command (it is often used to switch to the next
EFI application). This function is not called when performing the
"chainloader" command, because the callee may return to GRUB. For this
reason, users are encouraged to use "exit" instead of "chainloader" to
execute third-party boot applications.
This function does not guarantee that all secrets are wiped from RAM.
Console output, chunks from disk read requests and other may remain.
This function does not clear the IV prefix and rekey key for geli disks.
Also, this commit adds the relevant documentation improvements.
Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
docs/grub.texi | 6 ++++++
grub-core/commands/minicmd.c | 11 +++++++++++
grub-core/disk/cryptodisk.c | 28 ++++++++++++++++++++++++++++
include/grub/cryptodisk.h | 1 +
4 files changed, 46 insertions(+)
diff --git a/docs/grub.texi b/docs/grub.texi
index 1c078c5c5b..c4936db8c1 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -4727,6 +4727,11 @@ namespace in addition to the cryptodisk namespace.
Support for plain encryption mode (plain dm-crypt) is provided via separate
@command{@pxref{plainmount}} command.
+
+On the EFI platform, GRUB tries to erase master keys from memory when the cryptodisk
+module is unloaded or the command @command{exit} is executed. All secrets remain in
+memory when the command @command{chainloader} is issued, because execution can
+return to GRUB on the EFI platform.
@end deffn
@node cutmem
@@ -6981,6 +6986,7 @@ USB support provides benefits similar to ATA (for USB disks) or AT (for USB
keyboards). In addition it allows USBserial.
Chainloading refers to the ability to load another bootloader through the same protocol
+and on some platforms, like EFI, allow that bootloader to return to the GRUB.
Hints allow faster disk discovery by already knowing in advance which is the disk in
question. On some platforms hints are correct unless you move the disk between boots.
diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c
index 903af33131..bd9cb681ec 100644
--- a/grub-core/commands/minicmd.c
+++ b/grub-core/commands/minicmd.c
@@ -29,6 +29,10 @@
#include <grub/command.h>
#include <grub/i18n.h>
+#ifdef GRUB_MACHINE_EFI
+#include <grub/cryptodisk.h>
+#endif
+
GRUB_MOD_LICENSE ("GPLv3+");
/* cat FILE */
@@ -187,6 +191,13 @@ grub_mini_cmd_exit (struct grub_command *cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char *argv[] __attribute__ ((unused)))
{
+#ifdef GRUB_MACHINE_EFI
+ /*
+ * The "exit" command is often used to launch the next boot application.
+ * So, erase the secrets.
+ */
+ grub_cryptodisk_erasesecrets ();
+#endif
grub_exit ();
/* Not reached. */
}
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 33eb6568ca..f9ae750f85 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -1784,6 +1784,31 @@ grub_cryptodisk_challenge_password (void)
return GRUB_ERR_NONE;
}
+
+void
+grub_cryptodisk_erasesecrets (void)
+{
+ grub_cryptodisk_t i;
+ grub_uint8_t *buf;
+
+ buf = grub_zalloc (GRUB_CRYPTODISK_MAX_KEYLEN);
+ if (buf == NULL)
+ grub_fatal ("grub_cryptodisk_erasesecrets: cannot allocate memory");
+
+ for (i = cryptodisk_list; i != NULL; i = i->next)
+ if (grub_cryptodisk_setkey (i, buf, i->keysize))
+ grub_fatal ("grub_cryptodisk_erasesecrets: cannot erase secrets for %s", i->source);
+ else
+ grub_printf ("Erased crypto secrets for %s\n", i->source);
+ /*
+ * Unfortunately, there is no way to "force unmount" a given disk, it may
+ * have mounted "child" disks as well, e.g., an LVM volume. So, this
+ * function MUST be called when there is no way back, e.g., when exiting.
+ * Otherwise, subsequent read calls for a cryptodisk will return garbage.
+ */
+
+ grub_free (buf);
+}
#endif /* GRUB_MACHINE_EFI */
struct grub_procfs_entry luks_script =
@@ -1808,6 +1833,9 @@ GRUB_MOD_INIT (cryptodisk)
GRUB_MOD_FINI (cryptodisk)
{
+#ifdef GRUB_MACHINE_EFI
+ grub_cryptodisk_erasesecrets ();
+#endif
grub_disk_dev_unregister (&grub_cryptodisk_dev);
cryptodisk_cleanup ();
grub_unregister_extcmd (cmd);
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index b3291519b1..08abfb7b6c 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -205,5 +205,6 @@ grub_cryptodisk_t grub_cryptodisk_get_by_source_disk (grub_disk_t disk);
#ifdef GRUB_MACHINE_EFI
grub_err_t grub_cryptodisk_challenge_password (void);
+void grub_cryptodisk_erasesecrets (void);
#endif
#endif
--
2.49.0

View File

@@ -1,161 +0,0 @@
From ff14b89bda0445b97ad43b7cdbc5f20345f20006 Mon Sep 17 00:00:00 2001
From: Stefan Berger <stefanb@linux.ibm.com>
Date: Tue, 26 Nov 2024 15:39:45 -0500
Subject: [PATCH 6/7] ieee1275/tcg2: Add TCG2 driver for ieee1275 PowerPC
firmware
Follow recent extensions of EFI support providing a TCG2 driver with
a public API for getting the maximum TPM command size and passing a TPM
command through to the TPM 2. Implement this functionality using ieee1275
PowerPC firmware API calls. Move tcg2.c into the TCG2 driver.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/Makefile.core.def | 3 +-
grub-core/lib/ieee1275/tcg2.c | 102 ++++++++++++++++++++++++++++++++++
2 files changed, 104 insertions(+), 1 deletion(-)
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index c5fd796d4..8ecedf986 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1155,7 +1155,6 @@ module = {
name = tpm;
common = commands/tpm.c;
ieee1275 = commands/ieee1275/ibmvtpm.c;
- ieee1275 = lib/ieee1275/tcg2.c;
enable = powerpc_ieee1275;
};
@@ -2576,8 +2575,10 @@ module = {
common = lib/tss2/tss2.c;
efi = lib/efi/tcg2.c;
emu = lib/tss2/tcg2_emu.c;
+ powerpc_ieee1275 = lib/ieee1275/tcg2.c;
enable = efi;
enable = emu;
+ enable = powerpc_ieee1275;
cppflags = '-I$(srcdir)/lib/tss2';
};
diff --git a/grub-core/lib/ieee1275/tcg2.c b/grub-core/lib/ieee1275/tcg2.c
index ea01a30eb..40161c2f9 100644
--- a/grub-core/lib/ieee1275/tcg2.c
+++ b/grub-core/lib/ieee1275/tcg2.c
@@ -23,6 +23,8 @@
#include <grub/mm.h>
#include <grub/misc.h>
+#include <tcg2.h>
+
grub_ieee1275_ihandle_t grub_ieee1275_tpm_ihandle = GRUB_IEEE1275_IHANDLE_INVALID;
grub_err_t
@@ -53,3 +55,103 @@ grub_ieee1275_tpm_init (void)
return GRUB_ERR_NONE;
}
+
+grub_err_t
+grub_tcg2_get_max_output_size (grub_size_t *size)
+{
+ struct tpm_get_maximum_cmd_size
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t method;
+ grub_ieee1275_cell_t ihandle;
+ grub_ieee1275_cell_t catch_result;
+ grub_ieee1275_cell_t size;
+ };
+ struct tpm_get_maximum_cmd_size args;
+ static bool error_displayed = false;
+ grub_err_t err;
+
+ err = grub_ieee1275_tpm_init ();
+ if (err != GRUB_ERR_NONE)
+ return err;
+
+ INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 2);
+ args.method = (grub_ieee1275_cell_t) "get-maximum-cmd-size";
+ args.ihandle = grub_ieee1275_tpm_ihandle;
+
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+ return GRUB_ERR_INVALID_COMMAND;
+
+ /*
+ * args.catch_result is set if firmware does not support get-maximum-cmd-size.
+ * rc is GRUB_IEEE1275_CELL_FALSE (0) on failure.
+ */
+ if (args.catch_result)
+ {
+ if (error_displayed == false)
+ {
+ error_displayed = true;
+ return grub_error (GRUB_ERR_BAD_DEVICE,
+ "get-maximum-cmd-size failed: Firmware is likely too old");
+ }
+ return GRUB_ERR_INVALID_COMMAND;
+ }
+
+ *size = args.size;
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_tcg2_submit_command (grub_size_t input_size,
+ grub_uint8_t *input,
+ grub_size_t output_size,
+ grub_uint8_t *output)
+{
+ struct tpm_pass_through_to_tpm
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t method;
+ grub_ieee1275_cell_t ihandle;
+ grub_ieee1275_cell_t buf_size;
+ grub_ieee1275_cell_t buf_addr;
+ grub_ieee1275_cell_t catch_result;
+ grub_ieee1275_cell_t resp_size;
+ };
+ struct tpm_pass_through_to_tpm args;
+ static bool error_displayed = false;
+ grub_err_t err;
+
+ if (input_size == 0 || input == NULL ||
+ output_size == 0 || output == NULL)
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ err = grub_ieee1275_tpm_init ();
+ if (err != GRUB_ERR_NONE)
+ return err;
+
+ INIT_IEEE1275_COMMON (&args.common, "call-method", 4, 2);
+ args.method = (grub_ieee1275_cell_t) "pass-through-to-tpm";
+ args.ihandle = grub_ieee1275_tpm_ihandle;
+ args.buf_size = (grub_ieee1275_cell_t) input_size;
+ args.buf_addr = (grub_ieee1275_cell_t) input;
+
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+ return GRUB_ERR_INVALID_COMMAND;
+
+ /* args.catch_result is set if firmware does not support pass-through-to-tpm. */
+ if (args.catch_result)
+ {
+ if (error_displayed == false)
+ {
+ error_displayed = true;
+ return grub_error (GRUB_ERR_BAD_DEVICE,
+ "pass-through-to-tpm failed: Firmware is likely too old");
+ }
+ return GRUB_ERR_INVALID_COMMAND;
+ }
+
+ grub_memcpy (output, input, args.resp_size);
+
+ return GRUB_ERR_NONE;
+}
--
2.43.0

View File

@@ -1,35 +0,0 @@
From 07482c2ab034df5069761319e4969551c3dcc6e1 Mon Sep 17 00:00:00 2001
From: B Horn <b@horn.uk>
Date: Sun, 12 May 2024 03:01:40 +0100
Subject: [PATCH 06/20] kern/file: Ensure file->data is set
This is to avoid a generic issue were some filesystems would not set
data and also not set a grub_errno. This meant it was possible for many
filesystems to grub_dl_unref() themselves multiple times resulting in
it being possible to unload the filesystems while there were still
references to them, e.g., via a loopback.
Reported-by: B Horn <b@horn.uk>
Signed-off-by: B Horn <b@horn.uk>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/kern/file.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c
index 750177248f..e990507fca 100644
--- a/grub-core/kern/file.c
+++ b/grub-core/kern/file.c
@@ -114,6 +114,9 @@ grub_file_open (const char *name, enum grub_file_type type)
if ((file->fs->fs_open) (file, file_name) != GRUB_ERR_NONE)
goto fail;
+ if (file->data == NULL)
+ goto fail;
+
file->name = grub_strdup (name);
grub_errno = GRUB_ERR_NONE;
--
2.48.1

View File

@@ -1,109 +0,0 @@
From eeb78a4bd82a1c83e3bbe5a4faf9b2c2e8023445 Mon Sep 17 00:00:00 2001
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Date: Tue, 25 Feb 2025 01:45:35 +0530
Subject: [PATCH 6/9] powerpc_ieee1275: set use_static_keys flag
Introduce the use_static_keys flag to indicate that static keys are to be used
rather than keys from the PKS storage's DB variable. This variable is set when
Secure Boot is enabled with PKS but the DB variable is not present in the PKS storage.
The appendedsig module would use this variable to extract the default DB keys from
the ELF note and store the keys found there in the trustedlist.
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
---
.../kern/powerpc/ieee1275/platform_keystore.c | 15 ++++++++++++++-
grub-core/term/tparm.c | 1 -
include/grub/powerpc/ieee1275/platform_keystore.h | 11 ++++++-----
include/grub/types.h | 2 ++
4 files changed, 22 insertions(+), 7 deletions(-)
diff --git a/grub-core/kern/powerpc/ieee1275/platform_keystore.c b/grub-core/kern/powerpc/ieee1275/platform_keystore.c
index ea9f27eb22..81e40632b2 100644
--- a/grub-core/kern/powerpc/ieee1275/platform_keystore.c
+++ b/grub-core/kern/powerpc/ieee1275/platform_keystore.c
@@ -34,7 +34,11 @@
/* Platform Keystore */
static grub_size_t pks_max_object_size;
grub_uint8_t grub_pks_use_keystore = 0;
-grub_pks_t grub_pks_keystore = { .db = NULL, .dbx = NULL, .db_entries = 0, .dbx_entries = 0 };
+grub_pks_t grub_pks_keystore = { .db = NULL,
+ .dbx = NULL,
+ .db_entries = 0,
+ .dbx_entries = 0,
+ .use_static_keys = false };
/* Convert the esl data into the ESL */
static grub_esl_t *
@@ -315,6 +319,15 @@ grub_pks_keystore_init (void)
grub_memset (&grub_pks_keystore, 0, sizeof (grub_pks_t));
/* DB */
rc = read_secure_boot_variables (0, DB, &grub_pks_keystore.db, &grub_pks_keystore.db_entries);
+ if (rc == PKS_OBJECT_NOT_FOUND)
+ {
+ rc = GRUB_ERR_NONE;
+ /*
+ * DB variable won't be available by default in PKS.
+ * So, it will load the Default Keys from ELF Note */
+ grub_pks_keystore.use_static_keys = true;
+ }
+
if (rc == GRUB_ERR_NONE)
{
/* DBX */
diff --git a/grub-core/term/tparm.c b/grub-core/term/tparm.c
index fb5b15a88d..f2db325f6e 100644
--- a/grub-core/term/tparm.c
+++ b/grub-core/term/tparm.c
@@ -46,7 +46,6 @@
/*
* Common/troublesome character definitions
*/
-typedef char grub_bool_t;
#ifndef FALSE
# define FALSE (0)
#endif
diff --git a/include/grub/powerpc/ieee1275/platform_keystore.h b/include/grub/powerpc/ieee1275/platform_keystore.h
index 0641adb0f1..870fb8cc51 100644
--- a/include/grub/powerpc/ieee1275/platform_keystore.h
+++ b/include/grub/powerpc/ieee1275/platform_keystore.h
@@ -199,10 +199,11 @@ struct grub_pks_sd
/* The structure of a PKS.*/
struct grub_pks
{
- grub_pks_sd_t *db; /* signature database */
- grub_pks_sd_t *dbx; /* forbidden signature database */
- grub_size_t db_entries; /* size of signature database */
- grub_size_t dbx_entries; /* size of forbidden signature database */
+ grub_pks_sd_t *db; /* signature database */
+ grub_pks_sd_t *dbx; /* forbidden signature database */
+ grub_size_t db_entries; /* size of signature database */
+ grub_size_t dbx_entries; /* size of forbidden signature database */
+ grub_bool_t use_static_keys;/* flag to indicate use of static keys */
} GRUB_PACKED;
#ifdef __powerpc__
@@ -217,7 +218,7 @@ extern grub_pks_t EXPORT_VAR(grub_pks_keystore);
#else
#define grub_pks_use_keystore 0
-grub_pks_t grub_pks_keystore = {NULL, NULL, 0, 0};
+grub_pks_t grub_pks_keystore = {NULL, NULL, 0, 0, false};
void grub_pks_free_keystore (void);
#endif
diff --git a/include/grub/types.h b/include/grub/types.h
index 5542b9aa09..573a614fa6 100644
--- a/include/grub/types.h
+++ b/include/grub/types.h
@@ -397,4 +397,6 @@ struct grub_uuid
grub_uint8_t b[GRUB_UUID_SIZE];
};
+typedef char grub_bool_t;
+
#endif /* ! GRUB_TYPES_HEADER */
--
2.48.1

View File

@@ -1,147 +0,0 @@
From cd9cb944d973da6a031d06183cc6da974beb4bae Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Mon, 7 Apr 2025 16:29:20 +0800
Subject: [PATCH 6/7] tpm2_key_protector: Support NV index handles
Previously, NV index mode only supported persistent handles which are
only for TPM objects.
On the other hand, the "NV index" handle allows the user-defined data,
so it can be an alternative to the key file and support TPM 2.0 Key
File format immediately.
The following tpm2-tools commands store the given key file, sealed.tpm,
in either TPM 2.0 Key File format or the raw format into the NV index
handle 0x1000000.
# tpm2_nvdefine -C o \
-a "ownerread|ownerwrite" \
-s $(stat -c %s sealed.tpm) \
0x1000000
# tpm2_nvwrite -C o -i sealed.tpm 0x1000000
To unseal the key in GRUB, add the "tpm2_key_protector_init" command to
grub.cfg:
tpm2_key_protector_init --mode=nv --nvindex=0x1000000
cryptomount -u <UUID> --protector tpm2
To remove the NV index handle:
# tpm2_nvundefine -C o 0x1000000
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
.../commands/tpm2_key_protector/module.c | 70 ++++++++++++++++---
1 file changed, 60 insertions(+), 10 deletions(-)
diff --git a/grub-core/commands/tpm2_key_protector/module.c b/grub-core/commands/tpm2_key_protector/module.c
index 795f61518..857f3753f 100644
--- a/grub-core/commands/tpm2_key_protector/module.c
+++ b/grub-core/commands/tpm2_key_protector/module.c
@@ -1133,10 +1133,9 @@ tpm2_protector_srk_recover (const tpm2_protector_context_t *ctx,
}
static grub_err_t
-tpm2_protector_nv_recover (const tpm2_protector_context_t *ctx,
- grub_uint8_t **key, grub_size_t *key_size)
+tpm2_protector_load_persistent (const tpm2_protector_context_t *ctx, TPM_HANDLE_t sealed_handle,
+ grub_uint8_t **key, grub_size_t *key_size)
{
- TPM_HANDLE_t sealed_handle = ctx->nv;
tpm2key_policy_t policy_seq = NULL;
bool dump_pcr = false;
grub_err_t err;
@@ -1163,6 +1162,51 @@ tpm2_protector_nv_recover (const tpm2_protector_context_t *ctx,
return err;
}
+static grub_err_t
+tpm2_protector_key_from_nvindex (const tpm2_protector_context_t *ctx, TPM_HANDLE_t nvindex,
+ grub_uint8_t **key, grub_size_t *key_size)
+{
+ TPMS_AUTH_COMMAND_t authCmd = {0};
+ TPM2B_NV_PUBLIC_t nv_public;
+ TPM2B_NAME_t nv_name;
+ grub_uint16_t data_size;
+ TPM2B_MAX_NV_BUFFER_t data;
+ TPM_RC_t rc;
+
+ /* Get the data size in the NV index handle */
+ rc = grub_tpm2_nv_readpublic (nvindex, NULL, &nv_public, &nv_name);
+ if (rc != TPM_RC_SUCCESS)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to retrieve info from 0x%x (TPM2_NV_ReadPublic: 0x%x)", nvindex, rc);
+
+ data_size = nv_public.nvPublic.dataSize;
+ if (data_size > TPM_MAX_NV_BUFFER_SIZE)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "insufficient data buffer");
+
+ /* Read the data from the NV index handle */
+ authCmd.sessionHandle = TPM_RS_PW;
+ rc = grub_tpm2_nv_read (TPM_RH_OWNER, nvindex, &authCmd, data_size, 0, &data);
+ if (rc != TPM_RC_SUCCESS)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to read data from 0x%x (TPM2_NV_Read: 0x%x)", nvindex, rc);
+
+ return tpm2_protector_key_from_buffer (ctx, data.buffer, data_size, key, key_size);
+}
+
+static grub_err_t
+tpm2_protector_nv_recover (const tpm2_protector_context_t *ctx,
+ grub_uint8_t **key, grub_size_t *key_size)
+{
+ grub_err_t err;
+
+ if (TPM_HT_IS_PERSISTENT (ctx->nv) == true)
+ err = tpm2_protector_load_persistent (ctx, ctx->nv, key, key_size);
+ else if (TPM_HT_IS_NVINDEX (ctx->nv) == true)
+ err = tpm2_protector_key_from_nvindex (ctx, ctx->nv, key, key_size);
+ else
+ err = GRUB_ERR_BAD_ARGUMENT;
+
+ return err;
+}
+
static grub_err_t
tpm2_protector_recover (const tpm2_protector_context_t *ctx,
grub_uint8_t **key, grub_size_t *key_size)
@@ -1215,14 +1259,15 @@ tpm2_protector_check_args (tpm2_protector_context_t *ctx)
if (ctx->mode == TPM2_PROTECTOR_MODE_NV &&
(ctx->tpm2key != NULL || ctx->keyfile != NULL))
- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("in NV Index mode, a keyfile cannot be specified"));
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("a key file cannot be specified when using NV index mode"));
- if (ctx->mode == TPM2_PROTECTOR_MODE_NV && ctx->srk != 0)
- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("in NV Index mode, an SRK cannot be specified"));
+ if (ctx->mode == TPM2_PROTECTOR_MODE_NV && TPM_HT_IS_PERSISTENT (ctx->nv) == true &&
+ (ctx->srk != 0 || ctx->srk_type.type != TPM_ALG_ERROR))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("an SRK cannot be specified when using NV index mode with a persistent handle"));
if (ctx->mode == TPM2_PROTECTOR_MODE_NV &&
- ctx->srk_type.type != TPM_ALG_ERROR)
- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("in NV Index mode, an asymmetric key type cannot be specified"));
+ (TPM_HT_IS_PERSISTENT (ctx->nv) == false && TPM_HT_IS_NVINDEX (ctx->nv) == false))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("an NV index must be either a persistent handle or an NV index handle when using NV index mode"));
/* Defaults assignment */
if (ctx->bank == TPM_ALG_ERROR)
@@ -1234,8 +1279,13 @@ tpm2_protector_check_args (tpm2_protector_context_t *ctx)
ctx->pcr_count = 1;
}
- if (ctx->mode == TPM2_PROTECTOR_MODE_SRK &&
- ctx->srk_type.type == TPM_ALG_ERROR)
+ /*
+ * Set ECC_NIST_P256 as the default SRK when using SRK mode or NV mode with
+ * an NV index handle
+ */
+ if (ctx->srk_type.type == TPM_ALG_ERROR &&
+ (ctx->mode == TPM2_PROTECTOR_MODE_SRK ||
+ (ctx->mode == TPM2_PROTECTOR_MODE_NV && TPM_HT_IS_NVINDEX (ctx->nv) == true)))
{
ctx->srk_type.type = TPM_ALG_ECC;
ctx->srk_type.detail.ecc_curve = TPM_ECC_NIST_P256;
--
2.43.0

View File

@@ -1,111 +0,0 @@
From 9dce8958d674c09a93c893a5ef36807e6f286c45 Mon Sep 17 00:00:00 2001
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Date: Tue, 25 Feb 2025 02:20:20 +0530
Subject: [PATCH 7/9] appendedsig: Reads the default DB keys from ELF Note
If Secure Boot is enabled with PKS and the use_static_keys flag is set,
then read the DB default keys from the ELF note and store them in the trusted list buffer.
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
---
grub-core/commands/appendedsig/appendedsig.c | 56 ++++++++++++++------
1 file changed, 40 insertions(+), 16 deletions(-)
diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c
index b6daccd3d7..3cbe51ec13 100644
--- a/grub-core/commands/appendedsig/appendedsig.c
+++ b/grub-core/commands/appendedsig/appendedsig.c
@@ -1073,7 +1073,7 @@ create_distrusted_list (void)
* parse it, and add it to the trusted list.
*/
static grub_err_t
-build_static_trusted_list (const struct grub_module_header *header)
+build_static_trusted_list (const struct grub_module_header *header, const grub_bool_t is_pks)
{
grub_err_t err = GRUB_ERR_NONE;
struct grub_file pseudo_file;
@@ -1092,6 +1092,13 @@ build_static_trusted_list (const struct grub_module_header *header)
if (err != GRUB_ERR_NONE)
return err;
+ if (is_pks)
+ {
+ err = is_distrusted_cert_hash (cert_data, cert_data_size);
+ if (err != GRUB_ERR_NONE)
+ return err;
+ }
+
err = add_certificate (cert_data, cert_data_size, &db, 1);
grub_free (cert_data);
@@ -1144,6 +1151,22 @@ free_distrusted_list (void)
grub_memset (&dbx, 0, sizeof (dbx));
}
+static grub_err_t
+load_static_keys (const struct grub_module_header *header, const grub_bool_t is_pks)
+{
+ int rc = GRUB_ERR_NONE;
+ FOR_MODULES (header)
+ {
+ /* Not an ELF module, skip. */
+ if (header->type != OBJ_TYPE_X509_PUBKEY)
+ continue;
+ rc = build_static_trusted_list (header, is_pks);
+ if (rc != GRUB_ERR_NONE)
+ return rc;
+ }
+ return rc;
+}
+
GRUB_MOD_INIT (appendedsig)
{
int rc;
@@ -1163,26 +1186,27 @@ GRUB_MOD_INIT (appendedsig)
if (!grub_pks_use_keystore && check_sigs == check_sigs_forced)
{
- FOR_MODULES (header)
+ rc = load_static_keys (header, false);
+ if (rc != GRUB_ERR_NONE)
{
- /* Not an ELF module, skip. */
- if (header->type != OBJ_TYPE_X509_PUBKEY)
- continue;
-
- rc = build_static_trusted_list (header);
- if (rc != GRUB_ERR_NONE)
- {
- free_trusted_list ();
- grub_error (rc, "static trusted list creation failed");
- }
- else
- grub_printf ("appendedsig: the trusted list now has %" PRIuGRUB_SIZE " static keys\n",
- db.key_entries);
+ free_trusted_list ();
+ grub_error (rc, "static trusted list creation failed");
}
+ else
+ grub_printf ("appendedsig: the trusted list now has %" PRIuGRUB_SIZE " static keys\n",
+ db.key_entries);
}
else if (grub_pks_use_keystore && check_sigs == check_sigs_forced)
{
- rc = create_trusted_list ();
+ if (grub_pks_keystore.use_static_keys)
+ {
+ grub_printf ("Warning: db variable is not available at PKS and using a static keys "
+ "as a default key in trusted list\n");
+ rc = load_static_keys (header, grub_pks_keystore.use_static_keys);
+ }
+ else
+ rc = create_trusted_list ();
+
if (rc != GRUB_ERR_NONE)
{
free_trusted_list ();
--
2.48.1

View File

@@ -1,32 +0,0 @@
From d5a155864230964878280a52dc82392382af1c5d Mon Sep 17 00:00:00 2001
From: Maxim Suhanov <dfirblog@gmail.com>
Date: Thu, 8 May 2025 19:02:13 +0200
Subject: [PATCH 7/8] disk/cryptodisk: Wipe the passphrase from memory
Switching to another EFI boot application while there are secrets in
RAM is dangerous, because not all firmware is wiping memory on free.
To reduce the attack surface, wipe the passphrase acquired when
unlocking an encrypted volume.
Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/disk/cryptodisk.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index f9ae750f85..cb87d337ac 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -1251,6 +1251,7 @@ grub_cryptodisk_scan_device_real (const char *name,
#endif
if (askpass)
{
+ grub_memset (cargs->key_data, 0, cargs->key_len);
cargs->key_len = 0;
grub_free (cargs->key_data);
}
--
2.49.0

View File

@@ -1,216 +0,0 @@
From 6701b4a9e1994c8a05c87a7167694bc3dd71e7d6 Mon Sep 17 00:00:00 2001
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Date: Wed, 23 Oct 2024 17:54:32 +0530
Subject: [PATCH 7/8] grub-mkimage: Create new ELF note for SBAT
In order to store the SBAT data we create a new ELF note. The string
".sbat", zero-padded to 4 byte alignment, shall be entered in the name
field. The string "SBAT"'s ASCII values, 0x53424154, should be entered
in the type field.
Signed-off-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
include/grub/util/mkimage.h | 4 +-
util/grub-mkimagexx.c | 92 +++++++++++++++++++++++++++----------
util/mkimage.c | 5 +-
3 files changed, 74 insertions(+), 27 deletions(-)
diff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h
index 6f1da89b9..881e3031f 100644
--- a/include/grub/util/mkimage.h
+++ b/include/grub/util/mkimage.h
@@ -51,12 +51,12 @@ grub_mkimage_load_image64 (const char *kernel_path,
const struct grub_install_image_target_desc *image_target);
void
grub_mkimage_generate_elf32 (const struct grub_install_image_target_desc *image_target,
- int note, size_t appsig_size, char **core_img, size_t *core_size,
+ int note, size_t appsig_size, char *sbat, char **core_img, size_t *core_size,
Elf32_Addr target_addr,
struct grub_mkimage_layout *layout);
void
grub_mkimage_generate_elf64 (const struct grub_install_image_target_desc *image_target,
- int note, size_t appsig_size, char **core_img, size_t *core_size,
+ int note, size_t appsig_size, char *sbat, char **core_img, size_t *core_size,
Elf64_Addr target_addr,
struct grub_mkimage_layout *layout);
diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
index 9488f0525..b507d4ade 100644
--- a/util/grub-mkimagexx.c
+++ b/util/grub-mkimagexx.c
@@ -116,6 +116,14 @@ struct section_metadata
const char *strtab;
};
+#define GRUB_SBAT_NOTE_NAME ".sbat"
+#define GRUB_SBAT_NOTE_TYPE 0x53424154 /* "SBAT" */
+
+struct grub_sbat_note {
+ Elf32_Nhdr header;
+ char name[ALIGN_UP(sizeof(GRUB_SBAT_NOTE_NAME), 4)];
+};
+
static int
is_relocatable (const struct grub_install_image_target_desc *image_target)
{
@@ -217,7 +225,7 @@ grub_arm_reloc_jump24 (grub_uint32_t *target, Elf32_Addr sym_addr)
void
SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc *image_target,
- int note, size_t appsig_size, char **core_img, size_t *core_size,
+ int note, size_t appsig_size, char *sbat, char **core_img, size_t *core_size,
Elf_Addr target_addr,
struct grub_mkimage_layout *layout)
{
@@ -226,10 +234,17 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
Elf_Ehdr *ehdr;
Elf_Phdr *phdr;
Elf_Shdr *shdr;
- int header_size, footer_size = 0;
+ int header_size, footer_size = 0, footer_offset = 0;
int phnum = 1;
int shnum = 4;
int string_size = sizeof (".text") + sizeof ("mods") + 1;
+ char *footer;
+
+ if (sbat)
+ {
+ phnum++;
+ footer_size += ALIGN_UP (sizeof (struct grub_sbat_note) + layout->sbat_size, 4);
+ }
if (appsig_size)
{
@@ -263,6 +278,7 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
ehdr = (void *) elf_img;
phdr = (void *) (elf_img + sizeof (*ehdr));
shdr = (void *) (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr));
+ footer = elf_img + program_size + header_size;
memcpy (ehdr->e_ident, ELFMAG, SELFMAG);
ehdr->e_ident[EI_CLASS] = ELFCLASSXX;
if (!image_target->bigendian)
@@ -435,6 +451,8 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
phdr->p_filesz = grub_host_to_target32 (XEN_NOTE_SIZE);
phdr->p_memsz = 0;
phdr->p_offset = grub_host_to_target32 (header_size + program_size);
+ footer = ptr;
+ footer_offset = XEN_NOTE_SIZE;
}
if (image_target->id == IMAGE_XEN_PVH)
@@ -468,6 +486,8 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
phdr->p_filesz = grub_host_to_target32 (XEN_PVH_NOTE_SIZE);
phdr->p_memsz = 0;
phdr->p_offset = grub_host_to_target32 (header_size + program_size);
+ footer = ptr;
+ footer_offset = XEN_PVH_NOTE_SIZE;
}
if (note)
@@ -498,29 +518,55 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
phdr->p_filesz = grub_host_to_target32 (note_size);
phdr->p_memsz = 0;
phdr->p_offset = grub_host_to_target32 (header_size + program_size);
+ footer = (elf_img + program_size + header_size + note_size);
+ footer_offset += note_size;
}
- if (appsig_size) {
- int note_size = ALIGN_UP(sizeof (struct grub_appended_signature_note) + appsig_size, 4);
- struct grub_appended_signature_note *note_ptr = (struct grub_appended_signature_note *)
- (elf_img + program_size + header_size + (note ? sizeof (struct grub_ieee1275_note) : 0));
-
- note_ptr->header.n_namesz = grub_host_to_target32 (sizeof (GRUB_APPENDED_SIGNATURE_NOTE_NAME));
- /* needs to sit at the end, so we round this up and sign some zero padding */
- note_ptr->header.n_descsz = grub_host_to_target32 (ALIGN_UP(appsig_size, 4));
- note_ptr->header.n_type = grub_host_to_target32 (GRUB_APPENDED_SIGNATURE_NOTE_TYPE);
- strcpy (note_ptr->name, GRUB_APPENDED_SIGNATURE_NOTE_NAME);
-
- phdr++;
- phdr->p_type = grub_host_to_target32 (PT_NOTE);
- phdr->p_flags = grub_host_to_target32 (PF_R);
- phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
- phdr->p_vaddr = 0;
- phdr->p_paddr = 0;
- phdr->p_filesz = grub_host_to_target32 (note_size);
- phdr->p_memsz = 0;
- phdr->p_offset = grub_host_to_target32 (header_size + program_size + (note ? sizeof (struct grub_ieee1275_note) : 0));
- }
+ if (sbat)
+ {
+ int note_size = ALIGN_UP (sizeof (struct grub_sbat_note) + layout->sbat_size, 4);
+ struct grub_sbat_note *note_ptr = (struct grub_sbat_note *) footer;
+
+ note_ptr->header.n_namesz = grub_host_to_target32 (sizeof (GRUB_SBAT_NOTE_NAME));
+ note_ptr->header.n_descsz = grub_host_to_target32 (ALIGN_UP(layout->sbat_size, 4));
+ note_ptr->header.n_type = grub_host_to_target32 (GRUB_SBAT_NOTE_TYPE);
+ memcpy (note_ptr->name, GRUB_SBAT_NOTE_NAME, sizeof (GRUB_SBAT_NOTE_NAME));
+ memcpy ((char *)(note_ptr + 1), sbat, layout->sbat_size);
+
+ phdr++;
+ phdr->p_type = grub_host_to_target32 (PT_NOTE);
+ phdr->p_flags = grub_host_to_target32 (PF_R);
+ phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
+ phdr->p_vaddr = 0;
+ phdr->p_paddr = 0;
+ phdr->p_filesz = grub_host_to_target32 (note_size);
+ phdr->p_memsz = 0;
+ phdr->p_offset = grub_host_to_target32 (header_size + program_size + footer_offset);
+
+ footer += note_size;
+ footer_offset += note_size;
+ }
+
+ if (appsig_size)
+ {
+ int note_size = ALIGN_UP (sizeof (struct grub_appended_signature_note) + appsig_size, 4);
+ struct grub_appended_signature_note *note_ptr = (struct grub_appended_signature_note *)footer;
+ note_ptr->header.n_namesz = grub_host_to_target32 (sizeof (GRUB_APPENDED_SIGNATURE_NOTE_NAME));
+ /* needs to sit at the end, so we round this up and sign some zero padding */
+ note_ptr->header.n_descsz = grub_host_to_target32 (ALIGN_UP (appsig_size, 4));
+ note_ptr->header.n_type = grub_host_to_target32 (GRUB_APPENDED_SIGNATURE_NOTE_TYPE);
+ strcpy (note_ptr->name, GRUB_APPENDED_SIGNATURE_NOTE_NAME);
+
+ phdr++;
+ phdr->p_type = grub_host_to_target32 (PT_NOTE);
+ phdr->p_flags = grub_host_to_target32 (PF_R);
+ phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
+ phdr->p_vaddr = 0;
+ phdr->p_paddr = 0;
+ phdr->p_filesz = grub_host_to_target32 (note_size);
+ phdr->p_memsz = 0;
+ phdr->p_offset = grub_host_to_target32 (header_size + program_size + footer_offset);
+ }
{
char *str_start = (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr)
diff --git a/util/mkimage.c b/util/mkimage.c
index 0737935fd..be7f02c5c 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -1835,6 +1835,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
case IMAGE_I386_IEEE1275:
{
grub_uint64_t target_addr;
+ char *sbat = NULL;
if (image_target->id == IMAGE_LOONGSON_ELF)
{
if (comp == GRUB_COMPRESSION_NONE)
@@ -1846,10 +1847,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
else
target_addr = image_target->link_addr;
if (image_target->voidp_sizeof == 4)
- grub_mkimage_generate_elf32 (image_target, note, appsig_size, &core_img,
+ grub_mkimage_generate_elf32 (image_target, note, appsig_size, sbat, &core_img,
&core_size, target_addr, &layout);
else
- grub_mkimage_generate_elf64 (image_target, note, appsig_size, &core_img,
+ grub_mkimage_generate_elf64 (image_target, note, appsig_size, sbat, &core_img,
&core_size, target_addr, &layout);
}
break;
--
2.47.1

View File

@@ -0,0 +1,279 @@
From 96e5a28d120856057fe7fc9b281f11f8933063b7 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 30 Jun 2023 14:37:41 +0800
Subject: [PATCH 7/9] grub-switch-to-blscfg: adapt to openSUSE
A few tweaks to make it 'just works' for openSUSE:
- remove RHEL specific $grub_get_kernel_settings and all reference to it.
- make $grubdir and $startlink to the path in openSUSE
- change the bls template to openSUSE
- make $cmdline account for btrfs subvolumes, among others
- remove RHEL specific $GRUB_LINUX_MAKE_DEBUG and all related code
- remove ostree specific hack
- ignore increment.mod
- fix error in dash shell script
- fix kernel flavor parsing in openSUSE
Signed-off-by: Michael Chang <mchang@suse.com>
---
util/grub-switch-to-blscfg.in | 156 ++++++++++++++++++++--------------
1 file changed, 94 insertions(+), 62 deletions(-)
diff --git a/util/grub-switch-to-blscfg.in b/util/grub-switch-to-blscfg.in
index a851424be..145c22add 100644
--- a/util/grub-switch-to-blscfg.in
+++ b/util/grub-switch-to-blscfg.in
@@ -28,27 +28,24 @@ PACKAGE_NAME=@PACKAGE_NAME@
PACKAGE_VERSION=@PACKAGE_VERSION@
datarootdir="@datarootdir@"
datadir="@datadir@"
-if [ ! -v pkgdatadir ]; then
+if [ -z "${pkgdatadir+x}" ]; then
pkgdatadir="${datadir}/@PACKAGE@"
fi
self=`basename $0`
-grub_get_kernel_settings="${sbindir}/@grub_get_kernel_settings@"
grub_editenv=${bindir}/@grub_editenv@
-etcdefaultgrub=/etc/default/grub
+grub_probe="${sbindir}/@grub_probe@"
+etcdefaultgrub=${sysconfdir}/default/grub
-eval "$("${grub_get_kernel_settings}")" || true
-
-EFIDIR=$(grep ^ID= /etc/os-release | sed -e 's/^ID=//' -e 's/rhel/redhat/' -e 's/\"//g')
-if [ -d /sys/firmware/efi/efivars/ ]; then
- startlink=/etc/grub2-efi.cfg
- grubdir=`echo "/@bootdirname@/efi/EFI/${EFIDIR}/" | sed 's,//*,/,g'`
-else
- startlink=/etc/grub2.cfg
- grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'`
+if test -f "$etcdefaultgrub" ; then
+ # shellcheck source=/etc/default/grub
+ . "$etcdefaultgrub"
fi
+grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'`
+startlink="${grubdir}/grub.cfg"
+
blsdir=`echo "/@bootdirname@/loader/entries" | sed 's,//*,/,g'`
backupsuffix=.bak
@@ -58,19 +55,80 @@ arch="$(uname -m)"
export TEXTDOMAIN=@PACKAGE@
export TEXTDOMAINDIR="@localedir@"
+# shellcheck source=/usr/share/grub2/grub-mkconfig_lib
. "${pkgdatadir}/grub-mkconfig_lib"
+# FIXME: Abort if grub_probe fails
+
+GRUB_DEVICE="`${grub_probe} --target=device /`"
+GRUB_DEVICE_UUID="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> /dev/null`" || true
+GRUB_DEVICE_PARTUUID="`${grub_probe} --device ${GRUB_DEVICE} --target=partuuid 2> /dev/null`" || true
+GRUB_FS="`${grub_probe} --device ${GRUB_DEVICE} --target=fs 2> /dev/null || echo unknown`"
+
+# loop-AES arranges things so that /dev/loop/X can be our root device, but
+# the initrds that Linux uses don't like that.
+case ${GRUB_DEVICE} in
+ /dev/loop/*|/dev/loop[0-9])
+ GRUB_DEVICE=$(losetup "${GRUB_DEVICE}" | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/")
+ ;;
+esac
+
+# Default to disabling partition uuid support to maintian compatibility with
+# older kernels.
+GRUB_DISABLE_LINUX_PARTUUID=${GRUB_DISABLE_LINUX_PARTUUID-true}
+
+# btrfs may reside on multiple devices. We cannot pass them as value of root= parameter
+# and mounting btrfs requires user space scanning, so force UUID in this case.
+if ( [ "x${GRUB_DEVICE_UUID}" = "x" ] && [ "x${GRUB_DEVICE_PARTUUID}" = "x" ] ) \
+ || ( [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
+ && [ "x${GRUB_DISABLE_LINUX_PARTUUID}" = "xtrue" ] ) \
+ || ( ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \
+ && ! test -e "/dev/disk/by-partuuid/${GRUB_DEVICE_PARTUUID}" ) \
+ || ( test -e "${GRUB_DEVICE}" && uses_abstraction "${GRUB_DEVICE}" lvm ); then
+ LINUX_ROOT_DEVICE=${GRUB_DEVICE}
+elif [ "x${GRUB_DEVICE_UUID}" = "x" ] \
+ || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ]; then
+ LINUX_ROOT_DEVICE=PARTUUID=${GRUB_DEVICE_PARTUUID}
+else
+ LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}
+fi
+
+if [ "x$GRUB_CONMODE" != "x" ]; then
+ GRUB_CMDLINE_LINUX="conmode=${GRUB_CONMODE} ${GRUB_CMDLINE_LINUX}"
+fi
+
+case x"$GRUB_FS" in
+ xbtrfs)
+ if [ "x${SUSE_BTRFS_SNAPSHOT_BOOTING}" != "xtrue" ]; then
+ rootsubvol="`make_system_path_relative_to_its_root /`"
+ rootsubvol="${rootsubvol#/}"
+ if [ "x${rootsubvol}" != x ] && [ "x$SUSE_REMOVE_LINUX_ROOT_PARAM" != "xtrue" ]; then
+ GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}"
+ fi
+ fi
+ ;;
+ xzfs)
+ rpool=`${grub_probe} --device ${GRUB_DEVICE} --target=fs_label 2>/dev/null || true`
+ bootfs="`make_system_path_relative_to_its_root / | sed -e "s,@$,,"`"
+ LINUX_ROOT_DEVICE="ZFS=${rpool}${bootfs%/}"
+ ;;
+esac
+
+if [ "x$SUSE_REMOVE_LINUX_ROOT_PARAM" = "xtrue" ]; then
+ LINUX_ROOT_DEVICE=""
+fi
+
# Usage: usage
# Print the usage.
usage () {
gettext_printf "Usage: %s\n" "$self"
- gettext "Switch to BLS config files.\n"; echo
+ gettext "Switch to BLS config files. Only for testing purpose !!!\n"; echo
echo
print_option_help "-h, --help" "$(gettext "print this message and exit")"
print_option_help "-V, --version" "$(gettext "print the version information and exit")"
echo
print_option_help "--backup-suffix=$(gettext "SUFFIX")" "$backupsuffix"
- print_option_help "--bls-directory=$(gettext "DIR")" "$blsdir"
+ print_option_help "--bls-directory=$(gettext "DIR")" "Noop, always $blsdir"
print_option_help "--config-file=$(gettext "FILE")" "$startlink"
print_option_help "--grub-defaults=$(gettext "FILE")" "$etcdefaultgrub"
print_option_help "--grub-directory=$(gettext "DIR")" "$grubdir"
@@ -112,11 +170,15 @@ do
;;
--bls-directory)
- blsdir=`argument $option "$@"`
+ # blsdir=`argument $option "$@"`
+ gettext_printf "WARN: --bls-directory is currently disabled, it's always $blsdir !!!\n"
+ gettext_printf "WARN: use kernel-install instead if you want to test bls directory on ESP !!!\n"
shift
;;
--bls-directory=*)
- blsdir=`echo "$option" | sed 's/--bls-directory=//'`
+ # blsdir=`echo "$option" | sed 's/--bls-directory=//'`
+ gettext_printf "WARN: --bls-directory is currently disabled, it's always $blsdir !!!\n"
+ gettext_printf "WARN: use kernel-install instead if you want to test bls directory on ESP !!!\n"
;;
--config-file)
@@ -172,7 +234,7 @@ find_grub_cfg() {
return 1
}
-if ! find_grub_cfg ${startlink} ${grubdir}/grub.cfg ; then
+if ! find_grub_cfg "${startlink}" ; then
gettext_printf "Couldn't find config file\n" 1>&2
exit 1
fi
@@ -190,27 +252,24 @@ fi
mkbls() {
local kernelver=$1 && shift
local datetime=$1 && shift
+ local prefix=$1 && shift
local kernelopts=$1 && shift
- local debugname=""
- local debugid=""
local flavor=""
- if [ "$kernelver" == *\+* ] ; then
- local flavor=-"${kernelver##*+}"
- if [ "${flavor}" == "-debug" ]; then
- local debugname=" with debugging"
- local debugid="-debug"
- fi
- fi
+ case "$kernelver" in
+ *-*-*)
+ flavor=-"${kernelver##*-}"
+ ;;
+ esac
(
- source /etc/os-release
+ . /etc/os-release
cat <<EOF
-title ${NAME} (${kernelver}) ${VERSION}${debugname}
-version ${kernelver}${debugid}
-linux /vmlinuz-${kernelver}
-initrd /initramfs-${kernelver}.img
+title ${NAME} (${kernelver}) ${VERSION}
+version ${kernelver}
+linux ${prefix}/vmlinuz-${kernelver}
+initrd ${prefix}/initrd-${kernelver}
options ${kernelopts}
grub_users \$grub_users
grub_arg --unrestricted
@@ -233,42 +292,15 @@ copy_bls() {
continue
fi
- linux_relpath="$("${grub_mkrelpath}" "${linux_path}")"
- bootprefix="${linux_relpath%%"${linux}"}"
+ bootprefix="$(make_system_path_relative_to_its_root /boot)"
cmdline="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
mkbls "${kernelver}" \
"$(date -u +%Y%m%d%H%M%S -d "$(stat -c '%y' "${kernel_dir}")")" \
"${bootprefix}" "${cmdline}" >"${bls_target}"
-
- if [ "x$GRUB_LINUX_MAKE_DEBUG" = "xtrue" ]; then
- bls_debug="$(echo ${bls_target} | sed -e "s/${kernelver}/${kernelver}~debug/")"
- cp -aT "${bls_target}" "${bls_debug}"
- title="$(grep '^title[ \t]' "${bls_debug}" | sed -e 's/^title[ \t]*//')"
- options="$(echo "${cmdline} ${GRUB_CMDLINE_LINUX_DEBUG}" | sed -e 's/\//\\\//g')"
- sed -i -e "s/^title.*/title ${title}${GRUB_LINUX_DEBUG_TITLE_POSTFIX}/" "${bls_debug}"
- sed -i -e "s/^options.*/options ${options}/" "${bls_debug}"
- fi
done
-
- if [ -f "/boot/vmlinuz-0-rescue-${MACHINE_ID}" ]; then
- mkbls "0-rescue-${MACHINE_ID}" "0" "${bootprefix}" >"${blsdir}/${MACHINE_ID}-0-rescue.conf"
- fi
}
-# The grub2 EFI binary is not copied to the ESP as a part of an ostree
-# transaction. Make sure a grub2 version with BLS support is installed
-# but only do this if the blsdir is not set, to make sure that the BLS
-# parsing module will search for the BLS snippets in the default path.
-if test -f /run/ostree-booted && test -d /sys/firmware/efi/efivars && \
- ! ${grub_editenv} - list | grep -q blsdir && \
- mountpoint -q /boot; then
- grub_binary="$(find /usr/lib/ostree-boot/efi/EFI/${EFIDIR}/ -name grub*.efi)"
- install -m 700 ${grub_binary} ${grubdir} || exit 1
- # Create a hidden file to indicate that grub2 now has BLS support.
- touch /boot/grub2/.grub2-blscfg-supported
-fi
-
GENERATE=0
if grep '^GRUB_ENABLE_BLSCFG=.*' "${etcdefaultgrub}" \
| grep -vq '^GRUB_ENABLE_BLSCFG="*true"*\s*$' ; then
@@ -297,9 +329,7 @@ if [ "${GENERATE}" -eq 1 ] ; then
fi
if [ -n "${mod_dir}" ]; then
- for mod in blscfg increment; do
- install -m 700 ${prefix}/lib/grub/${mod_dir}/${mod}.mod ${grubdir}/$mod_dir/ || exit 1
- done
+ install -m 700 "${pkgdatadir}/${mod_dir}/blscfg.mod" "${grubdir}/$mod_dir/" || exit 1
fi
cp -af "${GRUB_CONFIG_FILE}" "${GRUB_CONFIG_FILE}${backupsuffix}"
@@ -311,6 +341,8 @@ if [ "${GENERATE}" -eq 1 ] ; then
gettext_printf "Updating %s failed\n" "${GRUB_CONFIG_FILE}"
exit 1
fi
+else
+ gettext_printf "Do nothing because \$GRUB_ENABLE_BLSCFG is already true in %s\n" "${GRUB_CONFIG_FILE}"
fi
# Bye.
--
2.45.2

View File

@@ -1,443 +0,0 @@
From 8e9240826c7d230cab6d52724d2cf3759e6f0d3f Mon Sep 17 00:00:00 2001
From: B Horn <b@horn.uk>
Date: Sun, 12 May 2024 10:15:03 +0100
Subject: [PATCH 07/20] kern/file: Implement filesystem reference counting
The grub_file_open() and grub_file_close() should be the only places
that allow a reference to a filesystem to stay open. So, add grub_dl_t
to grub_fs_t and set this in the GRUB_MOD_INIT() for each filesystem to
avoid issues when filesystems forget to do it themselves or do not track
their own references, e.g. squash4.
The fs_label(), fs_uuid(), fs_mtime() and fs_read() should all ref and
unref in the same function but it is essentially redundant in GRUB
single threaded model.
Signed-off-by: B Horn <b@horn.uk>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/affs.c | 1 +
grub-core/fs/bfs.c | 1 +
grub-core/fs/btrfs.c | 1 +
grub-core/fs/cbfs.c | 1 +
grub-core/fs/cpio.c | 1 +
grub-core/fs/cpio_be.c | 1 +
grub-core/fs/ext2.c | 1 +
grub-core/fs/f2fs.c | 1 +
grub-core/fs/fat.c | 1 +
grub-core/fs/hfs.c | 1 +
grub-core/fs/hfsplus.c | 1 +
grub-core/fs/iso9660.c | 1 +
grub-core/fs/jfs.c | 1 +
grub-core/fs/minix.c | 1 +
grub-core/fs/newc.c | 1 +
grub-core/fs/nilfs2.c | 1 +
grub-core/fs/ntfs.c | 1 +
grub-core/fs/odc.c | 1 +
grub-core/fs/proc.c | 1 +
grub-core/fs/reiserfs.c | 1 +
grub-core/fs/romfs.c | 1 +
grub-core/fs/sfs.c | 1 +
grub-core/fs/squash4.c | 1 +
grub-core/fs/tar.c | 1 +
grub-core/fs/udf.c | 1 +
grub-core/fs/ufs.c | 1 +
grub-core/fs/xfs.c | 1 +
grub-core/fs/zfs/zfs.c | 1 +
grub-core/kern/file.c | 7 +++++++
include/grub/fs.h | 4 ++++
30 files changed, 39 insertions(+)
diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c
index ed606b3f15..9b0afb9541 100644
--- a/grub-core/fs/affs.c
+++ b/grub-core/fs/affs.c
@@ -703,6 +703,7 @@ static struct grub_fs grub_affs_fs =
GRUB_MOD_INIT(affs)
{
+ grub_affs_fs.mod = mod;
grub_fs_register (&grub_affs_fs);
my_mod = mod;
}
diff --git a/grub-core/fs/bfs.c b/grub-core/fs/bfs.c
index 07cb3e3acf..f37b168958 100644
--- a/grub-core/fs/bfs.c
+++ b/grub-core/fs/bfs.c
@@ -1106,6 +1106,7 @@ GRUB_MOD_INIT (bfs)
{
COMPILE_TIME_ASSERT (1 << LOG_EXTENT_SIZE ==
sizeof (struct grub_bfs_extent));
+ grub_bfs_fs.mod = mod;
grub_fs_register (&grub_bfs_fs);
}
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
index 7e12dce9c2..0dd9a817ee 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -3565,6 +3565,7 @@ relpath_set_env (struct grub_env_var *var,
GRUB_MOD_INIT (btrfs)
{
+ grub_btrfs_fs.mod = mod;
grub_fs_register (&grub_btrfs_fs);
cmd_info = grub_register_command("btrfs-info", grub_cmd_btrfs_info,
"DEVICE",
diff --git a/grub-core/fs/cbfs.c b/grub-core/fs/cbfs.c
index 8ab7106afb..2332745fe8 100644
--- a/grub-core/fs/cbfs.c
+++ b/grub-core/fs/cbfs.c
@@ -390,6 +390,7 @@ GRUB_MOD_INIT (cbfs)
#if (defined (__i386__) || defined (__x86_64__)) && !defined (GRUB_UTIL) && !defined (GRUB_MACHINE_EMU) && !defined (GRUB_MACHINE_XEN)
init_cbfsdisk ();
#endif
+ grub_cbfs_fs.mod = mod;
grub_fs_register (&grub_cbfs_fs);
}
diff --git a/grub-core/fs/cpio.c b/grub-core/fs/cpio.c
index dab5f98988..1799f7ff5a 100644
--- a/grub-core/fs/cpio.c
+++ b/grub-core/fs/cpio.c
@@ -52,6 +52,7 @@ read_number (const grub_uint16_t *arr, grub_size_t size)
GRUB_MOD_INIT (cpio)
{
+ grub_cpio_fs.mod = mod;
grub_fs_register (&grub_cpio_fs);
}
diff --git a/grub-core/fs/cpio_be.c b/grub-core/fs/cpio_be.c
index 8465488921..7bed1b848c 100644
--- a/grub-core/fs/cpio_be.c
+++ b/grub-core/fs/cpio_be.c
@@ -52,6 +52,7 @@ read_number (const grub_uint16_t *arr, grub_size_t size)
GRUB_MOD_INIT (cpio_be)
{
+ grub_cpio_fs.mod = mod;
grub_fs_register (&grub_cpio_fs);
}
diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c
index e1cc5e62aa..04f5d04e14 100644
--- a/grub-core/fs/ext2.c
+++ b/grub-core/fs/ext2.c
@@ -1123,6 +1123,7 @@ static struct grub_fs grub_ext2_fs =
GRUB_MOD_INIT(ext2)
{
+ grub_ext2_fs.mod = mod;
grub_fs_register (&grub_ext2_fs);
my_mod = mod;
}
diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c
index 855e24618c..7e48796036 100644
--- a/grub-core/fs/f2fs.c
+++ b/grub-core/fs/f2fs.c
@@ -1350,6 +1350,7 @@ static struct grub_fs grub_f2fs_fs = {
GRUB_MOD_INIT (f2fs)
{
+ grub_f2fs_fs.mod = mod;
grub_fs_register (&grub_f2fs_fs);
my_mod = mod;
}
diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c
index c5efed7241..6e62b915dd 100644
--- a/grub-core/fs/fat.c
+++ b/grub-core/fs/fat.c
@@ -1312,6 +1312,7 @@ GRUB_MOD_INIT(fat)
#endif
{
COMPILE_TIME_ASSERT (sizeof (struct grub_fat_dir_entry) == 32);
+ grub_fat_fs.mod = mod;
grub_fs_register (&grub_fat_fs);
my_mod = mod;
}
diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c
index 920112b03e..ce7581dd5f 100644
--- a/grub-core/fs/hfs.c
+++ b/grub-core/fs/hfs.c
@@ -1434,6 +1434,7 @@ static struct grub_fs grub_hfs_fs =
GRUB_MOD_INIT(hfs)
{
+ grub_hfs_fs.mod = mod;
if (!grub_is_lockdown ())
grub_fs_register (&grub_hfs_fs);
my_mod = mod;
diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c
index de71fd486b..3f203abccd 100644
--- a/grub-core/fs/hfsplus.c
+++ b/grub-core/fs/hfsplus.c
@@ -1176,6 +1176,7 @@ static struct grub_fs grub_hfsplus_fs =
GRUB_MOD_INIT(hfsplus)
{
+ grub_hfsplus_fs.mod = mod;
grub_fs_register (&grub_hfsplus_fs);
my_mod = mod;
}
diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c
index 8c348b59a5..5aabca284b 100644
--- a/grub-core/fs/iso9660.c
+++ b/grub-core/fs/iso9660.c
@@ -1247,6 +1247,7 @@ static struct grub_fs grub_iso9660_fs =
GRUB_MOD_INIT(iso9660)
{
+ grub_iso9660_fs.mod = mod;
grub_fs_register (&grub_iso9660_fs);
my_mod = mod;
}
diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c
index 6f7c439049..3139e53329 100644
--- a/grub-core/fs/jfs.c
+++ b/grub-core/fs/jfs.c
@@ -963,6 +963,7 @@ static struct grub_fs grub_jfs_fs =
GRUB_MOD_INIT(jfs)
{
+ grub_jfs_fs.mod = mod;
grub_fs_register (&grub_jfs_fs);
my_mod = mod;
}
diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c
index 5354951d10..b7679c3e25 100644
--- a/grub-core/fs/minix.c
+++ b/grub-core/fs/minix.c
@@ -734,6 +734,7 @@ GRUB_MOD_INIT(minix)
#endif
#endif
{
+ grub_minix_fs.mod = mod;
grub_fs_register (&grub_minix_fs);
my_mod = mod;
}
diff --git a/grub-core/fs/newc.c b/grub-core/fs/newc.c
index 4fb8b2e3d2..43b7f8b642 100644
--- a/grub-core/fs/newc.c
+++ b/grub-core/fs/newc.c
@@ -64,6 +64,7 @@ read_number (const char *str, grub_size_t size)
GRUB_MOD_INIT (newc)
{
+ grub_cpio_fs.mod = mod;
grub_fs_register (&grub_cpio_fs);
}
diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c
index fc7374ead4..4e1e717386 100644
--- a/grub-core/fs/nilfs2.c
+++ b/grub-core/fs/nilfs2.c
@@ -1231,6 +1231,7 @@ GRUB_MOD_INIT (nilfs2)
grub_nilfs2_dat_entry));
COMPILE_TIME_ASSERT (1 << LOG_INODE_SIZE
== sizeof (struct grub_nilfs2_inode));
+ grub_nilfs2_fs.mod = mod;
grub_fs_register (&grub_nilfs2_fs);
my_mod = mod;
}
diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
index de435aa14d..560917dc2c 100644
--- a/grub-core/fs/ntfs.c
+++ b/grub-core/fs/ntfs.c
@@ -1320,6 +1320,7 @@ static struct grub_fs grub_ntfs_fs =
GRUB_MOD_INIT (ntfs)
{
+ grub_ntfs_fs.mod = mod;
grub_fs_register (&grub_ntfs_fs);
my_mod = mod;
}
diff --git a/grub-core/fs/odc.c b/grub-core/fs/odc.c
index 790000622d..8e4e8aeac8 100644
--- a/grub-core/fs/odc.c
+++ b/grub-core/fs/odc.c
@@ -52,6 +52,7 @@ read_number (const char *str, grub_size_t size)
GRUB_MOD_INIT (odc)
{
+ grub_cpio_fs.mod = mod;
grub_fs_register (&grub_cpio_fs);
}
diff --git a/grub-core/fs/proc.c b/grub-core/fs/proc.c
index 5f516502d4..bcde433495 100644
--- a/grub-core/fs/proc.c
+++ b/grub-core/fs/proc.c
@@ -192,6 +192,7 @@ static struct grub_fs grub_procfs_fs =
GRUB_MOD_INIT (procfs)
{
+ grub_procfs_fs.mod = mod;
grub_disk_dev_register (&grub_procfs_dev);
grub_fs_register (&grub_procfs_fs);
}
diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c
index 36b26ac98a..c3850e0138 100644
--- a/grub-core/fs/reiserfs.c
+++ b/grub-core/fs/reiserfs.c
@@ -1417,6 +1417,7 @@ static struct grub_fs grub_reiserfs_fs =
GRUB_MOD_INIT(reiserfs)
{
+ grub_reiserfs_fs.mod = mod;
grub_fs_register (&grub_reiserfs_fs);
my_mod = mod;
}
diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c
index 1f7dcfca1d..56b0b2b2f3 100644
--- a/grub-core/fs/romfs.c
+++ b/grub-core/fs/romfs.c
@@ -475,6 +475,7 @@ static struct grub_fs grub_romfs_fs =
GRUB_MOD_INIT(romfs)
{
+ grub_romfs_fs.mod = mod;
grub_fs_register (&grub_romfs_fs);
}
diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c
index 983e880088..f0d7cac435 100644
--- a/grub-core/fs/sfs.c
+++ b/grub-core/fs/sfs.c
@@ -779,6 +779,7 @@ static struct grub_fs grub_sfs_fs =
GRUB_MOD_INIT(sfs)
{
+ grub_sfs_fs.mod = mod;
grub_fs_register (&grub_sfs_fs);
my_mod = mod;
}
diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c
index a30e6ebe14..6e9d63874c 100644
--- a/grub-core/fs/squash4.c
+++ b/grub-core/fs/squash4.c
@@ -1044,6 +1044,7 @@ static struct grub_fs grub_squash_fs =
GRUB_MOD_INIT(squash4)
{
+ grub_squash_fs.mod = mod;
grub_fs_register (&grub_squash_fs);
}
diff --git a/grub-core/fs/tar.c b/grub-core/fs/tar.c
index a9e39b0eb6..a608ac9c9f 100644
--- a/grub-core/fs/tar.c
+++ b/grub-core/fs/tar.c
@@ -349,6 +349,7 @@ static struct grub_fs grub_cpio_fs = {
GRUB_MOD_INIT (tar)
{
+ grub_cpio_fs.mod = mod;
grub_fs_register (&grub_cpio_fs);
}
diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c
index b836e61075..8765c633c6 100644
--- a/grub-core/fs/udf.c
+++ b/grub-core/fs/udf.c
@@ -1455,6 +1455,7 @@ static struct grub_fs grub_udf_fs = {
GRUB_MOD_INIT (udf)
{
+ grub_udf_fs.mod = mod;
grub_fs_register (&grub_udf_fs);
my_mod = mod;
}
diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c
index 01235101b4..e82d9356d7 100644
--- a/grub-core/fs/ufs.c
+++ b/grub-core/fs/ufs.c
@@ -899,6 +899,7 @@ GRUB_MOD_INIT(ufs1)
#endif
#endif
{
+ grub_ufs_fs.mod = mod;
grub_fs_register (&grub_ufs_fs);
my_mod = mod;
}
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
index 1ce5fa4fc4..c17e54e447 100644
--- a/grub-core/fs/xfs.c
+++ b/grub-core/fs/xfs.c
@@ -1281,6 +1281,7 @@ static struct grub_fs grub_xfs_fs =
GRUB_MOD_INIT(xfs)
{
+ grub_xfs_fs.mod = mod;
grub_fs_register (&grub_xfs_fs);
my_mod = mod;
}
diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
index b5453e0062..a497b18695 100644
--- a/grub-core/fs/zfs/zfs.c
+++ b/grub-core/fs/zfs/zfs.c
@@ -4424,6 +4424,7 @@ static struct grub_fs grub_zfs_fs = {
GRUB_MOD_INIT (zfs)
{
COMPILE_TIME_ASSERT (sizeof (zap_leaf_chunk_t) == ZAP_LEAF_CHUNKSIZE);
+ grub_zfs_fs.mod = mod;
grub_fs_register (&grub_zfs_fs);
#ifndef GRUB_UTIL
my_mod = mod;
diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c
index e990507fca..6e7efe89ab 100644
--- a/grub-core/kern/file.c
+++ b/grub-core/kern/file.c
@@ -25,6 +25,7 @@
#include <grub/fs.h>
#include <grub/device.h>
#include <grub/i18n.h>
+#include <grub/dl.h>
void (*EXPORT_VAR (grub_grubnet_fini)) (void);
@@ -117,6 +118,9 @@ grub_file_open (const char *name, enum grub_file_type type)
if (file->data == NULL)
goto fail;
+ if (file->fs->mod)
+ grub_dl_ref (file->fs->mod);
+
file->name = grub_strdup (name);
grub_errno = GRUB_ERR_NONE;
@@ -197,6 +201,9 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len)
grub_err_t
grub_file_close (grub_file_t file)
{
+ if (file->fs->mod)
+ grub_dl_unref (file->fs->mod);
+
if (file->fs->fs_close)
(file->fs->fs_close) (file);
diff --git a/include/grub/fs.h b/include/grub/fs.h
index 4c380e3341..9c8206133d 100644
--- a/include/grub/fs.h
+++ b/include/grub/fs.h
@@ -23,6 +23,7 @@
#include <grub/device.h>
#include <grub/symbol.h>
#include <grub/types.h>
+#include <grub/dl.h>
#include <grub/list.h>
/* For embedding types. */
@@ -57,6 +58,9 @@ struct grub_fs
/* My name. */
const char *name;
+ /* My module */
+ grub_dl_t mod;
+
/* Call HOOK with each file under DIR. */
grub_err_t (*fs_dir) (grub_device_t device, const char *path,
grub_fs_dir_hook_t hook, void *hook_data);
--
2.48.1

View File

@@ -1,23 +0,0 @@
From 6811f6f09d61996a3acbc4fc0414e45964f0e2d9 Mon Sep 17 00:00:00 2001
From: Stefan Berger <stefanb@linux.ibm.com>
Date: Tue, 26 Nov 2024 15:39:46 -0500
Subject: [PATCH 7/7] tpm2_key_protector: Enable build for powerpc_ieee1275
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/Makefile.core.def | 1 +
1 file changed, 1 insertion(+)
Index: grub-2.12/grub-core/Makefile.core.def
===================================================================
--- grub-2.12.orig/grub-core/Makefile.core.def
+++ grub-2.12/grub-core/Makefile.core.def
@@ -2645,6 +2645,7 @@ module = {
/* The plaform support of tpm2_key_protector depends on the tcg2 implementation in tss2. */
enable = efi;
enable = emu;
+ enable = powerpc_ieee1275;
cppflags = '-I$(srcdir)/lib/tss2';
};

View File

@@ -1,579 +0,0 @@
From 5934bf51cbdf820c71eeed4bbbbcf23756e96217 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Mon, 7 Apr 2025 16:29:21 +0800
Subject: [PATCH 7/7] util/grub-protect: Support NV index mode
This commit implements the missing NV index mode support in grub-protect.
NV index mode stores the sealed key in the TPM non-volatile memory (NVRAM)
instead of a file. There are two supported types of TPM handles.
1. Persistent handle (0x81000000~0x81FFFFFF)
Only the raw format is supported due to the limitation of persistent
handles. This grub-protect command seals the key into the
persistent handle 0x81000000.
# grub-protect \
--protector=tpm2 \
--action=add \
--tpm2-bank=sha256 \
--tpm2-pcrs=7,11 \
--tpm2-keyfile=luks-key \
--tpm2-nvindex=0x81000000
2. NV index handle (0x1000000~0x1FFFFFF)
Both TPM 2.0 Key File format and the raw format are supported by NV
index handles. Here is the grub-protect command to seal the key in
TPM 2.0 Key File format into the NV index handle 0x1000000.
# grub-protect \
--protector=tpm2 \
--action=add \
--tpm2key \
--tpm2-bank=sha256 \
--tpm2-pcrs=7,11 \
--tpm2-keyfile=luks-key \
--tpm2-nvindex=0x1000000
Besides the "add" action, the corresponding "remove" action is also
introduced. To remove the data from a persistent or NV index handle,
just use "--tpm2-nvindex=HANDLE" combining with "--tpm2-evict". This
sample command removes the data from the NV index handle 0x1000000.
# grub-protect \
--protector=tpm2 \
--action=remove \
--tpm2-evict \
--tpm2-nvindex=0x1000000
Also set and check the boolean variables with true/false instead of 1/0.
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
util/grub-protect.c | 343 ++++++++++++++++++++++++++++++++++++--------
1 file changed, 287 insertions(+), 56 deletions(-)
diff --git a/util/grub-protect.c b/util/grub-protect.c
index 5b7e952f4..40d4a3fc5 100644
--- a/util/grub-protect.c
+++ b/util/grub-protect.c
@@ -61,7 +61,8 @@ typedef enum protect_opt
PROTECT_OPT_TPM2_KEYFILE,
PROTECT_OPT_TPM2_OUTFILE,
PROTECT_OPT_TPM2_EVICT,
- PROTECT_OPT_TPM2_TPM2KEY
+ PROTECT_OPT_TPM2_TPM2KEY,
+ PROTECT_OPT_TPM2_NVINDEX,
} protect_opt_t;
/* Option flags to keep track of specified arguments */
@@ -79,7 +80,8 @@ typedef enum protect_arg
PROTECT_ARG_TPM2_KEYFILE = 1 << 7,
PROTECT_ARG_TPM2_OUTFILE = 1 << 8,
PROTECT_ARG_TPM2_EVICT = 1 << 9,
- PROTECT_ARG_TPM2_TPM2KEY = 1 << 10
+ PROTECT_ARG_TPM2_TPM2KEY = 1 << 10,
+ PROTECT_ARG_TPM2_NVINDEX = 1 << 11
} protect_arg_t;
typedef enum protect_protector
@@ -111,6 +113,7 @@ typedef struct protect_args
const char *tpm2_outfile;
bool tpm2_evict;
bool tpm2_tpm2key;
+ TPM_HANDLE_t tpm2_nvindex;
} protect_args_t;
static struct argp_option protect_options[] =
@@ -224,6 +227,15 @@ static struct argp_option protect_options[] =
N_("Use TPM 2.0 Key File format."),
.group = 0
},
+ {
+ .name = "tpm2-nvindex",
+ .key = PROTECT_OPT_TPM2_NVINDEX,
+ .arg = "NUM",
+ .flags = 0,
+ .doc =
+ N_("Store the sealed key in a persistent or NV index handle."),
+ .group = 0
+ },
/* End of list */
{ 0, 0, 0, 0, 0, 0 }
};
@@ -668,8 +680,8 @@ extern asn1_static_node tpm2key_asn1_tab[];
#define TPM2KEY_SEALED_KEY_OID "2.23.133.10.1.5"
static grub_err_t
-protect_tpm2_export_tpm2key (const protect_args_t *args,
- tpm2_sealed_key_t *sealed_key)
+protect_tpm2_export_tpm2key (const protect_args_t *args, tpm2_sealed_key_t *sealed_key,
+ void **der_buf, int *der_buf_size)
{
const char *sealed_key_oid = TPM2KEY_SEALED_KEY_OID;
asn1_node asn1_def = NULL;
@@ -689,12 +701,13 @@ protect_tpm2_export_tpm2key (const protect_args_t *args,
};
struct grub_tpm2_buffer pub_buf;
struct grub_tpm2_buffer priv_buf;
- void *der_buf = NULL;
- int der_buf_size = 0;
int i;
int ret;
grub_err_t err;
+ if (der_buf == NULL)
+ return GRUB_ERR_BAD_ARGUMENT;
+
for (i = 0; i < args->tpm2_pcr_count; i++)
TPMS_PCR_SELECTION_SelectPCR (&pcr_sel.pcrSelections[0], args->tpm2_pcrs[i]);
@@ -844,8 +857,8 @@ protect_tpm2_export_tpm2key (const protect_args_t *args,
}
/* Create the DER binary */
- der_buf_size = 0;
- ret = asn1_der_coding (tpm2key, "", NULL, &der_buf_size, NULL);
+ *der_buf_size = 0;
+ ret = asn1_der_coding (tpm2key, "", NULL, der_buf_size, NULL);
if (ret != ASN1_MEM_ERROR)
{
fprintf (stderr, "Failed to get DER size: 0x%x\n", ret);
@@ -853,15 +866,15 @@ protect_tpm2_export_tpm2key (const protect_args_t *args,
goto error;
}
- der_buf = grub_malloc (der_buf_size);
- if (der_buf == NULL)
+ *der_buf = grub_malloc (*der_buf_size);
+ if (*der_buf == NULL)
{
fprintf (stderr, "Failed to allocate memory for DER encoding\n");
err = GRUB_ERR_OUT_OF_MEMORY;
goto error;
}
- ret = asn1_der_coding (tpm2key, "", der_buf, &der_buf_size, NULL);
+ ret = asn1_der_coding (tpm2key, "", *der_buf, der_buf_size, NULL);
if (ret != ASN1_SUCCESS)
{
fprintf (stderr, "DER coding error: 0x%x\n", ret);
@@ -869,13 +882,7 @@ protect_tpm2_export_tpm2key (const protect_args_t *args,
goto error;
}
- err = protect_write_file (args->tpm2_outfile, der_buf, der_buf_size);
- if (err != GRUB_ERR_NONE)
- fprintf (stderr, N_("Could not write tpm2key file (%s).\n"), strerror (errno));
-
error:
- grub_free (der_buf);
-
if (tpm2key)
asn1_delete_structure (&tpm2key);
@@ -883,10 +890,8 @@ protect_tpm2_export_tpm2key (const protect_args_t *args,
}
static grub_err_t
-protect_tpm2_export_sealed_key (const char *filepath,
- tpm2_sealed_key_t *sealed_key)
+protect_tpm2_export_raw (tpm2_sealed_key_t *sealed_key, void **out_buf, int *out_buf_size)
{
- grub_err_t err;
struct grub_tpm2_buffer buf;
grub_tpm2_buffer_init (&buf);
@@ -896,13 +901,98 @@ protect_tpm2_export_sealed_key (const char *filepath,
if (buf.error != 0)
return GRUB_ERR_BAD_ARGUMENT;
- err = protect_write_file (filepath, buf.data, buf.size);
- if (err != GRUB_ERR_NONE)
- fprintf (stderr, N_("Could not write sealed key file (%s).\n"), strerror (errno));
+ *out_buf_size = buf.size;
+ *out_buf = grub_malloc (buf.size);
+
+ if (*out_buf == NULL)
+ {
+ fprintf (stderr, N_("Could not allocate memory for the raw format key.\n"));
+ return GRUB_ERR_OUT_OF_MEMORY;
+ }
+
+ grub_memcpy (*out_buf, buf.data, buf.size);
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+protect_tpm2_export_persistent (protect_args_t *args,
+ TPM_HANDLE_t srk_handle,
+ tpm2_sealed_key_t *sealed_key)
+{
+ TPMS_AUTH_COMMAND_t authCmd = {0};
+ TPM2B_NAME_t name = {0};
+ TPM_HANDLE_t sealed_handle;
+ TPM_RC_t rc;
+ grub_err_t err = GRUB_ERR_NONE;
+
+ /* Load the sealed key and associate it with the SRK */
+ authCmd.sessionHandle = TPM_RS_PW;
+ rc = grub_tpm2_load (srk_handle, &authCmd, &sealed_key->private, &sealed_key->public,
+ &sealed_handle, &name, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ fprintf (stderr, "Failed to load sealed key (TPM2_Load: %x).\n", rc);
+ return GRUB_ERR_BAD_DEVICE;
+ }
+
+ /* Make the sealed key object persistent */
+ authCmd.sessionHandle = TPM_RS_PW;
+ rc = grub_tpm2_evictcontrol (TPM_RH_OWNER, sealed_handle, &authCmd, args->tpm2_nvindex, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ fprintf (stderr, "Failed to make sealed key persistent with handle 0x%x (TPM2_EvictControl: 0x%x).\n", args->tpm2_nvindex, rc);
+ err = GRUB_ERR_BAD_DEVICE;
+ goto exit;
+ }
+
+ exit:
+ grub_tpm2_flushcontext (sealed_handle);
return err;
}
+static grub_err_t
+protect_tpm2_export_nvindex (protect_args_t *args, void *data, int data_size)
+{
+ TPMS_AUTH_COMMAND_t authCmd = {0};
+ TPM2B_NV_PUBLIC_t pub_info = {0};
+ TPM2B_MAX_NV_BUFFER_t nv_data = {0};
+ TPM_RC_t rc;
+
+ if (data_size > TPM_MAX_NV_BUFFER_SIZE || data_size < 0)
+ {
+ fprintf (stderr, N_("Invalid tpm2key size for TPM NV buffer\n"));
+ return GRUB_ERR_OUT_OF_RANGE;
+ }
+
+ pub_info.nvPublic.nvIndex = args->tpm2_nvindex;
+ pub_info.nvPublic.nameAlg = TPM_ALG_SHA256;
+ pub_info.nvPublic.attributes = TPMA_NV_OWNERWRITE | TPMA_NV_OWNERREAD;
+ pub_info.nvPublic.dataSize = (grub_uint16_t) data_size;
+
+ authCmd.sessionHandle = TPM_RS_PW;
+ rc = grub_tpm2_nv_definespace (TPM_RH_OWNER, &authCmd, NULL, &pub_info);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ fprintf (stderr, "Failed to define NV space for 0x%x (TPM2_NV_DefineSpace: 0x%x)\n", args->tpm2_nvindex, rc);
+ return GRUB_ERR_BAD_DEVICE;
+ }
+
+ authCmd.sessionHandle = TPM_RS_PW;
+ grub_memcpy (nv_data.buffer, data, data_size);
+ nv_data.size = (grub_uint16_t) data_size;
+
+ rc = grub_tpm2_nv_write (TPM_RH_OWNER, args->tpm2_nvindex, &authCmd, &nv_data, 0);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ fprintf (stderr, "Failed to write data into 0x%x (TPM2_NV_Write: 0x%x)\n", args->tpm2_nvindex, rc);
+ return GRUB_ERR_BAD_DEVICE;
+ }
+
+ return GRUB_ERR_NONE;
+}
+
static grub_err_t
protect_tpm2_add (protect_args_t *args)
{
@@ -911,6 +1001,8 @@ protect_tpm2_add (protect_args_t *args)
grub_size_t key_size;
TPM_HANDLE_t srk;
TPM2B_DIGEST_t policy_digest;
+ void *out_buf = NULL;
+ int out_buf_size;
tpm2_sealed_key_t sealed_key;
err = protect_tpm2_open_device (args->tpm2_device);
@@ -940,15 +1032,51 @@ protect_tpm2_add (protect_args_t *args)
if (err != GRUB_ERR_NONE)
goto exit3;
- if (args->tpm2_tpm2key != 0)
- err = protect_tpm2_export_tpm2key (args, &sealed_key);
+ if (args->tpm2_tpm2key == true)
+ {
+ err = protect_tpm2_export_tpm2key (args, &sealed_key, &out_buf, &out_buf_size);
+ if (err != GRUB_ERR_NONE)
+ {
+ fprintf (stderr, N_("Could not export to TPM 2.0 Key File format\n"));
+ goto exit3;
+ }
+ }
else
- err = protect_tpm2_export_sealed_key (args->tpm2_outfile, &sealed_key);
- if (err != GRUB_ERR_NONE)
- goto exit3;
+ {
+ err = protect_tpm2_export_raw (&sealed_key, &out_buf, &out_buf_size);
+ if (err != GRUB_ERR_NONE)
+ {
+ fprintf (stderr, N_("Could not export to the raw format\n"));
+ goto exit3;
+ }
+ }
+
+ if (args->tpm2_outfile != NULL)
+ {
+ err = protect_write_file (args->tpm2_outfile, out_buf, out_buf_size);
+ if (err != GRUB_ERR_NONE)
+ {
+ fprintf (stderr, N_("Could not write key file (%s).\n"), strerror (errno));
+ goto exit3;
+ }
+ }
+
+ if (TPM_HT_IS_NVINDEX (args->tpm2_nvindex) == true)
+ {
+ err = protect_tpm2_export_nvindex (args, out_buf, out_buf_size);
+ if (err != GRUB_ERR_NONE)
+ goto exit3;
+ }
+ else if (TPM_HT_IS_PERSISTENT (args->tpm2_nvindex) == true)
+ {
+ err = protect_tpm2_export_persistent (args, srk, &sealed_key);
+ if (err != GRUB_ERR_NONE)
+ goto exit3;
+ }
exit3:
grub_tpm2_flushcontext (srk);
+ grub_free (out_buf);
exit2:
grub_free (key);
@@ -960,14 +1088,66 @@ protect_tpm2_add (protect_args_t *args)
}
static grub_err_t
-protect_tpm2_remove (protect_args_t *args)
+protect_tpm2_evict (TPM_HANDLE_t handle)
{
TPM_RC_t rc;
TPM2B_PUBLIC_t public;
- TPMS_AUTH_COMMAND_t authCommand = {0};
+ TPMS_AUTH_COMMAND_t authCmd = {0};
+
+ /* Find the persistent handle */
+ rc = grub_tpm2_readpublic (handle, NULL, &public);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ fprintf (stderr, "Handle 0x%x not found.\n", handle);
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
+
+ /* Evict the persistent handle */
+ authCmd.sessionHandle = TPM_RS_PW;
+ rc = grub_tpm2_evictcontrol (TPM_RH_OWNER, handle, &authCmd, handle, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ fprintf (stderr, "Failed to evict handle 0x%x (TPM2_EvictControl: 0x%x).\n", handle, rc);
+ return GRUB_ERR_BAD_DEVICE;
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+protect_tpm2_nv_undefine (TPM_HANDLE_t handle)
+{
+ TPM_RC_t rc;
+ TPM2B_NV_PUBLIC_t nv_public;
+ TPMS_AUTH_COMMAND_t authCmd = {0};
+ TPM2B_NAME_t nv_name;
+
+ /* Find the nvindex handle */
+ rc = grub_tpm2_nv_readpublic (handle, NULL, &nv_public, &nv_name);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ fprintf (stderr, "Handle 0x%x not found.\n", handle);
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
+
+ /* Undefine the nvindex handle */
+ authCmd.sessionHandle = TPM_RS_PW;
+ rc = grub_tpm2_nv_undefinespace (TPM_RH_OWNER, handle, &authCmd);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ fprintf (stderr, "Failed to undefine handle 0x%x (TPM2_NV_UndefineSpace: 0x%x).\n", handle, rc);
+ return GRUB_ERR_BAD_DEVICE;
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+protect_tpm2_remove (protect_args_t *args)
+{
grub_err_t err;
- if (args->tpm2_evict == 0)
+ if (args->tpm2_evict == false)
{
printf ("--tpm2-evict not specified, nothing to do.\n");
return GRUB_ERR_NONE;
@@ -977,35 +1157,41 @@ protect_tpm2_remove (protect_args_t *args)
if (err != GRUB_ERR_NONE)
return err;
- /* Find SRK */
- rc = grub_tpm2_readpublic (args->tpm2_srk, NULL, &public);
- if (rc != TPM_RC_SUCCESS)
+ if (args->tpm2_srk != 0)
{
- fprintf (stderr, "SRK with handle 0x%x not found.\n", args->tpm2_srk);
- err = GRUB_ERR_BAD_ARGUMENT;
- goto exit1;
+ err = protect_tpm2_evict (args->tpm2_srk);
+ if (err != GRUB_ERR_NONE)
+ goto exit;
}
- /* Evict SRK */
- authCommand.sessionHandle = TPM_RS_PW;
-
- rc = grub_tpm2_evictcontrol (TPM_RH_OWNER, args->tpm2_srk, &authCommand, args->tpm2_srk, NULL);
- if (rc != TPM_RC_SUCCESS)
+ if (args->tpm2_nvindex != 0)
{
- fprintf (stderr, "Failed to evict SRK with handle 0x%x (TPM2_EvictControl: 0x%x).\n", args->tpm2_srk, rc);
- err = GRUB_ERR_BAD_DEVICE;
- goto exit2;
+ if (TPM_HT_IS_PERSISTENT (args->tpm2_nvindex) == true)
+ {
+ err = protect_tpm2_evict (args->tpm2_nvindex);
+ if (err != GRUB_ERR_NONE)
+ goto exit;
+ }
+ else if (TPM_HT_IS_NVINDEX (args->tpm2_nvindex) == true)
+ {
+ err = protect_tpm2_nv_undefine (args->tpm2_nvindex);
+ if (err != GRUB_ERR_NONE)
+ goto exit;
+ }
+ else
+ {
+ fprintf (stderr, "Unsupported handle 0x%x\n", args->tpm2_nvindex);
+ err = GRUB_ERR_BAD_ARGUMENT;
+ goto exit;
+ }
}
err = GRUB_ERR_NONE;
- exit2:
- grub_tpm2_flushcontext (args->tpm2_srk);
-
- exit1:
+ exit:
protect_tpm2_close_device ();
- return GRUB_ERR_NONE;
+ return err;
}
static grub_err_t
@@ -1045,9 +1231,36 @@ protect_tpm2_args_verify (protect_args_t *args)
return GRUB_ERR_BAD_ARGUMENT;
}
- if (args->tpm2_outfile == NULL)
+ if (args->tpm2_outfile == NULL && args->tpm2_nvindex == 0)
{
- fprintf (stderr, N_("--tpm2-outfile must be specified.\n"));
+ fprintf (stderr, N_("--tpm2-outfile or --tpm2-nvindex must be specified.\n"));
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
+
+ if (args->tpm2_nvindex != 0)
+ {
+ if (args->tpm2_tpm2key == true && TPM_HT_IS_PERSISTENT (args->tpm2_nvindex) == true)
+ {
+ fprintf (stderr, N_("Persistent handle does not support TPM 2.0 Key File format.\n"));
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
+
+ if (TPM_HT_IS_PERSISTENT (args->tpm2_nvindex) == false && TPM_HT_IS_NVINDEX (args->tpm2_nvindex) == false)
+ {
+ fprintf (stderr, N_("--tpm2-nvindex must be a persistent or NV index handle.\n"));
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
+
+ if (args->tpm2_nvindex == args->tpm2_srk)
+ {
+ fprintf (stderr, N_("--tpm2-nvindex and --tpm2-srk must be different.\n"));
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
+ }
+
+ if (args->tpm2_srk != 0 && TPM_HT_IS_PERSISTENT(args->tpm2_srk) == false)
+ {
+ fprintf (stderr, N_("--tpm2-srk must be a persistent handle, e.g. 0x81000000.\n"));
return GRUB_ERR_BAD_ARGUMENT;
}
@@ -1099,9 +1312,9 @@ protect_tpm2_args_verify (protect_args_t *args)
return GRUB_ERR_BAD_ARGUMENT;
}
- if (args->tpm2_srk == 0)
+ if (args->tpm2_srk == 0 && args->tpm2_nvindex == 0)
{
- fprintf (stderr, N_("--tpm2-srk is not specified when --action is 'remove'.\n"));
+ fprintf (stderr, N_("missing --tpm2-srk or --tpm2-nvindex for --action 'remove'.\n"));
return GRUB_ERR_BAD_ARGUMENT;
}
@@ -1274,7 +1487,7 @@ protect_argp_parser (int key, char *arg, struct argp_state *state)
return EINVAL;
}
- args->tpm2_evict = 1;
+ args->tpm2_evict = true;
args->args |= PROTECT_ARG_TPM2_EVICT;
break;
@@ -1285,10 +1498,28 @@ protect_argp_parser (int key, char *arg, struct argp_state *state)
return EINVAL;
}
- args->tpm2_tpm2key = 1;
+ args->tpm2_tpm2key = true;
args->args |= PROTECT_ARG_TPM2_TPM2KEY;
break;
+ case PROTECT_OPT_TPM2_NVINDEX:
+ if (args->args & PROTECT_ARG_TPM2_NVINDEX)
+ {
+ fprintf (stderr, N_("--tpm2-nvindex can only be specified once.\n"));
+ return EINVAL;
+ }
+
+ err = grub_tpm2_protector_parse_tpm_handle (arg, &args->tpm2_nvindex);
+ if (err != GRUB_ERR_NONE)
+ {
+ if (grub_errno != GRUB_ERR_NONE)
+ grub_print_error ();
+ return EINVAL;
+ }
+
+ args->args |= PROTECT_ARG_TPM2_NVINDEX;
+ break;
+
default:
return ARGP_ERR_UNKNOWN;
}
--
2.43.0

View File

@@ -1,688 +0,0 @@
From 964b7ef5695ac925e8cdcf3381d5cfb45dc5d140 Mon Sep 17 00:00:00 2001
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Date: Tue, 25 Feb 2025 02:33:17 +0530
Subject: [PATCH 8/9] appendedsig: The grub command's trusted and distrusted
support
To support the following trusted and distrusted commands
1. trusted_list:
It will show the list of trusted certificates and binary hashes
2. distrusted_list:
It will show the list of distrusted certificates and binary/certificate hashes
3. trusted_certificate:
It will add the trusted certificate to the trusted list
4. trusted_signature:
It will add the certificate/binary hash to the trusted list
5. distrusted_certificate:
It will remove the trusted certificate from trsuted list
6. distrusted_signature:
It will add the certificate/binary hash to the distrsuted list
Note:-
The addition/deletion of trusted certificates and binary hashes
are not allowed in grub command prompt while secure boot is enabled.
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
---
grub-core/commands/appendedsig/appendedsig.c | 545 ++++++++++++-------
1 file changed, 354 insertions(+), 191 deletions(-)
diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c
index 3cbe51ec13..6ccfdb4c6e 100644
--- a/grub-core/commands/appendedsig/appendedsig.c
+++ b/grub-core/commands/appendedsig/appendedsig.c
@@ -118,6 +118,36 @@ static enum
check_sigs_forced = 2
} check_sigs = check_sigs_no;
+enum
+{
+ OPTION_BINARY_HASH = 0,
+ OPTION_CERT_HASH = 1
+};
+
+static const struct grub_arg_option options[] =
+{
+ {"binary-hash", 'b', 0, N_("hash file of the binary."), 0, ARG_TYPE_NONE},
+ {"cert-hash", 'c', 1, N_("hash file of the certificate."), 0, ARG_TYPE_NONE},
+ {0, 0, 0, 0, 0, 0}
+};
+
+static void
+print_hex (const grub_uint8_t *data, const grub_size_t length)
+{
+ grub_size_t i, count = 0;
+ for (i = 0; i < length-1; i++)
+ {
+ grub_printf ("%02x:", data[i]);
+ count++;
+ if (count == 16)
+ {
+ grub_printf ("\n\t ");
+ count = 0;
+ }
+ }
+ grub_printf ("%02x\n", data[i]);
+}
+
/*
* GUID can be used to determine the hashing function and
* generate the hash using determined hashing function.
@@ -346,78 +376,6 @@ grub_env_write_sec (struct grub_env_var *var __attribute__((unused)),
return grub_strdup (grub_env_read_sec (NULL, NULL));
}
-static grub_err_t
-file_read_all (grub_file_t file, grub_uint8_t **buf, grub_size_t *len)
-{
- grub_off_t full_file_size;
- grub_size_t file_size, total_read_size = 0;
- grub_ssize_t read_size;
-
- full_file_size = grub_file_size (file);
- if (full_file_size == GRUB_FILE_SIZE_UNKNOWN)
- return grub_error (GRUB_ERR_BAD_ARGUMENT,
- N_("Cannot read a file of unknown size into a buffer"));
-
- if (full_file_size > GRUB_SIZE_MAX)
- return grub_error (GRUB_ERR_OUT_OF_RANGE,
- N_("File is too large to read: %" PRIuGRUB_UINT64_T
- " bytes"), full_file_size);
-
- file_size = (grub_size_t) full_file_size;
-
- *buf = grub_malloc (file_size);
- if (!*buf)
- return grub_error (GRUB_ERR_OUT_OF_MEMORY,
- N_("Could not allocate file data buffer size %"
- PRIuGRUB_SIZE), file_size);
-
- while (total_read_size < file_size)
- {
- read_size =
- grub_file_read (file, *buf + total_read_size,
- file_size - total_read_size);
-
- if (read_size < 0)
- {
- grub_free (*buf);
- return grub_errno;
- }
- else if (read_size == 0)
- {
- grub_free (*buf);
- return grub_error (GRUB_ERR_IO,
- N_("Could not read full file size (%"
- PRIuGRUB_SIZE "), only %" PRIuGRUB_SIZE
- " bytes read"), file_size, total_read_size);
- }
-
- total_read_size += read_size;
- }
- *len = file_size;
- return GRUB_ERR_NONE;
-}
-
-static grub_err_t
-read_cert_from_file (grub_file_t f, struct x509_certificate *certificate)
-{
- grub_err_t err;
- grub_uint8_t *buf;
- grub_size_t file_size;
-
- err = file_read_all (f, &buf, &file_size);
- if (err != GRUB_ERR_NONE)
- return err;
-
- err = parse_x509_certificate (buf, file_size, certificate);
- if (err != GRUB_ERR_NONE)
- {
- grub_free (buf);
- return err;
- }
-
- return GRUB_ERR_NONE;
-}
-
static grub_err_t
extract_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize,
struct grub_appended_signature *sig)
@@ -647,159 +605,351 @@ static grub_err_t
grub_cmd_verify_signature (grub_command_t cmd __attribute__((unused)),
int argc, char **args)
{
- grub_file_t f;
grub_err_t err = GRUB_ERR_NONE;
- grub_uint8_t *data;
- grub_size_t file_size;
+ grub_file_t signed_file = NULL;
+ grub_uint8_t *signed_data = NULL;
+ grub_ssize_t signed_data_size = 0;
- if (argc < 1)
- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
+ if (argc != 1)
+ {
+ grub_printf (N_("a signed file is expected\n"
+ "Example:\n\tverify_appended <SIGNED FILE>\n"));
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
grub_dprintf ("appendedsig", "verifying %s\n", args[0]);
- f = grub_file_open (args[0], GRUB_FILE_TYPE_VERIFY_SIGNATURE);
- if (!f)
+ signed_file = grub_file_open (args[0], GRUB_FILE_TYPE_VERIFY_SIGNATURE);
+ if (signed_file == NULL)
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("unable to open a signed file"));
+
+ err = grub_read_file (signed_file, &signed_data, &signed_data_size);
+ if (err != GRUB_ERR_NONE)
{
- err = grub_errno;
- goto cleanup;
+ grub_file_close (signed_file);
+ return err;
}
- err = file_read_all (f, &data, &file_size);
+ grub_file_close (signed_file);
+ err = grub_verify_appended_signature (signed_data, signed_data_size);
+ grub_free (signed_data);
+
+ return err;
+}
+
+static grub_err_t
+grub_cmd_trusted_list (grub_command_t cmd __attribute__((unused)),
+ int argc __attribute__((unused)), char **args __attribute__((unused)))
+{
+ struct x509_certificate *cert = NULL;
+ grub_size_t i = 0, cert_num = 1;
+
+ for (cert = db.keys; cert; cert = cert->next)
+ {
+ grub_printf (N_("trusted certificate %" PRIuGRUB_SIZE ":\n"), cert_num);
+ grub_printf (N_("\tserial: "));
+
+ for (i = 0; i < cert->serial_len - 1; i++)
+ grub_printf ("%02x:", cert->serial[i]);
+
+ grub_printf ("%02x\n", cert->serial[cert->serial_len - 1]);
+ grub_printf ("\tCN: %s\n\n", cert->subject);
+ cert_num++;
+
+ }
+
+ for (i = 0; i < db.signature_entries; i++)
+ {
+ grub_printf (N_("trusted binary hash %" PRIuGRUB_SIZE ":\n"), i+1);
+ grub_printf (N_("\thash: "));
+ print_hex (db.signatures[i], db.signature_size[i]);
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_distrusted_list (grub_command_t cmd __attribute__((unused)),
+ int argc __attribute__((unused)),
+ char **args __attribute__((unused)))
+{
+ struct x509_certificate *cert = NULL;
+ grub_size_t i = 0, cert_num = 1;
+
+ for (cert = dbx.keys; cert; cert = cert->next)
+ {
+ grub_printf (N_("distrusted certificate %" PRIuGRUB_SIZE ":\n"), cert_num);
+ grub_printf (N_("\tserial: "));
+
+ for (i = 0; i < cert->serial_len - 1; i++)
+ grub_printf ("%02x:", cert->serial[i]);
+
+ grub_printf ("%02x\n", cert->serial[cert->serial_len - 1]);
+ grub_printf ("\tCN: %s\n\n", cert->subject);
+ cert_num++;
+ }
+
+ for (i = 0; i < dbx.signature_entries; i++)
+ {
+ grub_printf (N_("distrusted certificate/binary hash %" PRIuGRUB_SIZE ":\n"), i+1);
+ grub_printf (N_("\thash: "));
+ print_hex (dbx.signatures[i], dbx.signature_size[i]);
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_trusted_cert (grub_command_t cmd __attribute__((unused)),
+ int argc, char **args)
+{
+ grub_err_t err = GRUB_ERR_NONE;
+ grub_file_t cert_file = NULL;
+ grub_uint8_t *cert_data = NULL;
+ grub_ssize_t cert_data_size = 0;
+
+ if (argc != 1)
+ {
+ grub_printf (N_("a trusted X.509 certificate file is expected\n"
+ "Example:\n\ttrusted_certificate <CERT FILE>\n"));
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
+
+ if (check_sigs == check_sigs_forced)
+ {
+ grub_printf ("Warning: since secure boot is enabled, "
+ "adding of trusted X.509 certificate is not permitted!\n");
+ return grub_errno;
+ }
+
+ if (grub_strlen (args[0]) == 0)
+ return grub_error (GRUB_ERR_BAD_FILENAME,
+ N_("missing trusted X.509 certificate file"));
+
+ cert_file = grub_file_open (args[0], GRUB_FILE_TYPE_CERTIFICATE_TRUST |
+ GRUB_FILE_TYPE_NO_DECOMPRESS);
+ if (cert_file == NULL)
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND,
+ N_("unable to open the trusted X.509 certificate file"));
+
+ err = grub_read_file (cert_file, &cert_data, &cert_data_size);
if (err != GRUB_ERR_NONE)
- goto cleanup;
+ {
+ grub_file_close (cert_file);
+ return err;
+ }
- err = grub_verify_appended_signature (data, file_size);
+ grub_file_close (cert_file);
+ err = add_certificate (cert_data, cert_data_size, &db, 1);
+ if (err != GRUB_ERR_NONE)
+ {
+ free_trusted_list ();
+ free_distrusted_list ();
+ grub_error (err, "adding of trusted certificate failed");
+ }
- grub_free (data);
+ grub_free (cert_data);
-cleanup:
- if (f)
- grub_file_close (f);
return err;
}
static grub_err_t
-grub_cmd_distrust (grub_command_t cmd __attribute__((unused)),
- int argc, char **args)
+grub_cmd_trusted_hash (grub_command_t cmd __attribute__((unused)), int argc, char**args)
{
- unsigned long cert_num, i;
- struct x509_certificate *cert, *prev;
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_file_t hash_file = NULL;
+ grub_uint8_t *hash_data = NULL;
+ grub_ssize_t hash_data_size = 0;
if (argc != 1)
- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("One argument expected"));
+ {
+ grub_printf (N_("a trusted binary hash file is expected\n"
+ "Example:\n\ttrusted_signature <BINARY HASH FILE>\n"));
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
- grub_errno = GRUB_ERR_NONE;
- cert_num = grub_strtoul (args[0], NULL, 10);
- if (grub_errno != GRUB_ERR_NONE)
- return grub_errno;
+ if (check_sigs == check_sigs_forced)
+ {
+ grub_printf ("Warning: since secure boot is enabled, "
+ "adding of trusted binary hash is not permitted!\n");
+ return grub_errno;
+ }
- if (cert_num < 1)
- return grub_error (GRUB_ERR_BAD_ARGUMENT,
- N_("Certificate number too small - numbers start at 1"));
+ if (grub_strlen (args[0]) == 0)
+ return grub_error (GRUB_ERR_BAD_FILENAME, N_("missing trusted binary hash file"));
- if (cert_num == 1)
- {
- cert = db.keys;
- db.keys = cert->next;
+ hash_file = grub_file_open (args[0], GRUB_FILE_TYPE_TO_HASH | GRUB_FILE_TYPE_NO_DECOMPRESS);
+ if (hash_file == NULL)
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND,
+ N_("unable to open the trusted binary hash file"));
- certificate_release (cert);
- grub_free (cert);
- return GRUB_ERR_NONE;
+ rc = grub_read_file (hash_file, &hash_data, &hash_data_size);
+ if (rc != GRUB_ERR_NONE)
+ {
+ grub_file_close (hash_file);
+ return rc;
}
- i = 2;
- prev = db.keys;
- cert = db.keys->next;
- while (cert)
+
+ grub_file_close (hash_file);
+
+ grub_dprintf ("appendedsig", "adding a trusted binary hash %s\n with size of %" PRIuGRUB_SIZE "\n",
+ hash_data, hash_data_size);
+
+ /* only accept SHA256, SHA384 and SHA512 binary hash */
+ if (hash_data_size != 32 && hash_data_size != 48 && hash_data_size != 64)
+ return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("unacceptable trusted binary hash type"));
+
+ rc = add_hash ((const grub_uint8_t **) &hash_data, hash_data_size, &db.signatures,
+ &db.signature_size, &db.signature_entries);
+ if (rc != GRUB_ERR_NONE)
{
- if (i == cert_num)
- {
- prev->next = cert->next;
- certificate_release (cert);
- grub_free (cert);
- return GRUB_ERR_NONE;
- }
- i++;
- prev = cert;
- cert = cert->next;
+ free_trusted_list ();
+ free_distrusted_list ();
+ grub_error (rc, "adding of trusted binary hash failed");
}
- return grub_error (GRUB_ERR_BAD_ARGUMENT,
- N_("No certificate number %lu found - only %lu certificates in the store"),
- cert_num, i - 1);
+ grub_free (hash_data);
+
+ return rc;
}
static grub_err_t
-grub_cmd_trust (grub_command_t cmd __attribute__((unused)),
- int argc, char **args)
+grub_cmd_distrusted_cert (grub_command_t cmd __attribute__((unused)), int argc, char **args)
{
- grub_file_t certf;
- struct x509_certificate *cert = NULL;
- grub_err_t err;
+ grub_size_t cert_num = 0, i = 1;
+ struct x509_certificate *current_cert = db.keys;
+ struct x509_certificate *previous_cert = db.keys;
if (argc != 1)
- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
+ {
+ grub_printf (N_("trusted certificate number is expected\n"
+ "Example:\n\tdistrusted_certificate <CERT_NUMER>\n"));
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
- certf = grub_file_open (args[0],
- GRUB_FILE_TYPE_CERTIFICATE_TRUST
- | GRUB_FILE_TYPE_NO_DECOMPRESS);
- if (!certf)
- return grub_errno;
+ if (check_sigs == check_sigs_forced)
+ {
+ grub_printf ("Warning: since secure boot is enabled, "
+ "removing of trusted certificate is not permitted!\n");
+ return grub_errno;
+ }
+ cert_num = grub_strtoul (args[0], NULL, 10);
+ if (cert_num < 1)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("trusted certificate number should to begin with 1"));
- cert = grub_zalloc (sizeof (struct x509_certificate));
- if (!cert)
- return grub_error (GRUB_ERR_OUT_OF_MEMORY,
- N_("Could not allocate memory for certificate"));
+ if (cert_num > db.key_entries)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("trusted certificate number should not exceed %" PRIuGRUB_SIZE ""),
+ db.key_entries);
+ else if (cert_num < db.key_entries)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("there is no certificate on the trusted list. so, not permitted"));
- err = read_cert_from_file (certf, cert);
- grub_file_close (certf);
- if (err != GRUB_ERR_NONE)
+ for (i = 1; i < db.key_entries; i++)
{
- grub_free (cert);
- return err;
+ if (cert_num == 1)
+ {
+ previous_cert = current_cert->next;
+ break;
+ }
+ else if (cert_num == i)
+ {
+ previous_cert->next = current_cert->next;
+ break;
+ }
+
+ previous_cert = current_cert;
+ current_cert = current_cert->next;
}
- grub_dprintf ("appendedsig", "Loaded certificate with CN: %s\n",
- cert->subject);
- cert->next = db.keys;
- db.keys = cert;
+ certificate_release (current_cert);
+ grub_free (current_cert);
return GRUB_ERR_NONE;
}
static grub_err_t
-grub_cmd_list (grub_command_t cmd __attribute__((unused)),
- int argc __attribute__((unused)),
- char **args __attribute__((unused)))
+grub_cmd_distrusted_hash (grub_extcmd_context_t ctxt, int argc, char **args)
{
- struct x509_certificate *cert;
- int cert_num = 1;
- grub_size_t i;
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_file_t hash_file = NULL;
+ grub_uint8_t *hash_data = NULL;
+ grub_ssize_t hash_data_size = 0;
- for (cert = db.keys; cert; cert = cert->next)
+ if (argc != 2)
{
- grub_printf (N_("Certificate %d:\n"), cert_num);
+ grub_printf (N_("a distrusted certificate/binary hash file is expected\n"
+ "Example:\n\tdistrusted_signature [option] <FILE>\n"
+ "option:\n[-b|--binary-hash] FILE [BINARY HASH FILE]\n"
+ "[-c|--cert-hash] FILE [CERTFICATE HASH FILE]\n"));
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
- grub_printf (N_("\tSerial: "));
- for (i = 0; i < cert->serial_len - 1; i++)
- {
- grub_printf ("%02x:", cert->serial[i]);
- }
- grub_printf ("%02x\n", cert->serial[cert->serial_len - 1]);
+ if (check_sigs == check_sigs_forced)
+ {
+ grub_printf ("Warning: since secure boot is enabled, "
+ "adding of distrusted certificate/binary hash is not permitted!\n");
+ return grub_errno;
+ }
- grub_printf ("\tCN: %s\n\n", cert->subject);
- cert_num++;
+ if (!ctxt->state[OPTION_BINARY_HASH].set && !ctxt->state[OPTION_CERT_HASH].set)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("missing options and use --help to konw"));
+
+ if (grub_strlen (args[1]) == 0)
+ return grub_error (GRUB_ERR_BAD_FILENAME,
+ N_("missing distrusted certificate/binary hash file"));
+
+ hash_file = grub_file_open (args[1], GRUB_FILE_TYPE_TO_HASH | GRUB_FILE_TYPE_NO_DECOMPRESS);
+ if (hash_file == NULL)
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND,
+ N_("unable to open the distrusted certificate/binary hash file"));
+ rc = grub_read_file (hash_file, &hash_data, &hash_data_size);
+ if (rc != GRUB_ERR_NONE)
+ {
+ grub_file_close (hash_file);
+ return rc;
}
- return GRUB_ERR_NONE;
+ grub_file_close (hash_file);
+
+ grub_dprintf ("appendedsig", "adding a distrusted certificate/binary hash %s\n"
+ " with size of %" PRIuGRUB_SIZE "\n", hash_data, hash_data_size);
+
+ if (ctxt->state[OPTION_BINARY_HASH].set)
+ {
+ /* only accept SHA256, SHA384 and SHA512 binary hash */
+ if (hash_data_size != 32 && hash_data_size != 48 && hash_data_size != 64)
+ return grub_error (GRUB_ERR_BAD_SIGNATURE,
+ N_("unacceptable distrusted binary hash type"));
+ }
+ else if (ctxt->state[OPTION_CERT_HASH].set)
+ {
+ /* only accept SHA256, SHA384 and SHA512 certificate hash */
+ if (hash_data_size != 32 && hash_data_size != 48 && hash_data_size != 64)
+ return grub_error (GRUB_ERR_BAD_SIGNATURE,
+ N_("unacceptable distrusted certificate hash type"));
+ }
+
+ rc = add_hash ((const grub_uint8_t **) &hash_data, hash_data_size, &dbx.signatures,
+ &dbx.signature_size, &dbx.signature_entries);
+ if (rc != GRUB_ERR_NONE)
+ {
+ free_trusted_list ();
+ free_distrusted_list ();
+ grub_error (rc, "adding of distrusted binary/certificate hash failed");
+ }
+
+ grub_free (hash_data);
+
+ return rc;
}
static grub_err_t
-appendedsig_init (grub_file_t io __attribute__((unused)),
- enum grub_file_type type,
- void **context __attribute__((unused)),
- enum grub_verify_flags *flags)
+appendedsig_init (grub_file_t io __attribute__ ((unused)), enum grub_file_type type,
+ void **context __attribute__ ((unused)), enum grub_verify_flags *flags)
{
if (check_sigs == check_sigs_no)
{
@@ -874,8 +1024,6 @@ static struct grub_fs pseudo_fs = {
.fs_read = pseudo_read
};
-static grub_command_t cmd_verify, cmd_list, cmd_distrust, cmd_trust;
-
/*
* Verify the trusted certificate against the certificate hashes from platform keystore buffer's
* distrusted list.
@@ -1167,6 +1315,10 @@ load_static_keys (const struct grub_module_header *header, const grub_bool_t is_
return rc;
}
+static grub_extcmd_t cmd_distrusted_hash;
+static grub_command_t cmd_verify, cmd_trusted_list, cmd_trusted_cert, cmd_trusted_hash,
+ cmd_distrusted_list, cmd_distrusted_cert;
+
GRUB_MOD_INIT (appendedsig)
{
int rc;
@@ -1229,22 +1381,31 @@ GRUB_MOD_INIT (appendedsig)
grub_pks_free_keystore ();
}
-
- cmd_trust =
- grub_register_command ("trust_certificate", grub_cmd_trust,
- N_("X509_CERTIFICATE"),
- N_("Add X509_CERTIFICATE to trusted certificates."));
- cmd_list =
- grub_register_command ("list_certificates", grub_cmd_list, 0,
- N_("Show the list of trusted x509 certificates."));
- cmd_verify =
- grub_register_command ("verify_appended", grub_cmd_verify_signature,
- N_("FILE"),
- N_("Verify FILE against the trusted x509 certificates."));
- cmd_distrust =
- grub_register_command ("distrust_certificate", grub_cmd_distrust,
- N_("CERT_NUMBER"),
- N_("Remove CERT_NUMBER (as listed by list_certificates) from trusted certificates."));
+ cmd_trusted_cert = grub_register_command ("trusted_certificate", grub_cmd_trusted_cert,
+ N_("X509_CERTIFICATE"),
+ N_("Add X509_CERTIFICATE to trusted list."));
+ cmd_trusted_hash = grub_register_command ("trusted_signature", grub_cmd_trusted_hash,
+ N_("BINARY HASH FILE"),
+ N_("Add trusted BINARY HASH to trusted list."));
+ cmd_distrusted_cert = grub_register_command ("distrusted_certificate", grub_cmd_distrusted_cert,
+ N_("CERT_NUMBER"),
+ N_("Remove CERT_NUMBER (as listed by list_trusted)"
+ " from trusted list."));
+ cmd_distrusted_hash = grub_register_extcmd ("distrusted_signature", grub_cmd_distrusted_hash, 0,
+ N_("[-b|--binary-hash] FILE [BINARY HASH FILE]\n"
+ "[-c|--cert-hash] FILE [CERTFICATE HASH FILE]"),
+ N_("Add distrusted CERTFICATE/BINARY HASH "
+ "to distrusted list."),
+ options);
+ cmd_trusted_list = grub_register_command ("trusted_list", grub_cmd_trusted_list, 0,
+ N_("Show the list of trusted x509 certificates and"
+ " trusted binary hashes."));
+ cmd_distrusted_list = grub_register_command ("distrusted_list", grub_cmd_distrusted_list, 0,
+ N_("Show the list of distrusted certificates and"
+ " certificate/binary hashes"));
+ cmd_verify = grub_register_command ("verify_appended", grub_cmd_verify_signature, N_("FILE"),
+ N_("Verify FILE against the trusted x509 certificates/"
+ "trusted binary hashes."));
grub_verifier_register (&grub_appendedsig_verifier);
grub_dl_set_persistent (mod);
@@ -1256,10 +1417,12 @@ GRUB_MOD_FINI (appendedsig)
* grub_dl_set_persistent should prevent this from actually running, but
* it does still run under emu.
*/
-
grub_verifier_unregister (&grub_appendedsig_verifier);
grub_unregister_command (cmd_verify);
- grub_unregister_command (cmd_list);
- grub_unregister_command (cmd_trust);
- grub_unregister_command (cmd_distrust);
+ grub_unregister_command (cmd_trusted_list);
+ grub_unregister_command (cmd_distrusted_list);
+ grub_unregister_command (cmd_trusted_cert);
+ grub_unregister_command (cmd_distrusted_cert);
+ grub_unregister_command (cmd_trusted_hash);
+ grub_unregister_extcmd (cmd_distrusted_hash);
}
--
2.48.1

View File

@@ -0,0 +1,75 @@
From 2b0e6effc31ec166bbbe35a3cd2b4c73051f38bb Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 16 Jun 2023 15:54:50 +0800
Subject: [PATCH 8/9] blscfg: reading bls fragments if boot present
The Boot Loader Specification (BLS) designates the EFI System Partition
(ESP) as a primary location for $BOOT, where boot menu entries can be
stored. The specification encourages boot loaders to retrieve menu
entries from the ESP, even when XBOOTLDR is present.
This commit aligns with the BLS specification by introducing the
capability to search for the ESP in addition to the default root
partition or any specified location via blscfg's command line. The $boot
environment variable is utilized as a reference to the ESP device for
the blscfg command. Initialization of $boot in grub.cfg is demonstrated
as follows:
insmod part_gpt
insmod fat
search --no-floppy --fs-uuid --set=boot F414-5A9F
If $boot is unset, no additional search for the BLS location will be
performed.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/commands/blscfg.c | 10 ++++++++++
util/grub.d/10_linux.in | 3 ++-
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c
index c872bcef0..cbe2a289e 100644
--- a/grub-core/commands/blscfg.c
+++ b/grub-core/commands/blscfg.c
@@ -1186,6 +1186,7 @@ grub_cmd_blscfg (grub_extcmd_context_t ctxt UNUSED,
char *entry_id = NULL;
bool show_default = true;
bool show_non_default = true;
+ const char *boot = NULL;
if (argc == 1) {
if (grub_strcmp (args[0], "default") == 0) {
@@ -1205,6 +1206,15 @@ grub_cmd_blscfg (grub_extcmd_context_t ctxt UNUSED,
if (r)
return r;
+ boot = grub_env_get("boot");
+ path = (boot) ? grub_xasprintf("(%s)" GRUB_BLS_CONFIG_PATH, boot) : NULL;
+ if (path)
+ {
+ bls_load_entries(path);
+ grub_print_error();
+ }
+ grub_free(path);
+
return bls_create_entries(show_default, show_non_default, entry_id);
}
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 45eefb332..edf0fca55 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -201,7 +201,8 @@ populate_menu()
}
# Make BLS the default if GRUB_ENABLE_BLSCFG was not set and grubby is not installed.
-if [ -z "${GRUB_ENABLE_BLSCFG}" ] && ! command -v new-kernel-pkg >/dev/null; then
+# FIXME: The test should be aligned to openSUSE, grubby is not our default tool
+if [ -z "${GRUB_ENABLE_BLSCFG}" ] && ! command -v new-kernel-pkg >/dev/null && false; then
GRUB_ENABLE_BLSCFG="true"
fi
--
2.44.0

View File

@@ -1,117 +0,0 @@
From ba5a201546cfb69d3079f18c89a79bda98e7bcd1 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 8 May 2025 19:02:14 +0200
Subject: [PATCH 8/8] cryptocheck: Add --quiet option
The option can be used to suppress output if we only want to test the
return value of the command.
Also, mention this option in the documentation.
Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Signed-off-by: Michael Chang <mchang@suse.com>
---
docs/grub.texi | 4 +++-
grub-core/commands/search.c | 7 ++++++-
grub-core/disk/diskfilter.c | 25 +++++++++++++++++++------
3 files changed, 28 insertions(+), 8 deletions(-)
diff --git a/docs/grub.texi b/docs/grub.texi
index c4936db8c1..9646cf9282 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -4684,12 +4684,14 @@ Alias for @code{hashsum --hash crc32 arg @dots{}}. See command @command{hashsum}
@node cryptocheck
@subsection cryptocheck
-@deffn Command cryptocheck device
+@deffn Command cryptocheck [ @option{--quiet} ] device
Check if a given diskfilter device is backed by encrypted devices
(@pxref{cryptomount} for additional information).
The command examines all backing devices, physical volumes, of a specified
logical volume, like LVM2, and fails when at least one of them is unencrypted.
+
+The option @option{--quiet} can be given to suppress the output.
@end deffn
@node cryptomount
diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c
index 185c1e70f7..49b679e805 100644
--- a/grub-core/commands/search.c
+++ b/grub-core/commands/search.c
@@ -67,6 +67,9 @@ is_unencrypted_disk (grub_disk_t disk)
if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID)
{
+ char opt[] = "--quiet";
+ char *args[2];
+
cmd = grub_command_find ("cryptocheck");
if (cmd == NULL) /* No diskfilter module loaded for some reason. */
return true;
@@ -77,7 +80,9 @@ is_unencrypted_disk (grub_disk_t disk)
return true;
grub_snprintf (disk_str, disk_str_len, "(%s)", disk->name);
- res = cmd->func (cmd, 1, &disk_str);
+ args[0] = opt;
+ args[1] = disk_str;
+ res = cmd->func (cmd, 2, args);
grub_free (disk_str);
return (res != GRUB_ERR_NONE) ? true : false; /* GRUB_ERR_NONE for encrypted. */
}
diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c
index 3f7c05e14e..b1d5d464f5 100644
--- a/grub-core/disk/diskfilter.c
+++ b/grub-core/disk/diskfilter.c
@@ -1524,6 +1524,19 @@ grub_cmd_cryptocheck (grub_command_t cmd __attribute__ ((unused)),
int check_pvs_res;
int namelen;
int pvs_cnt;
+ int opt_quiet = 0;
+
+ if (argc == 2)
+ {
+ if (grub_strcmp (args[0], "--quiet") == 0)
+ {
+ opt_quiet = 1;
+ argc--;
+ args++;
+ }
+ else
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unrecognized option: %s"), args[0]);
+ }
if (argc != 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("disk name expected"));
@@ -1546,11 +1559,11 @@ grub_cmd_cryptocheck (grub_command_t cmd __attribute__ ((unused)),
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" : "");
+ if (!opt_quiet)
+ 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;
}
@@ -1578,7 +1591,7 @@ GRUB_MOD_INIT(diskfilter)
{
grub_disk_dev_register (&grub_diskfilter_dev);
cmd = grub_register_command ("cryptocheck", grub_cmd_cryptocheck,
- N_("DEVICE"),
+ N_("[--quiet] DEVICE"),
N_("Check if a logical volume resides on encrypted disks."));
}
--
2.49.0

View File

@@ -1,48 +0,0 @@
From 312edf1f0ebaebba72e348ae88d95b29fa24c09c Mon Sep 17 00:00:00 2001
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Date: Wed, 23 Oct 2024 17:54:33 +0530
Subject: [PATCH 8/8] grub-mkimage: Add SBAT metadata into ELF note for PowerPC
targets
The SBAT metadata is read from CSV file and transformed into an ELF note
with the -s option.
Signed-off-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
util/mkimage.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/util/mkimage.c b/util/mkimage.c
index be7f02c5c..d3948937b 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -958,8 +958,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
total_module_size += dtb_size + sizeof (struct grub_module_header);
}
- if (sbat_path != NULL && image_target->id != IMAGE_EFI)
- grub_util_error (_(".sbat section can be embedded into EFI images only"));
+ if (sbat_path != NULL && (image_target->id != IMAGE_EFI && image_target->id != IMAGE_PPC))
+ grub_util_error (_("SBAT data can be added only to EFI or powerpc-ieee1275 images"));
if (disable_shim_lock)
total_module_size += sizeof (struct grub_module_header);
@@ -1836,6 +1836,13 @@ grub_install_generate_image (const char *dir, const char *prefix,
{
grub_uint64_t target_addr;
char *sbat = NULL;
+ if (sbat_path != NULL)
+ {
+ sbat_size = grub_util_get_image_size (sbat_path);
+ sbat = xmalloc (sbat_size);
+ grub_util_load_image (sbat_path, sbat);
+ layout.sbat_size = sbat_size;
+ }
if (image_target->id == IMAGE_LOONGSON_ELF)
{
if (comp == GRUB_COMPRESSION_NONE)
--
2.47.1

View File

@@ -1,83 +0,0 @@
From de9400db3f181e059f9ab1bb6a667ae2c29baf03 Mon Sep 17 00:00:00 2001
From: B Horn <b@horn.uk>
Date: Fri, 15 Nov 2024 13:12:09 +0000
Subject: [PATCH 08/20] net: Fix OOB write in grub_net_search_config_file()
The function included a call to grub_strcpy() which copied data from an
environment variable to a buffer allocated in grub_cmd_normal(). The
grub_cmd_normal() didn't consider the length of the environment variable.
So, the copy operation could exceed the allocation and lead to an OOB
write. Fix the issue by replacing grub_strcpy() with grub_strlcpy() and
pass the underlying buffers size to the grub_net_search_config_file().
Fixes: CVE-2025-0624
Reported-by: B Horn <b@horn.uk>
Signed-off-by: B Horn <b@horn.uk>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/net/net.c | 7 ++++---
grub-core/normal/main.c | 2 +-
include/grub/net.h | 2 +-
3 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
index 22221dc6a0..df13c3aaaa 100644
--- a/grub-core/net/net.c
+++ b/grub-core/net/net.c
@@ -1912,14 +1912,15 @@ grub_config_search_through (char *config, char *suffix,
}
grub_err_t
-grub_net_search_config_file (char *config)
+grub_net_search_config_file (char *config, grub_size_t config_buf_len)
{
- grub_size_t config_len;
+ grub_size_t config_len, suffix_len;
char *suffix;
config_len = grub_strlen (config);
config[config_len] = '-';
suffix = config + config_len + 1;
+ suffix_len = config_buf_len - (config_len + 1);
struct grub_net_network_level_interface *inf;
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
@@ -1945,7 +1946,7 @@ grub_net_search_config_file (char *config)
if (client_uuid)
{
- grub_strcpy (suffix, client_uuid);
+ grub_strlcpy (suffix, client_uuid, suffix_len);
if (grub_config_search_through (config, suffix, 1, 0) == 0)
return GRUB_ERR_NONE;
}
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index b08fd6977d..f2679c4378 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -451,7 +451,7 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0 &&
!disable_net_search)
- grub_net_search_config_file (config);
+ grub_net_search_config_file (config, config_len);
grub_enter_normal_mode (config);
grub_free (config);
diff --git a/include/grub/net.h b/include/grub/net.h
index dfb089a35c..abb637eaa2 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -652,7 +652,7 @@ void
grub_net_remove_dns_server (const struct grub_net_network_level_address *s);
grub_err_t
-grub_net_search_config_file (char *config);
+grub_net_search_config_file (char *config, grub_size_t config_buf_len);
extern char *grub_net_default_server;
--
2.48.1

View File

@@ -0,0 +1,252 @@
From abd8b83cdc6398c52c7d2b71b378938cf51872fd Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Wed, 13 Mar 2024 15:26:42 +0800
Subject: [PATCH 9/9] 10_linux: Some refinement for BLS
Remove BLS_POPULATE_MENU as it is not being used currently and removing
kernelopts assignment in the grub boot config itself to fully delegate
the responsibility of generating kernel options to a functioning BLS
generator.
Additionally, removing unused dead code, which is often blamed for
causing errors in the dash shell script.
Signed-off-by: Michael Chang <mchang@suse.com>
---
util/grub.d/10_linux.in | 194 ----------------------------------------
1 file changed, 194 deletions(-)
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index edf0fca55..666eae995 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -93,11 +93,7 @@ fi
populate_header_warn()
{
-if [ "x${BLS_POPULATE_MENU}" = "xtrue" ]; then
- bls_parser="10_linux script"
-else
bls_parser="blscfg command"
-fi
cat <<EOF
# This section was generated by a script. Do not modify the generated file - all changes
@@ -110,102 +106,6 @@ cat <<EOF
EOF
}
-read_config()
-{
- config_file=${1}
- title=""
- initrd=""
- options=""
- linux=""
- grub_arg=""
-
- while read -r line
- do
- record=$(echo ${line} | cut -f 1 -d ' ')
- value=$(echo ${line} | cut -s -f2- -d ' ')
- case "${record}" in
- "title")
- title=${value}
- ;;
- "initrd")
- initrd=${value}
- ;;
- "linux")
- linux=${value}
- ;;
- "options")
- options=${value}
- ;;
- "grub_arg")
- grub_arg=${value}
- ;;
- esac
- done < ${config_file}
-}
-
-blsdir="/boot/loader/entries"
-
-get_sorted_bls()
-{
- if ! [ -d "${blsdir}" ] || [ -f /run/ostree-booted ] || [ -d /ostree/repo ]; then
- return
- fi
-
- local IFS=$'\n'
-
- files=($(for bls in ${blsdir}/*.conf; do
- if ! [[ -e "${bls}" ]] ; then
- continue
- fi
- bls="${bls%.conf}"
- bls="${bls##*/}"
- echo "${bls}"
- done | ${kernel_sort} 2>/dev/null | tac)) || :
-
- echo "${files[@]}"
-}
-
-update_bls_cmdline()
-{
- local cmdline="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
- local -a files=($(get_sorted_bls))
-
- for bls in "${files[@]}"; do
- local options="${cmdline}"
- if [ -z "${bls##*debug*}" ]; then
- options="${options} ${GRUB_CMDLINE_LINUX_DEBUG}"
- fi
- options="$(echo "${options}" | sed -e 's/\//\\\//g')"
- sed -i -e "s/^options.*/options ${options}/" "${blsdir}/${bls}.conf"
- done
-}
-
-populate_menu()
-{
- local -a files=($(get_sorted_bls))
-
- gettext_printf "Generating boot entries from BLS files...\n" >&2
-
- for bls in "${files[@]}"; do
- read_config "${blsdir}/${bls}.conf"
-
- menu="${menu}menuentry '${title}' ${grub_arg} --id=${bls} {\n"
- menu="${menu}\t linux ${linux} ${options}\n"
- if [ -n "${initrd}" ] ; then
- menu="${menu}\t initrd ${boot_prefix}${initrd}\n"
- fi
- menu="${menu}}\n\n"
- done
- # The printf command seems to be more reliable across shells for special character (\n, \t) evaluation
- printf "$menu"
-}
-
-# Make BLS the default if GRUB_ENABLE_BLSCFG was not set and grubby is not installed.
-# FIXME: The test should be aligned to openSUSE, grubby is not our default tool
-if [ -z "${GRUB_ENABLE_BLSCFG}" ] && ! command -v new-kernel-pkg >/dev/null && false; then
- GRUB_ENABLE_BLSCFG="true"
-fi
-
if [ "x${GRUB_ENABLE_BLSCFG}" = "xtrue" ]; then
if [ x$dirname = x/ ]; then
if [ -z "${prepare_root_cache}" ]; then
@@ -225,111 +125,17 @@ if [ "x${GRUB_ENABLE_BLSCFG}" = "xtrue" ]; then
prepare_grub_to_access_device_with_variable boot ${boot_device}
fi
- arch="$(uname -m)"
- if [ "x${arch}" = "xppc64le" ] && [ -d /sys/firmware/opal ]; then
-
- BLS_POPULATE_MENU="true"
- petitboot_path="/sys/firmware/devicetree/base/ibm,firmware-versions/petitboot"
-
- if test -e ${petitboot_path}; then
- read -r -d '' petitboot_version < ${petitboot_path}
- petitboot_version="$(echo ${petitboot_version//v})"
-
- if test -n ${petitboot_version}; then
- major_version="$(echo ${petitboot_version} | cut -d . -f1)"
- minor_version="$(echo ${petitboot_version} | cut -d . -f2)"
-
- re='^[0-9]+$'
- if [[ $major_version =~ $re ]] && [[ $minor_version =~ $re ]] &&
- ([[ ${major_version} -gt 1 ]] ||
- [[ ${major_version} -eq 1 &&
- ${minor_version} -ge 8 ]]); then
- BLS_POPULATE_MENU="false"
- fi
- fi
- fi
- fi
-
populate_header_warn
- cat << EOF
-# The kernelopts variable should be defined in the grubenv file. But to ensure that menu
-# entries populated from BootLoaderSpec files that use this variable work correctly even
-# without a grubenv file, define a fallback kernelopts variable if this has not been set.
-#
-# The kernelopts variable in the grubenv file can be modified using the grubby tool or by
-# executing the grub2-mkconfig tool. For the latter, the values of the GRUB_CMDLINE_LINUX
-# and GRUB_CMDLINE_LINUX_DEFAULT options from /etc/default/grub file are used to set both
-# the kernelopts variable in the grubenv file and the fallback kernelopts variable.
-if [ -z "\${kernelopts}" ]; then
- set kernelopts="root=${LINUX_ROOT_DEVICE} ro ${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
-fi
-EOF
-
- update_bls_cmdline
-
- if [ "x${BLS_POPULATE_MENU}" = "xtrue" ]; then
- populate_menu
- else
cat << EOF
insmod blscfg
blscfg
EOF
- fi
-
- if [ "x${GRUB_GRUBENV_UPDATE}" = "xyes" ]; then
- blsdir="/boot/loader/entries"
- [ -d "${blsdir}" ] && GRUB_BLS_FS="$(${grub_probe} --target=fs ${blsdir})"
- if [ "x${GRUB_BLS_FS}" = "xbtrfs" ] || [ "x${GRUB_BLS_FS}" = "xzfs" ]; then
- blsdir=$(make_system_path_relative_to_its_root "${blsdir}")
- if [ "x${blsdir}" != "x/loader/entries" ] && [ "x${blsdir}" != "x/boot/loader/entries" ]; then
- ${grub_editenv} - set blsdir="${blsdir}"
- fi
- fi
-
- if [ -n "${GRUB_EARLY_INITRD_LINUX_CUSTOM}" ]; then
- ${grub_editenv} - set early_initrd="${GRUB_EARLY_INITRD_LINUX_CUSTOM}"
- fi
-
- if [ -n "${GRUB_DEFAULT_DTB}" ]; then
- ${grub_editenv} - set devicetree="${GRUB_DEFAULT_DTB}"
- fi
-
- if [ -n "${GRUB_SAVEDEFAULT}" ]; then
- ${grub_editenv} - set save_default="${GRUB_SAVEDEFAULT}"
- fi
- fi
exit 0
fi
-mktitle ()
-{
- local title_type
- local version
- local OS_NAME
- local OS_VERS
-
- title_type=$1 && shift
- version=$1 && shift
-
- OS_NAME="$(eval $(grep ^NAME= /etc/os-release) ; echo ${NAME})"
- OS_VERS="$(eval $(grep ^VERSION= /etc/os-release) ; echo ${VERSION})"
-
- case $title_type in
- recovery)
- title=$(printf '%s (%s) %s (recovery mode)' \
- "${OS_NAME}" "${version}" "${OS_VERS}")
- ;;
- *)
- title=$(printf '%s (%s) %s' \
- "${OS_NAME}" "${version}" "${OS_VERS}")
- ;;
- esac
- echo -n ${title}
-}
-
title_correction_code=
hotkey=1
--
2.45.2

View File

@@ -1,218 +0,0 @@
From e57bcf83765291da62ad92f330cc1ffb535d4017 Mon Sep 17 00:00:00 2001
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Date: Tue, 25 Feb 2025 02:47:03 +0530
Subject: [PATCH 9/9] appendedsig: documentation
This explains how static and dynamic key appended signatures can be used to form part of
a secure boot chain, and documents the commands and variables introduced.
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
---
docs/grub.texi | 113 +++++++++++++++++++++++++++++++++----------------
1 file changed, 76 insertions(+), 37 deletions(-)
diff --git a/docs/grub.texi b/docs/grub.texi
index e89007920c..9aaea72826 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -4373,7 +4373,9 @@ you forget a command, you can run the command @command{help}
* date:: Display or set current date and time
* devicetree:: Load a device tree blob
* distrust:: Remove a pubkey from trusted keys
-* distrust_certificate:: Remove a certificate from the list of trusted certificates
+* distrusted_certificate:: Remove a certificate from the trusted list
+* distrusted_list:: List distrusted certificates and binary/certificate hashes
+* distrusted_signature:: Add a binary hash to the distrusted list
* drivemap:: Map a drive to another
* echo:: Display a line of text
* efitextmode:: Set/Get text output mode resolution
@@ -4390,7 +4392,6 @@ you forget a command, you can run the command @command{help}
* hexdump:: Show raw contents of a file or memory
* insmod:: Insert a module
* keystatus:: Check key modifier status
-* list_certificates:: List trusted certificates
* list_env:: List variables in environment block
* list_trusted:: List trusted public keys
* load_env:: Load variables from environment block
@@ -4429,7 +4430,9 @@ you forget a command, you can run the command @command{help}
* test:: Check file types and compare values
* true:: Do nothing, successfully
* trust:: Add public key to list of trusted keys
-* trust_certificate:: Add an x509 certificate to the list of trusted certificates
+* trusted_certificate:: Add an x509 certificate to the trusted list
+* trusted_list:: List trusted certificates and binary hashes
+* trusted_signature:: Add a binary hash to the trusted list.
* unset:: Unset an environment variable
@comment * vbeinfo:: List available video modes
* verify_appended:: Verify appended digital signature
@@ -4775,16 +4778,15 @@ These keys are used to validate signatures when environment variable
GPG-style digital signatures}, for more information.
@end deffn
+@node distrusted_certificate
+@subsection distrusted_certificate
-@node distrust_certificate
-@subsection distrust_certificate
-
-@deffn Command distrust_certificate cert_number
+@deffn Command distrusted_certificate cert_number
Remove the x509 certificate numbered @var{cert_number} from GRUB's keyring of
trusted x509 certificates for verifying appended signatures.
@var{cert_number} is the certificate number as listed by
-@command{list_certificates} (@pxref{list_certificates}).
+@command{trusted_list} (@pxref{trusted_list}).
These certificates are used to validate appended signatures when environment
variable @code{check_appended_signatures} is set to @code{enforce}
@@ -4793,6 +4795,27 @@ variable @code{check_appended_signatures} is set to @code{enforce}
information.
@end deffn
+@node distrusted_list
+@subsection distrusted_list
+
+@deffn Command distrusted_list
+List all the distrusted x509 certificates and binary/certificate hashes.
+The output is a numbered list of certificates and binary/certificate hashes,
+showing the certificate's serial number and Common Name.
+@end deffn
+
+@node distrusted_signature
+@subsection distrusted_signature
+
+@deffn Command distrusted_signature
+Read a binary hash from the file @var{binary hash file}
+and add it to GRUB's internal distrusted list. These hash are used to
+restrict validation of linux image integrity using trusted list if appended
+signatures validation failed when the environment variable
+@code{check_appended_signatures} is set to @code{enforce}.
+
+See @xref{Using appended signatures} for more information.
+@end deffn
@node drivemap
@subsection drivemap
@@ -5069,22 +5092,6 @@ without any options, the @command{keystatus} command returns true if and
only if checking key modifier status is supported.
@end deffn
-
-@node list_certificates
-@subsection list_certificates
-
-@deffn Command list_certificates
-List all x509 certificates trusted by GRUB for validating appended signatures.
-The output is a numbered list of certificates, showing the certificate's serial
-number and Common Name.
-
-The certificate number can be used as an argument to
-@command{distrust_certificate} (@pxref{distrust_certificate}).
-
-See @xref{Using appended signatures} for more information.
-@end deffn
-
-
@node list_env
@subsection list_env
@@ -5936,17 +5943,17 @@ information.
@end deffn
-@node trust_certificate
-@subsection trust_certificate
+@node trusted_certificate
+@subsection trusted_certificate
-@deffn Command trust_certificate x509_certificate
+@deffn Command trusted_certificate x509_certificate
Read a DER-formatted x509 certificate from the file @var{x509_certificate}
and add it to GRUB's internal list of trusted x509 certificates. These
certificates are used to validate appended signatures when the environment
variable @code{check_appended_signatures} is set to @code{enforce}.
Note that if @code{check_appended_signatures} is set to @code{enforce}
-when @command{trust_certificate} is executed, then @var{x509_certificate}
+when @command{trusted_certificate} is executed, then @var{x509_certificate}
must itself bear an appended signature. (It is not sufficient that
@var{x509_certificate} be signed by a trusted certificate according to the
x509 rules: grub does not include support for validating signatures within x509
@@ -5955,6 +5962,32 @@ certificates themselves.)
See @xref{Using appended signatures} for more information.
@end deffn
+@node trusted_list
+@subsection trusted_list
+
+@deffn Command trusted_list
+List all x509 certificates and binary hases trusted by GRUB for validating
+appended signatures. The output is a numbered list of certificates and binary
+hashes, showing the certificate's serial number and Common Name.
+
+The certificate number can be used as an argument to
+@command{distrusted_certificate} (@pxref{distrusted_certificate}).
+
+See @xref{Using appended signatures} for more information.
+@end deffn
+
+@node trusted_signature
+@subsection trusted_signature
+
+@deffn Command trust_signature
+Read a binary hash from the file @var{binary hash file}
+and add it to GRUB's internal trusted list. These binary hash are used to
+validate linux image integrity if appended signatures validation failed
+when the environment variable @code{check_appended_signatures} is set
+to @code{enforce}.
+
+See @xref{Using appended signatures} for more information.
+@end deffn
@node unset
@subsection unset
@@ -5979,9 +6012,8 @@ only on PC BIOS platforms.
@deffn Command verify_appended file
Verifies an appended signature on @var{file} against the trusted certificates
-known to GRUB (See @pxref{list_certificates}, @pxref{trust_certificate}, and
-@pxref{distrust_certificate}).
-
+known to GRUB (See @pxref{trusted_list}, @pxref{trusted_certificate}, and
+@pxref{distrusted_certificate}).
Exit code @code{$?} is set to 0 if the signature validates
successfully. If validation fails, it is set to a non-zero value.
See @xref{Using appended signatures}, for more information.
@@ -6669,14 +6701,21 @@ To enable appended signature verification, load the appendedsig module and an
x509 certificate for verification. Building the appendedsig module into the
core grub image is recommended.
-Certificates can be managed at boot time using the @pxref{trust_certificate},
-@pxref{distrust_certificate} and @pxref{list_certificates} commands.
-Certificates can also be built in to the core image using the @code{--x509}
-parameter to @command{grub-install} or @command{grub-mkimage}.
+For static key, Certificates will be built in to the core image using
+the @code{--x509} parameter to @command{grub-install} or @command{grub-mkimage}.
+it can allow to list the trusted certificates and binary hashes at boot time using
+@pxref{trusted_list} and list distrusted certificates and binary/certificate hashes
+at boot time using @pxref{distrusted_list} commands.
+
+For dynamic key, loads the signature database (DB) and forbidden
+signature database (DBX) from platform keystore (PKS) and it can allow to list
+the trusted certificates and binary hashes at boot time using @pxref{trusted_list}
+and list distrusted certificates and binary/certificate hashes at boot time using
+@pxref{distrusted_list} commands.
-A file can be explictly verified using the @pxref{verify_appended} command.
+A file can be explicitly verified using the @pxref{verify_appended} command.
-Only signatures made with the SHA-256 or SHA-512 hash algorithm are supported,
+Only signatures made with the SHA-256, SHA-384 and SHA-512 hash algorithm are supported,
and only RSA signatures are supported.
A file can be signed with the @command{sign-file} utility supplied with the
--
2.48.1

View File

@@ -1,36 +0,0 @@
From c3093b6240302e52438469857fec616aa4b294a3 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <dja@axtens.net>
Date: Fri, 8 Mar 2024 22:47:20 +1100
Subject: [PATCH 09/20] video/readers/jpeg: Do not permit duplicate SOF0
markers in JPEG
Otherwise a subsequent header could change the height and width
allowing future OOB writes.
Fixes: CVE-2024-45774
Reported-by: Nils Langius <nils@langius.de>
Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/video/readers/jpeg.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
index ae634fd419..631a893564 100644
--- a/grub-core/video/readers/jpeg.c
+++ b/grub-core/video/readers/jpeg.c
@@ -339,6 +339,10 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data)
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
+ if (data->image_height != 0 || data->image_width != 0)
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+ "jpeg: cannot have duplicate SOF0 markers");
+
if (grub_jpeg_get_byte (data) != 8)
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
"jpeg: only 8-bit precision is supported");
--
2.48.1

View File

@@ -1,37 +0,0 @@
From 5d6f17ba4e94fe00b80498e9ce1aac57e22adba7 Mon Sep 17 00:00:00 2001
From: Lidong Chen <lidong.chen@oracle.com>
Date: Fri, 22 Nov 2024 06:27:55 +0000
Subject: [PATCH 10/20] commands/extcmd: Missing check for failed allocation
The grub_extcmd_dispatcher() calls grub_arg_list_alloc() to allocate
a grub_arg_list struct but it does not verify the allocation was successful.
In case of failed allocation the NULL state pointer can be accessed in
parse_option() through grub_arg_parse() which may lead to a security issue.
Fixes: CVE-2024-45775
Reported-by: Nils Langius <nils@langius.de>
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Alec Brown <alec.r.brown@oracle.com>
---
grub-core/commands/extcmd.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/grub-core/commands/extcmd.c b/grub-core/commands/extcmd.c
index 4ac111a991..95bd71235a 100644
--- a/grub-core/commands/extcmd.c
+++ b/grub-core/commands/extcmd.c
@@ -49,6 +49,9 @@ grub_extcmd_dispatcher (struct grub_command *cmd, int argc, char **args,
}
state = grub_arg_list_alloc (ext, argc, args);
+ if (state == NULL)
+ return grub_errno;
+
if (grub_arg_parse (ext, argc, args, state, &new_args, &new_argc))
{
context.state = state;
--
2.48.1

View File

@@ -1,34 +0,0 @@
From a496d7fbb80826b341ec1a578704dd574b716d68 Mon Sep 17 00:00:00 2001
From: B Horn <b@horn.uk>
Date: Fri, 1 Nov 2024 19:24:29 +0000
Subject: [PATCH 11/20] commands/pgp: Unregister the "check_signatures" hooks
on module unload
If the hooks are not removed they can be called after the module has
been unloaded leading to an use-after-free.
Fixes: CVE-2025-0622
Reported-by: B Horn <b@horn.uk>
Signed-off-by: B Horn <b@horn.uk>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/commands/pgp.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/grub-core/commands/pgp.c b/grub-core/commands/pgp.c
index 847a5046a5..fa3ef5c754 100644
--- a/grub-core/commands/pgp.c
+++ b/grub-core/commands/pgp.c
@@ -982,6 +982,8 @@ GRUB_MOD_INIT(pgp)
GRUB_MOD_FINI(pgp)
{
+ grub_register_variable_hook ("check_signatures", NULL, NULL);
+ grub_env_unset ("check_signatures");
grub_verifier_unregister (&grub_pubkey_verifier);
grub_unregister_extcmd (cmd);
grub_unregister_extcmd (cmd_trust);
--
2.48.1

View File

@@ -1,40 +0,0 @@
From cf9108c54b25bd485832bf8930c18abf2935b35e Mon Sep 17 00:00:00 2001
From: B Horn <b@horn.uk>
Date: Fri, 1 Nov 2024 23:46:55 +0000
Subject: [PATCH 12/20] normal: Remove variables hooks on module unload
The normal module does not entirely cleanup after itself in
its GRUB_MOD_FINI() leaving a few variables hooks in place.
It is not possible to unload normal module now but fix the
issues for completeness.
On the occasion replace 0s with NULLs for "pager" variable
hooks unregister.
Fixes: CVE-2025-0622
Reported-by: B Horn <b@horn.uk>
Signed-off-by: B Horn <b@horn.uk>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/normal/main.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index f2679c4378..c9eda889ca 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -694,7 +694,9 @@ GRUB_MOD_FINI(normal)
grub_xputs = grub_xputs_saved;
grub_set_history (0);
- grub_register_variable_hook ("pager", 0, 0);
+ grub_register_variable_hook ("pager", NULL, NULL);
+ grub_register_variable_hook ("color_normal", NULL, NULL);
+ grub_register_variable_hook ("color_highlight", NULL, NULL);
grub_fs_autoload_hook = 0;
grub_unregister_command (cmd_clear);
}
--
2.48.1

View File

@@ -1,37 +0,0 @@
From dff23721425f363f2d1b6ee41be44af69cdd4aab Mon Sep 17 00:00:00 2001
From: B Horn <b@horn.uk>
Date: Fri, 1 Nov 2024 23:52:06 +0000
Subject: [PATCH 13/20] gettext: Remove variables hooks on module unload
The gettext module does not entirely cleanup after itself in
its GRUB_MOD_FINI() leaving a few variables hooks in place.
It is not possible to unload gettext module because normal
module depends on it. Though fix the issues for completeness.
Fixes: CVE-2025-0622
Reported-by: B Horn <b@horn.uk>
Signed-off-by: B Horn <b@horn.uk>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/gettext/gettext.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/grub-core/gettext/gettext.c b/grub-core/gettext/gettext.c
index 7a1c14e4f3..e4f4f8ee66 100644
--- a/grub-core/gettext/gettext.c
+++ b/grub-core/gettext/gettext.c
@@ -535,6 +535,10 @@ GRUB_MOD_INIT (gettext)
GRUB_MOD_FINI (gettext)
{
+ grub_register_variable_hook ("locale_dir", NULL, NULL);
+ grub_register_variable_hook ("secondary_locale_dir", NULL, NULL);
+ grub_register_variable_hook ("lang", NULL, NULL);
+
grub_gettext_delete_list (&main_context);
grub_gettext_delete_list (&secondary_context);
--
2.48.1

View File

@@ -1,39 +0,0 @@
From 9126fb474968a1f4ea8e233c5746fa735a07b3d4 Mon Sep 17 00:00:00 2001
From: Lidong Chen <lidong.chen@oracle.com>
Date: Fri, 22 Nov 2024 06:27:56 +0000
Subject: [PATCH 14/20] gettext: Integer overflow leads to heap OOB write or
read
Calculation of ctx->grub_gettext_msg_list size in grub_mofile_open() may
overflow leading to subsequent OOB write or read. This patch fixes the
issue by replacing grub_zalloc() and explicit multiplication with
grub_calloc() which does the same thing in safe manner.
Fixes: CVE-2024-45776
Reported-by: Nils Langius <nils@langius.de>
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Alec Brown <alec.r.brown@oracle.com>
---
grub-core/gettext/gettext.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/grub-core/gettext/gettext.c b/grub-core/gettext/gettext.c
index e4f4f8ee66..63bb1ab73f 100644
--- a/grub-core/gettext/gettext.c
+++ b/grub-core/gettext/gettext.c
@@ -323,8 +323,8 @@ grub_mofile_open (struct grub_gettext_context *ctx,
for (ctx->grub_gettext_max_log = 0; ctx->grub_gettext_max >> ctx->grub_gettext_max_log;
ctx->grub_gettext_max_log++);
- ctx->grub_gettext_msg_list = grub_zalloc (ctx->grub_gettext_max
- * sizeof (ctx->grub_gettext_msg_list[0]));
+ ctx->grub_gettext_msg_list = grub_calloc (ctx->grub_gettext_max,
+ sizeof (ctx->grub_gettext_msg_list[0]));
if (!ctx->grub_gettext_msg_list)
{
grub_file_close (fd);
--
2.48.1

View File

@@ -1,56 +0,0 @@
From 1f8d74717d2bebd1206143c1acbf720be9097011 Mon Sep 17 00:00:00 2001
From: Lidong Chen <lidong.chen@oracle.com>
Date: Fri, 22 Nov 2024 06:27:57 +0000
Subject: [PATCH 15/20] gettext: Integer overflow leads to heap OOB write
The size calculation of the translation buffer in
grub_gettext_getstr_from_position() may overflow
to 0 leading to heap OOB write. This patch fixes
the issue by using grub_add() and checking for
an overflow.
Fixes: CVE-2024-45777
Reported-by: Nils Langius <nils@langius.de>
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Alec Brown <alec.r.brown@oracle.com>
---
grub-core/gettext/gettext.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/grub-core/gettext/gettext.c b/grub-core/gettext/gettext.c
index 63bb1ab73f..9ffc734284 100644
--- a/grub-core/gettext/gettext.c
+++ b/grub-core/gettext/gettext.c
@@ -26,6 +26,7 @@
#include <grub/file.h>
#include <grub/kernel.h>
#include <grub/i18n.h>
+#include <grub/safemath.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -99,6 +100,7 @@ grub_gettext_getstr_from_position (struct grub_gettext_context *ctx,
char *translation;
struct string_descriptor desc;
grub_err_t err;
+ grub_size_t alloc_sz;
internal_position = (off + position * sizeof (desc));
@@ -109,7 +111,10 @@ grub_gettext_getstr_from_position (struct grub_gettext_context *ctx,
length = grub_cpu_to_le32 (desc.length);
offset = grub_cpu_to_le32 (desc.offset);
- translation = grub_malloc (length + 1);
+ if (grub_add (length, 1, &alloc_sz))
+ return NULL;
+
+ translation = grub_malloc (alloc_sz);
if (!translation)
return NULL;
--
2.48.1

View File

@@ -1,72 +0,0 @@
From fd945966dc04c01765dcf129d8884f0b22991e74 Mon Sep 17 00:00:00 2001
From: Jonathan Bar Or <jonathanbaror@gmail.com>
Date: Thu, 23 Jan 2025 19:17:05 +0100
Subject: [PATCH 16/20] commands/read: Fix an integer overflow when supplying
more than 2^31 characters
The grub_getline() function currently has a signed integer variable "i"
that can be overflown when user supplies more than 2^31 characters.
It results in a memory corruption of the allocated line buffer as well
as supplying large negative values to grub_realloc().
Fixes: CVE-2025-0690
Reported-by: Jonathan Bar Or <jonathanbaror@gmail.com>
Signed-off-by: Jonathan Bar Or <jonathanbaror@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/commands/read.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/grub-core/commands/read.c b/grub-core/commands/read.c
index 9bbc523f6b..b8597692e2 100644
--- a/grub-core/commands/read.c
+++ b/grub-core/commands/read.c
@@ -26,6 +26,7 @@
#include <grub/types.h>
#include <grub/extcmd.h>
#include <grub/i18n.h>
+#include <grub/safemath.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -38,13 +39,14 @@ static const struct grub_arg_option options[] =
static char *
grub_getline (int silent)
{
- int i;
+ grub_size_t i;
char *line;
char *tmp;
int c;
+ grub_size_t alloc_size;
i = 0;
- line = grub_malloc (1 + i + sizeof('\0'));
+ line = grub_malloc (1 + sizeof('\0'));
if (! line)
return NULL;
@@ -60,8 +62,17 @@ grub_getline (int silent)
line[i] = (char) c;
if (!silent)
grub_printf ("%c", c);
- i++;
- tmp = grub_realloc (line, 1 + i + sizeof('\0'));
+ if (grub_add (i, 1, &i))
+ {
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
+ return NULL;
+ }
+ if (grub_add (i, 1 + sizeof('\0'), &alloc_size))
+ {
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
+ return NULL;
+ }
+ tmp = grub_realloc (line, alloc_size);
if (! tmp)
{
grub_free (line);
--
2.48.1

View File

@@ -1,37 +0,0 @@
From 0f62a673fe00e83984810b7ec61b2d9a0bb8b9d4 Mon Sep 17 00:00:00 2001
From: B Horn <b@horn.uk>
Date: Thu, 18 Apr 2024 20:29:39 +0100
Subject: [PATCH 17/20] commands/minicmd: Block the dump command in lockdown
mode
The dump enables a user to read memory which should not be possible
in lockdown mode.
Fixes: CVE-2025-1118
Reported-by: B Horn <b@horn.uk>
Reported-by: Jonathan Bar Or <jonathanbaror@gmail.com>
Signed-off-by: B Horn <b@horn.uk>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/commands/minicmd.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c
index fa498931ed..903af33131 100644
--- a/grub-core/commands/minicmd.c
+++ b/grub-core/commands/minicmd.c
@@ -203,8 +203,8 @@ GRUB_MOD_INIT(minicmd)
grub_register_command ("help", grub_mini_cmd_help,
0, N_("Show this message."));
cmd_dump =
- grub_register_command ("dump", grub_mini_cmd_dump,
- N_("ADDR [SIZE]"), N_("Show memory contents."));
+ grub_register_command_lockdown ("dump", grub_mini_cmd_dump,
+ N_("ADDR [SIZE]"), N_("Show memory contents."));
cmd_rmmod =
grub_register_command ("rmmod", grub_mini_cmd_rmmod,
N_("MODULE"), N_("Remove a module."));
--
2.48.1

Some files were not shown because too many files have changed in this diff Show More