From d9083613d341d204ad1944a565ce0ab1284ad36cf665c4b7d65b797ce3182bdb Mon Sep 17 00:00:00 2001 From: Michael Chang Date: Mon, 13 Mar 2023 10:05:13 +0000 Subject: [PATCH] Accepting request 1071066 from home:michael-chang:branches:Base:System - Discard cached key from grub shell and editor mode * 0001-clean-up-crypttab-and-linux-modules-dependency.patch * 0002-discard-cached-key-before-entering-grub-shell-and-ed.patch - Make grub more robust against storage race condition causing system boot failures (bsc#1189036) * 0001-ieee1275-ofdisk-retry-on-open-and-read-failure.patch OBS-URL: https://build.opensuse.org/request/show/1071066 OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=443 --- ...rypttab-and-linux-modules-dependency.patch | 197 ++++++++++++++++++ ...fdisk-retry-on-open-and-read-failure.patch | 126 +++++++++++ ...ey-before-entering-grub-shell-and-ed.patch | 88 ++++++++ grub2.changes | 14 ++ grub2.spec | 4 + 5 files changed, 429 insertions(+) create mode 100644 0001-clean-up-crypttab-and-linux-modules-dependency.patch create mode 100644 0001-ieee1275-ofdisk-retry-on-open-and-read-failure.patch create mode 100644 0002-discard-cached-key-before-entering-grub-shell-and-ed.patch diff --git a/0001-clean-up-crypttab-and-linux-modules-dependency.patch b/0001-clean-up-crypttab-and-linux-modules-dependency.patch new file mode 100644 index 0000000..712e53d --- /dev/null +++ b/0001-clean-up-crypttab-and-linux-modules-dependency.patch @@ -0,0 +1,197 @@ +From e9422d6869f1b2d78a7cfbfcae1610953d87705b Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Thu, 16 Feb 2023 21:28:07 +0800 +Subject: [PATCH 1/2] clean up crypttab and linux modules dependency + +The linux module could have quite a few dependency to other modules, the +i386-pc build in particular has many. + + linux: normal vbe video boot cmdline relocator mmap + +That will be easy to cause loop dependency if one of these modules has +to require function from linux. To avoid falling into the pitfall in +future extension, we move away the key publish related function from +linux to crypttab module in that it is also a right thing to do. + +Signed-off-by: Michael Chang +--- + grub-core/commands/crypttab.c | 48 +++++++++++++++++++++++++++++- + grub-core/disk/cryptodisk.c | 2 +- + grub-core/loader/linux.c | 55 +---------------------------------- + include/grub/crypttab.h | 22 ++++++++++++++ + include/grub/linux.h | 3 -- + 5 files changed, 71 insertions(+), 59 deletions(-) + create mode 100644 include/grub/crypttab.h + +--- a/grub-core/commands/crypttab.c ++++ b/grub-core/commands/crypttab.c +@@ -3,10 +3,52 @@ + #include + #include + #include +-#include ++#include ++#include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + ++struct grub_key_publisher *kpuber; ++ ++grub_err_t ++grub_initrd_publish_key (const char *uuid, const char *key, grub_size_t key_len, const char *path) ++{ ++ struct grub_key_publisher *cur = grub_named_list_find (GRUB_AS_NAMED_LIST (kpuber), uuid); ++ ++ if (!cur) ++ cur = grub_zalloc (sizeof (*cur)); ++ if (!cur) ++ return grub_errno; ++ ++ if (key && key_len) ++ { ++ grub_free (cur->key); ++ cur->key = grub_malloc (key_len); ++ if (!cur->key) ++ { ++ grub_free (cur); ++ return grub_errno; ++ } ++ grub_memcpy (cur->key, key, key_len); ++ cur->key_len = key_len; ++ } ++ ++ if (path) ++ { ++ grub_free (cur->path); ++ cur->path = grub_strdup (path); ++ } ++ ++ if (!cur->name) ++ { ++ cur->name = grub_strdup (uuid); ++ grub_list_push (GRUB_AS_LIST_P (&kpuber), GRUB_AS_LIST (cur)); ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ + static grub_err_t + grub_cmd_crypttab_entry (grub_command_t cmd __attribute__ ((unused)), + int argc, char **argv) +--- a/grub-core/disk/cryptodisk.c ++++ b/grub-core/disk/cryptodisk.c +@@ -31,7 +31,7 @@ + #ifdef GRUB_UTIL + #include + #else +-#include ++#include + #endif + + GRUB_MOD_LICENSE ("GPLv3+"); +--- a/grub-core/loader/linux.c ++++ b/grub-core/loader/linux.c +@@ -6,6 +6,7 @@ + #include + #include + #include ++#include + + struct newc_head + { +@@ -40,18 +41,6 @@ + struct dir *child; + }; + +-struct grub_key_publisher +-{ +- struct grub_key_publisher *next; +- struct grub_key_publisher **prev; +- char *name; /* UUID */ +- char *path; +- char *key; +- grub_size_t key_len; +-}; +- +-static struct grub_key_publisher *kpuber; +- + static char + hex (grub_uint8_t val) + { +@@ -423,41 +412,3 @@ + root = 0; + return GRUB_ERR_NONE; + } +- +-grub_err_t +-grub_initrd_publish_key (const char *uuid, const char *key, grub_size_t key_len, const char *path) +-{ +- struct grub_key_publisher *cur = grub_named_list_find (GRUB_AS_NAMED_LIST (kpuber), uuid); +- +- if (!cur) +- cur = grub_zalloc (sizeof (*cur)); +- if (!cur) +- return grub_errno; +- +- if (key && key_len) +- { +- grub_free (cur->key); +- cur->key = grub_malloc (key_len); +- if (!cur->key) +- { +- grub_free (cur); +- return grub_errno; +- } +- grub_memcpy (cur->key, key, key_len); +- cur->key_len = key_len; +- } +- +- if (path) +- { +- grub_free (cur->path); +- cur->path = grub_strdup (path); +- } +- +- if (!cur->name) +- { +- cur->name = grub_strdup (uuid); +- grub_list_push (GRUB_AS_LIST_P (&kpuber), GRUB_AS_LIST (cur)); +- } +- +- return GRUB_ERR_NONE; +-} +--- /dev/null ++++ b/include/grub/crypttab.h +@@ -0,0 +1,22 @@ ++#ifndef GRUB_CRYPTTAB_HEADER ++#define GRUB_CRYPTTAB_HEADER 1 ++ ++#include ++#include ++ ++struct grub_key_publisher ++{ ++ struct grub_key_publisher *next; ++ struct grub_key_publisher **prev; ++ char *name; /* UUID */ ++ char *path; ++ char *key; ++ grub_size_t key_len; ++}; ++ ++extern struct grub_key_publisher *EXPORT_VAR (kpuber); ++ ++grub_err_t ++grub_initrd_publish_key (const char *uuid, const char *key, grub_size_t key_len, const char *path); ++ ++#endif /* ! GRUB_CRYPTTAB_HEADER */ +--- a/include/grub/linux.h ++++ b/include/grub/linux.h +@@ -22,6 +22,3 @@ + grub_err_t + grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx, + char *argv[], void *target); +- +-grub_err_t +-grub_initrd_publish_key (const char *uuid, const char *key, grub_size_t key_len, const char *path); diff --git a/0001-ieee1275-ofdisk-retry-on-open-and-read-failure.patch b/0001-ieee1275-ofdisk-retry-on-open-and-read-failure.patch new file mode 100644 index 0000000..ad9e0a3 --- /dev/null +++ b/0001-ieee1275-ofdisk-retry-on-open-and-read-failure.patch @@ -0,0 +1,126 @@ +From b99c45820f228ff5b881700eda95a017abf2e198 Mon Sep 17 00:00:00 2001 +From: Mukesh Kumar Chaurasiya +Date: Wed, 1 Mar 2023 15:08:05 +0530 +Subject: [PATCH] ieee1275/ofdisk: retry on open and read failure + +Sometimes, when booting from a very busy SAN, the access to the +disk can fail and then grub will eventually drop to grub prompt. +This scenario is more frequent when deploying many machines at +the same time using the same SAN. +This patch aims to force the ofdisk module to retry the open or +read function after it fails. We use MAX_RETRIES to specify the +amount of times it will try to access the disk before it +definitely fails. + +Signed-off-by: Mukesh Kumar Chaurasiya +--- + grub-core/disk/ieee1275/ofdisk.c | 65 +++++++++++++++++++++++++++++++- + 1 file changed, 63 insertions(+), 2 deletions(-) + +diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c +index c6cba0c8a..f4183a531 100644 +--- a/grub-core/disk/ieee1275/ofdisk.c ++++ b/grub-core/disk/ieee1275/ofdisk.c +@@ -24,6 +24,9 @@ + #include + #include + #include ++#include ++ ++#define RETRY_DEFAULT_TIMEOUT 15000 + + static char *last_devpath; + static grub_ieee1275_ihandle_t last_ihandle; +@@ -452,7 +455,7 @@ compute_dev_path (const char *name) + } + + static grub_err_t +-grub_ofdisk_open (const char *name, grub_disk_t disk) ++grub_ofdisk_open_real (const char *name, grub_disk_t disk) + { + grub_ieee1275_phandle_t dev; + char *devpath; +@@ -525,6 +528,41 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) + return 0; + } + ++static grub_uint64_t ++grub_ofdisk_disk_timeout(void) ++{ ++ if(grub_env_get("ofdisk_retry_timeout") != NULL) ++ { ++ grub_uint64_t retry = grub_strtoul(grub_env_get("ofdisk_retry_timeout"), 0, 10); ++ if(retry) ++ return retry; ++ } ++ ++ return RETRY_DEFAULT_TIMEOUT; ++} ++ ++static grub_err_t ++grub_ofdisk_open (const char *name, grub_disk_t disk) ++{ ++ grub_err_t err; ++ grub_uint64_t timeout = grub_get_time_ms () + grub_ofdisk_disk_timeout(); ++ ++ retry: ++ err = grub_ofdisk_open_real (name, disk); ++ ++ if (err == GRUB_ERR_UNKNOWN_DEVICE) ++ { ++ if (grub_get_time_ms () < timeout) ++ { ++ grub_dprintf ("ofdisk","Failed to open disk %s. Retrying...\n", name); ++ grub_errno = GRUB_ERR_NONE; ++ goto retry; ++ } ++ } ++ ++ return err; ++} ++ + static void + grub_ofdisk_close (grub_disk_t disk) + { +@@ -568,7 +606,7 @@ grub_ofdisk_prepare (grub_disk_t disk, grub_disk_addr_t sector) + } + + static grub_err_t +-grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector, ++grub_ofdisk_read_real (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, char *buf) + { + grub_err_t err; +@@ -587,6 +625,29 @@ grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector, + return 0; + } + ++static grub_err_t ++grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector, ++ grub_size_t size, char *buf) ++{ ++ grub_err_t err; ++ grub_uint64_t timeout = grub_get_time_ms () + grub_ofdisk_disk_timeout(); ++ ++ retry: ++ err = grub_ofdisk_read_real (disk, sector, size, buf); ++ ++ if (err == GRUB_ERR_READ_ERROR) ++ { ++ if (grub_get_time_ms () < timeout) ++ { ++ grub_dprintf ("ofdisk","Failed to read disk %s. Retrying...\n", (char*)disk->data); ++ grub_errno = GRUB_ERR_NONE; ++ goto retry; ++ } ++ } ++ ++ return err; ++} ++ + static grub_err_t + grub_ofdisk_write (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, const char *buf) +-- +2.39.2 + diff --git a/0002-discard-cached-key-before-entering-grub-shell-and-ed.patch b/0002-discard-cached-key-before-entering-grub-shell-and-ed.patch new file mode 100644 index 0000000..95faef3 --- /dev/null +++ b/0002-discard-cached-key-before-entering-grub-shell-and-ed.patch @@ -0,0 +1,88 @@ +From 2271da7522d8406c528d2a9079d810e140f8041a Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Fri, 3 Feb 2023 19:40:31 +0800 +Subject: [PATCH 2/2] discard cached key before entering grub shell and editor + mode + +The cached key is cleared in case of anyone poking around it by means of +the interactive shell offerings. + +Signed-off-by: Michael Chang +--- + grub-core/commands/crypttab.c | 16 ++++++++++++++++ + grub-core/normal/main.c | 2 ++ + grub-core/normal/menu_entry.c | 3 +++ + include/grub/crypttab.h | 2 ++ + 4 files changed, 23 insertions(+) + +--- a/grub-core/commands/crypttab.c ++++ b/grub-core/commands/crypttab.c +@@ -49,6 +49,22 @@ + return GRUB_ERR_NONE; + } + ++void ++grub_initrd_discard_key (void) ++{ ++ struct grub_key_publisher *cur, *nxt; ++ ++ FOR_LIST_ELEMENTS_SAFE (cur, nxt, kpuber) ++ { ++ grub_list_remove (GRUB_AS_LIST (cur)); ++ grub_memset (cur->key, 0, cur->key_len); ++ grub_free (cur->name); ++ grub_free (cur->path); ++ grub_free (cur->key); ++ grub_free (cur); ++ } ++} ++ + static grub_err_t + grub_cmd_crypttab_entry (grub_command_t cmd __attribute__ ((unused)), + int argc, char **argv) +--- a/grub-core/normal/main.c ++++ b/grub-core/normal/main.c +@@ -37,6 +37,7 @@ + #ifdef GRUB_MACHINE_IEEE1275 + #include + #endif ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -477,6 +478,7 @@ + return; + } + ++ grub_initrd_discard_key (); + grub_normal_reader_init (nested); + + while (1) +--- a/grub-core/normal/menu_entry.c ++++ b/grub-core/normal/menu_entry.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + enum update_mode + { +@@ -1262,6 +1263,8 @@ + return; + } + ++ grub_initrd_discard_key(); ++ + screen = make_screen (entry); + if (! screen) + return; +--- a/include/grub/crypttab.h ++++ b/include/grub/crypttab.h +@@ -19,4 +19,6 @@ + grub_err_t + grub_initrd_publish_key (const char *uuid, const char *key, grub_size_t key_len, const char *path); + ++void ++grub_initrd_discard_key (void); + #endif /* ! GRUB_CRYPTTAB_HEADER */ diff --git a/grub2.changes b/grub2.changes index 8c0cf1b..fc70764 100644 --- a/grub2.changes +++ b/grub2.changes @@ -1,3 +1,17 @@ +------------------------------------------------------------------- +Mon Mar 6 06:31:09 UTC 2023 - Michael Chang + +- Discard cached key from grub shell and editor mode + * 0001-clean-up-crypttab-and-linux-modules-dependency.patch + * 0002-discard-cached-key-before-entering-grub-shell-and-ed.patch + +------------------------------------------------------------------- +Fri Mar 3 07:48:56 UTC 2023 - Michael Chang + +- Make grub more robust against storage race condition causing system boot + failures (bsc#1189036) + * 0001-ieee1275-ofdisk-retry-on-open-and-read-failure.patch + ------------------------------------------------------------------- Wed Mar 1 02:58:07 UTC 2023 - Michael Chang diff --git a/grub2.spec b/grub2.spec index adabcfa..283d44d 100644 --- a/grub2.spec +++ b/grub2.spec @@ -498,6 +498,10 @@ Patch970: grub2-add-module-for-boot-loader-interface.patch Patch971: 0001-ieee1275-Further-increase-initially-allocated-heap-f.patch Patch972: 0002-tpm-Disable-tpm-verifier-if-tpm-is-not-present.patch Patch973: 0001-RISC-V-Handle-R_RISCV_CALL_PLT-reloc.patch +Patch974: 0001-clean-up-crypttab-and-linux-modules-dependency.patch +Patch975: 0002-discard-cached-key-before-entering-grub-shell-and-ed.patch +# Make grub more robust against storage race condition causing system boot failures (bsc#1189036) +Patch976: 0001-ieee1275-ofdisk-retry-on-open-and-read-failure.patch Requires: gettext-runtime %if 0%{?suse_version} >= 1140