From 3e026f665ced2a351429fa93e0bade8681332bf0fd5cb0092124ce9a1efea4cc Mon Sep 17 00:00:00 2001 From: Michael Chang Date: Mon, 19 Sep 2022 06:10:23 +0000 Subject: [PATCH] Accepting request 1004537 from home:gary_lin:branches:Base:System - Add safety measure to pcr snapshot by checking platform and tpm status * safe_tpm_pcr_snapshot.patch - Fix installation failure due to unavailable nvram device on ppc64le (bsc#1201361) * 0001-grub-install-set-point-of-no-return-for-powerpc-ieee1275.patch - Add patches to dynamically allocate additional memory regions for EFI systems (bsc#1202438) * 0001-mm-Allow-dynamically-requesting-additional-memory-re.patch * 0002-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch * 0003-kern-efi-mm-Extract-function-to-add-memory-regions.patch * 0004-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch * 0005-kern-efi-mm-Implement-runtime-addition-of-pages.patch - Enlarge the default heap size and defer the disk cache invalidation (bsc#1202438) * 0001-kern-efi-mm-Enlarge-the-default-heap-size.patch * 0002-mm-Defer-the-disk-cache-invalidation.patch - Add patches for ALP FDE support * 0001-devmapper-getroot-Have-devmapper-recognize-LUKS2.patch * 0002-devmapper-getroot-Set-up-cheated-LUKS2-cryptodisk-mo.patch * 0003-disk-cryptodisk-When-cheatmounting-use-the-sector-in.patch * 0004-normal-menu-Don-t-show-Booting-s-msg-when-auto-booti.patch * 0005-EFI-suppress-the-Welcome-to-GRUB-message-in-EFI-buil.patch * 0006-EFI-console-Do-not-set-colorstate-until-the-first-te.patch * 0007-EFI-console-Do-not-set-cursor-until-the-first-text-o.patch * 0008-linuxefi-Use-common-grub_initrd_load.patch * 0009-Add-crypttab_entry-to-obviate-the-need-to-input-pass.patch * 0010-templates-import-etc-crypttab-to-grub.cfg.patch OBS-URL: https://build.opensuse.org/request/show/1004537 OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=419 --- ...troot-Have-devmapper-recognize-LUKS2.patch | 53 +++ ...nt-of-no-return-for-powerpc-ieee1275.patch | 32 ++ ...efi-mm-Enlarge-the-default-heap-size.patch | 32 ++ ...ally-requesting-additional-memory-re.patch | 133 +++++++ ...e-tpm-verifier-if-tpm-is-not-present.patch | 88 +++++ ...t-Set-up-cheated-LUKS2-cryptodisk-mo.patch | 127 +++++++ ...ys-request-a-fixed-number-of-pages-o.patch | 106 ++++++ ...mm-Defer-the-disk-cache-invalidation.patch | 68 ++++ ...When-cheatmounting-use-the-sector-in.patch | 71 ++++ ...tract-function-to-add-memory-regions.patch | 86 +++++ ...ss-up-errors-from-add_memory_regions.patch | 89 +++++ ...t-show-Booting-s-msg-when-auto-booti.patch | 93 +++++ ...-Welcome-to-GRUB-message-in-EFI-buil.patch | 45 +++ ...-Implement-runtime-addition-of-pages.patch | 77 ++++ ...ot-set-colorstate-until-the-first-te.patch | 54 +++ ...ot-set-cursor-until-the-first-text-o.patch | 75 ++++ ...linuxefi-Use-common-grub_initrd_load.patch | 156 ++++++++ ...ry-to-obviate-the-need-to-input-pass.patch | 338 ++++++++++++++++++ ...ates-import-etc-crypttab-to-grub.cfg.patch | 81 +++++ efi-set-variable-with-attrs.patch | 51 +++ grub-install-record-pcrs.patch | 18 + grub-read-pcr.patch | 151 ++++++++ grub-unseal-debug.patch | 41 +++ grub2.changes | 56 +++ grub2.spec | 33 +- safe_tpm_pcr_snapshot.patch | 90 +++++ tpm-protector-dont-measure-sealed-key.patch | 15 + tpm-protector-export-secret-key.patch | 138 +++++++ tpm-record-pcrs.patch | 235 ++++++++++++ 29 files changed, 2631 insertions(+), 1 deletion(-) create mode 100644 0001-devmapper-getroot-Have-devmapper-recognize-LUKS2.patch create mode 100644 0001-grub-install-set-point-of-no-return-for-powerpc-ieee1275.patch create mode 100644 0001-kern-efi-mm-Enlarge-the-default-heap-size.patch create mode 100644 0001-mm-Allow-dynamically-requesting-additional-memory-re.patch create mode 100644 0001-tpm-Disable-tpm-verifier-if-tpm-is-not-present.patch create mode 100644 0002-devmapper-getroot-Set-up-cheated-LUKS2-cryptodisk-mo.patch create mode 100644 0002-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch create mode 100644 0002-mm-Defer-the-disk-cache-invalidation.patch create mode 100644 0003-disk-cryptodisk-When-cheatmounting-use-the-sector-in.patch create mode 100644 0003-kern-efi-mm-Extract-function-to-add-memory-regions.patch create mode 100644 0004-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch create mode 100644 0004-normal-menu-Don-t-show-Booting-s-msg-when-auto-booti.patch create mode 100644 0005-EFI-suppress-the-Welcome-to-GRUB-message-in-EFI-buil.patch create mode 100644 0005-kern-efi-mm-Implement-runtime-addition-of-pages.patch create mode 100644 0006-EFI-console-Do-not-set-colorstate-until-the-first-te.patch create mode 100644 0007-EFI-console-Do-not-set-cursor-until-the-first-text-o.patch create mode 100644 0008-linuxefi-Use-common-grub_initrd_load.patch create mode 100644 0009-Add-crypttab_entry-to-obviate-the-need-to-input-pass.patch create mode 100644 0010-templates-import-etc-crypttab-to-grub.cfg.patch create mode 100644 efi-set-variable-with-attrs.patch create mode 100644 grub-install-record-pcrs.patch create mode 100644 grub-read-pcr.patch create mode 100644 grub-unseal-debug.patch create mode 100644 safe_tpm_pcr_snapshot.patch create mode 100644 tpm-protector-dont-measure-sealed-key.patch create mode 100644 tpm-protector-export-secret-key.patch create mode 100644 tpm-record-pcrs.patch diff --git a/0001-devmapper-getroot-Have-devmapper-recognize-LUKS2.patch b/0001-devmapper-getroot-Have-devmapper-recognize-LUKS2.patch new file mode 100644 index 0000000..268417a --- /dev/null +++ b/0001-devmapper-getroot-Have-devmapper-recognize-LUKS2.patch @@ -0,0 +1,53 @@ +From ebe4ac49e800b18b539564169593ab1c6f163378 Mon Sep 17 00:00:00 2001 +From: Josselin Poiret via Grub-devel +Date: Tue, 14 Jun 2022 15:47:29 +0200 +Subject: [PATCH 01/10] devmapper/getroot: Have devmapper recognize LUKS2 + +Changes UUID comparisons so that LUKS1 and LUKS2 are both recognized +as being LUKS cryptodisks. +--- + grub-core/osdep/devmapper/getroot.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/grub-core/osdep/devmapper/getroot.c b/grub-core/osdep/devmapper/getroot.c +index 9ba5c98655..2bf4264cf0 100644 +--- a/grub-core/osdep/devmapper/getroot.c ++++ b/grub-core/osdep/devmapper/getroot.c +@@ -138,7 +138,8 @@ grub_util_get_dm_abstraction (const char *os_dev) + grub_free (uuid); + return GRUB_DEV_ABSTRACTION_LVM; + } +- if (strncmp (uuid, "CRYPT-LUKS1-", 12) == 0) ++ if (strncmp (uuid, "CRYPT-LUKS1-", sizeof ("CRYPT-LUKS1-") - 1) == 0 ++ || strncmp (uuid, "CRYPT-LUKS2-", sizeof ("CRYPT-LUKS2-") - 1) == 0) + { + grub_free (uuid); + return GRUB_DEV_ABSTRACTION_LUKS; +@@ -179,7 +180,9 @@ grub_util_pull_devmapper (const char *os_dev) + grub_util_pull_device (subdev); + } + } +- if (uuid && strncmp (uuid, "CRYPT-LUKS1-", sizeof ("CRYPT-LUKS1-") - 1) == 0 ++ if (uuid ++ && (strncmp (uuid, "CRYPT-LUKS1-", sizeof ("CRYPT-LUKS1-") - 1) == 0 ++ || strncmp (uuid, "CRYPT-LUKS2-", sizeof ("CRYPT-LUKS2-") - 1) == 0) + && lastsubdev) + { + char *grdev = grub_util_get_grub_dev (lastsubdev); +@@ -253,11 +256,11 @@ grub_util_get_devmapper_grub_dev (const char *os_dev) + { + char *dash; + +- dash = grub_strchr (uuid + sizeof ("CRYPT-LUKS1-") - 1, '-'); ++ dash = grub_strchr (uuid + sizeof ("CRYPT-LUKS*-") - 1, '-'); + if (dash) + *dash = 0; + grub_dev = grub_xasprintf ("cryptouuid/%s", +- uuid + sizeof ("CRYPT-LUKS1-") - 1); ++ uuid + sizeof ("CRYPT-LUKS*-") - 1); + grub_free (uuid); + return grub_dev; + } +-- +2.34.1 + diff --git a/0001-grub-install-set-point-of-no-return-for-powerpc-ieee1275.patch b/0001-grub-install-set-point-of-no-return-for-powerpc-ieee1275.patch new file mode 100644 index 0000000..47696be --- /dev/null +++ b/0001-grub-install-set-point-of-no-return-for-powerpc-ieee1275.patch @@ -0,0 +1,32 @@ +From grub-devel-bounces@gnu.org Thu Aug 25 08:11:08 2022 +From: Michael Chang +Date: Thu, 25 Aug 2022 14:05:01 +0800 +Subject: [PATCH] grub-install: set point of no return for powerpc-ieee1275 + install + +The point of no return is used to define a point where no change should +be reverted in a wake of fatal error that consequently aborts the +process. The powerpc-ieee1275 install apparently missed this point of no +return defintion that newly installed modules could be inadvertently +reverted after successful image embedding so that boot failure is +incurred due to inconsistent state. + +Signed-off-by: Michael Chang +[iluceno@suse.de: Backported to SLES-15-SP4] +Signed-off-by: Ismael Luceno +--- + util/grub-install.c | 1 + + 1 file changed, 1 insertion(+) + +Index: grub-2.06/util/grub-install.c +=================================================================== +--- grub-2.06.orig/util/grub-install.c ++++ grub-2.06/util/grub-install.c +@@ -2160,6 +2160,7 @@ main (int argc, char *argv[]) + { + grub_util_error ("%s", _("failed to copy Grub to the PReP partition")); + } ++ grub_set_install_backup_ponr (); + + if ((signed_grub_mode >= SIGNED_GRUB_FORCE) || ((signed_grub_mode == SIGNED_GRUB_AUTO) && (ppc_sb_state > 0))) + { diff --git a/0001-kern-efi-mm-Enlarge-the-default-heap-size.patch b/0001-kern-efi-mm-Enlarge-the-default-heap-size.patch new file mode 100644 index 0000000..149c5c1 --- /dev/null +++ b/0001-kern-efi-mm-Enlarge-the-default-heap-size.patch @@ -0,0 +1,32 @@ +From 3e08d9afd273b5dade84fec5f7f17113c47b6b75 Mon Sep 17 00:00:00 2001 +From: Gary Lin +Date: Fri, 2 Sep 2022 11:26:39 +0800 +Subject: [PATCH 1/2] kern/efi/mm: Enlarge the default heap size + +The default heap size (0x100000, 1MB) is not enough for the +openSUSE/SUSE theme, and the additional dynamical allocation of memory +regions significantly slows down the loading of the grub2 menu theme. +This commit increases the default heap size to 0x2000000, 32MB, and this +should be enough to cover the theme files. + +Signed-off-by: Gary Lin +--- + grub-core/kern/efi/mm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index 48380d3..70d3e3d 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -39,7 +39,7 @@ + #define MEMORY_MAP_SIZE 0x3000 + + /* The default heap size for GRUB itself in bytes. */ +-#define DEFAULT_HEAP_SIZE 0x100000 ++#define DEFAULT_HEAP_SIZE 0x2000000 + + static void *finish_mmap_buf = 0; + static grub_efi_uintn_t finish_mmap_size = 0; +-- +2.35.3 + diff --git a/0001-mm-Allow-dynamically-requesting-additional-memory-re.patch b/0001-mm-Allow-dynamically-requesting-additional-memory-re.patch new file mode 100644 index 0000000..364e106 --- /dev/null +++ b/0001-mm-Allow-dynamically-requesting-additional-memory-re.patch @@ -0,0 +1,133 @@ +From 23bca58a68264657f176885c3564d07c9938b7f6 Mon Sep 17 00:00:00 2001 +From: Patrick Steinhardt +Date: Thu, 21 Apr 2022 15:24:18 +1000 +Subject: [PATCH 1/5] mm: Allow dynamically requesting additional memory + regions + +Currently, all platforms will set up their heap on initialization of the +platform code. While this works mostly fine, it poses some limitations +on memory management on us. Most notably, allocating big chunks of +memory in the gigabyte range would require us to pre-request this many +bytes from the firmware and add it to the heap from the beginning on +some platforms like EFI. As this isn't needed for most configurations, +it is inefficient and may even negatively impact some usecases when, +e.g., chainloading. Nonetheless, allocating big chunks of memory is +required sometimes, where one example is the upcoming support for the +Argon2 key derival function in LUKS2. + +In order to avoid pre-allocating big chunks of memory, this commit +implements a runtime mechanism to add more pages to the system. When +a given allocation cannot be currently satisfied, we'll call a given +callback set up by the platform's own memory management subsystem, +asking it to add a memory area with at least "n" bytes. If this +succeeds, we retry searching for a valid memory region, which should +now succeed. + +If this fails, we try asking for "n" bytes, possibly spread across +multiple regions, in hopes that region merging means that we end up +with enough memory for things to work out. + +Signed-off-by: Patrick Steinhardt +Signed-off-by: Daniel Axtens +Tested-by: Stefan Berger +Reviewed-by: Daniel Kiper +Tested-by: Patrick Steinhardt +--- + grub-core/kern/mm.c | 30 ++++++++++++++++++++++++++++++ + include/grub/mm.h | 18 ++++++++++++++++++ + 2 files changed, 48 insertions(+) + +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index 5c0a624..0bd9f75 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -28,6 +28,9 @@ + - multiple regions may be used as free space. They may not be + contiguous. + ++ - if existing regions are insufficient to satisfy an allocation, a new ++ region can be requested from firmware. ++ + Regions are managed by a singly linked list, and the meta information is + stored in the beginning of each region. Space after the meta information + is used to allocate memory. +@@ -77,6 +80,7 @@ + + + grub_mm_region_t grub_mm_base; ++grub_mm_add_region_func_t grub_mm_add_region_fn; + + /* Get a header from the pointer PTR, and set *P and *R to a pointer + to the header and a pointer to its region, respectively. PTR must +@@ -364,6 +368,32 @@ grub_memalign (grub_size_t align, grub_size_t size) + goto again; + #endif + ++ case 1: ++ /* Request additional pages, contiguous */ ++ count++; ++ ++ if (grub_mm_add_region_fn != NULL && ++ grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_CONSECUTIVE) == GRUB_ERR_NONE) ++ goto again; ++ ++ /* fallthrough */ ++ ++ case 2: ++ /* Request additional pages, anything at all */ ++ count++; ++ ++ if (grub_mm_add_region_fn != NULL) ++ { ++ /* ++ * Try again even if this fails, in case it was able to partially ++ * satisfy the request ++ */ ++ grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_NONE); ++ goto again; ++ } ++ ++ /* fallthrough */ ++ + default: + break; + } +diff --git a/include/grub/mm.h b/include/grub/mm.h +index 1754635..67faebf 100644 +--- a/include/grub/mm.h ++++ b/include/grub/mm.h +@@ -20,6 +20,7 @@ + #ifndef GRUB_MM_H + #define GRUB_MM_H 1 + ++#include + #include + #include + #include +@@ -28,6 +29,23 @@ + # define NULL ((void *) 0) + #endif + ++#define GRUB_MM_ADD_REGION_NONE 0 ++#define GRUB_MM_ADD_REGION_CONSECUTIVE (1 << 0) ++ ++/* ++ * Function used to request memory regions of `grub_size_t` bytes. The second ++ * parameter is a bitfield of `GRUB_MM_ADD_REGION` flags. ++ */ ++typedef grub_err_t (*grub_mm_add_region_func_t) (grub_size_t, unsigned int); ++ ++/* ++ * Set this function pointer to enable adding memory-regions at runtime in case ++ * a memory allocation cannot be satisfied with existing regions. ++ */ ++#ifndef GRUB_MACHINE_EMU ++extern grub_mm_add_region_func_t EXPORT_VAR(grub_mm_add_region_fn); ++#endif ++ + void grub_mm_init_region (void *addr, grub_size_t size); + void *EXPORT_FUNC(grub_malloc) (grub_size_t size); + void *EXPORT_FUNC(grub_zalloc) (grub_size_t size); +-- +2.35.3 + diff --git a/0001-tpm-Disable-tpm-verifier-if-tpm-is-not-present.patch b/0001-tpm-Disable-tpm-verifier-if-tpm-is-not-present.patch new file mode 100644 index 0000000..1deb5b2 --- /dev/null +++ b/0001-tpm-Disable-tpm-verifier-if-tpm-is-not-present.patch @@ -0,0 +1,88 @@ +From 12378be5243c1c02ce28de2e5703e87197c69157 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Mon, 29 Aug 2022 11:28:28 +0800 +Subject: [PATCH] tpm: Disable tpm verifier if tpm is not present + +This helps to prevent out of memory error when reading large files via disablig +tpm device as verifier has to read all content into memory in one chunk to +measure the hash and extend to tpm. + +Signed-off-by: Michael Chang +--- + grub-core/commands/efi/tpm.c | 37 +++++++++++++++++++++++++++++++++++++ + grub-core/commands/tpm.c | 4 ++++ + include/grub/tpm.h | 1 + + 3 files changed, 42 insertions(+) + +--- a/grub-core/commands/efi/tpm.c ++++ b/grub-core/commands/efi/tpm.c +@@ -349,3 +349,40 @@ + + return result; + } ++ ++int ++grub_tpm_present () ++{ ++ grub_efi_handle_t tpm_handle; ++ grub_efi_uint8_t protocol_version; ++ ++ if (!grub_tpm_handle_find (&tpm_handle, &protocol_version)) ++ return 0; ++ ++ if (protocol_version == 1) ++ { ++ grub_efi_tpm_protocol_t *tpm; ++ ++ tpm = grub_efi_open_protocol (tpm_handle, &tpm_guid, ++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ if (!tpm) ++ { ++ grub_dprintf ("tpm", "Cannot open TPM protocol\n"); ++ return 0; ++ } ++ return grub_tpm1_present (tpm); ++ } ++ else ++ { ++ grub_efi_tpm2_protocol_t *tpm; ++ ++ tpm = grub_efi_open_protocol (tpm_handle, &tpm2_guid, ++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ if (!tpm) ++ { ++ grub_dprintf ("tpm", "Cannot open TPM protocol\n"); ++ return 0; ++ } ++ return grub_tpm2_present (tpm); ++ } ++} +--- a/grub-core/commands/tpm.c ++++ b/grub-core/commands/tpm.c +@@ -291,6 +291,8 @@ + + GRUB_MOD_INIT (tpm) + { ++ if (!grub_tpm_present()) ++ return; + grub_verifier_register (&grub_tpm_verifier); + + cmd = grub_register_extcmd ("tpm_record_pcrs", grub_tpm_record_pcrs, 0, +@@ -301,6 +303,8 @@ + + GRUB_MOD_FINI (tpm) + { ++ if (!grub_tpm_present()) ++ return; + grub_verifier_unregister (&grub_tpm_verifier); + grub_unregister_extcmd (cmd); + } +--- a/include/grub/tpm.h ++++ b/include/grub/tpm.h +@@ -44,5 +44,6 @@ + grub_uint8_t pcr, const char *description); + struct grub_tpm_digest *grub_tpm_read_pcr (grub_uint8_t index, const char *algo); + void grub_tpm_digest_free (struct grub_tpm_digest *d); ++int grub_tpm_present (void); + + #endif diff --git a/0002-devmapper-getroot-Set-up-cheated-LUKS2-cryptodisk-mo.patch b/0002-devmapper-getroot-Set-up-cheated-LUKS2-cryptodisk-mo.patch new file mode 100644 index 0000000..a03e641 --- /dev/null +++ b/0002-devmapper-getroot-Set-up-cheated-LUKS2-cryptodisk-mo.patch @@ -0,0 +1,127 @@ +From a25627c13b7e1e6998a14b5dd23b04b28465d737 Mon Sep 17 00:00:00 2001 +From: Josselin Poiret via Grub-devel +Date: Tue, 14 Jun 2022 15:47:30 +0200 +Subject: [PATCH 02/10] devmapper/getroot: Set up cheated LUKS2 cryptodisk + mount from DM parameters + +This lets a LUKS2 cryptodisk have its cipher and hash filled out, +otherwise they wouldn't be initialized if cheat mounted. +--- + grub-core/osdep/devmapper/getroot.c | 91 +++++++++++++++++++++++++++++++++++- + 1 file changed, 90 insertions(+), 1 deletion(-) + +--- a/grub-core/osdep/devmapper/getroot.c ++++ b/grub-core/osdep/devmapper/getroot.c +@@ -51,6 +51,8 @@ + #include + #include + ++#include ++ + static int + grub_util_open_dm (const char *os_dev, struct dm_tree **tree, + struct dm_tree_node **node) +@@ -186,7 +188,6 @@ + && lastsubdev) + { + char *grdev = grub_util_get_grub_dev (lastsubdev); +- dm_tree_free (tree); + if (grdev) + { + grub_err_t err; +@@ -194,7 +195,95 @@ + if (err) + grub_util_error (_("can't mount encrypted volume `%s': %s"), + lastsubdev, grub_errmsg); ++ if (strncmp (uuid, "CRYPT-LUKS2-", sizeof ("CRYPT-LUKS2-") - 1) == 0) ++ { ++ /* set LUKS2 cipher from dm parameters, since it is not ++ * possible to determine the correct one without ++ * unlocking, as there might be multiple segments. ++ */ ++ grub_disk_t source; ++ grub_cryptodisk_t cryptodisk; ++ grub_uint64_t start, length; ++ char *target_type; ++ char *params; ++ const char *name; ++ char *cipher, *cipher_mode; ++ struct dm_task *dmt; ++ char *seek_head, *c; ++ unsigned int remaining; ++ ++ source = grub_disk_open (grdev); ++ cryptodisk = grub_cryptodisk_get_by_source_disk (source); ++ grub_disk_close (source); ++ ++ name = dm_tree_node_get_name (node); ++ ++ grub_util_info ("populating parameters of cryptomount `%s' from DM device `%s'", ++ uuid, name); ++ ++ dmt = dm_task_create (DM_DEVICE_TABLE); ++ if (dmt == 0) ++ grub_util_error (_("can't create dm task DM_DEVICE_TABLE")); ++ if (dm_task_set_name (dmt, name) == 0) ++ grub_util_error (_("can't set dm task name to `%s'"), name); ++ if (dm_task_run (dmt) == 0) ++ grub_util_error (_("can't run dm task for `%s'"), name); ++ /* dm_get_next_target doesn't have any error modes, everything has ++ * been handled by dm_task_run. ++ */ ++ dm_get_next_target (dmt, NULL, &start, &length, ++ &target_type, ¶ms); ++ if (strncmp (target_type, "crypt", sizeof ("crypt")) != 0) ++ grub_util_error (_("dm target of type `%s' is not `crypt'"), ++ target_type); ++ ++ /* dm target parameters for dm-crypt is ++ * [<#opt_params> ...] ++ */ ++ c = params; ++ remaining = grub_strlen (c); ++ ++ /* first, get the cipher name from the cipher */ ++ if (!(seek_head = grub_memchr (c, '-', remaining))) ++ grub_util_error (_("can't get cipher from dm-crypt parameters `%s'"), ++ params); ++ cipher = grub_strndup (c, seek_head - c); ++ remaining -= seek_head - c + 1; ++ c = seek_head + 1; ++ ++ /* now, the cipher mode */ ++ if (!(seek_head = grub_memchr (c, ' ', remaining))) ++ grub_util_error (_("can't get cipher mode from dm-crypt parameters `%s'"), ++ params); ++ cipher_mode = grub_strndup (c, seek_head - c); ++ remaining -= seek_head - c + 1; ++ c = seek_head + 1; ++ ++ err = grub_cryptodisk_setcipher (cryptodisk, cipher, cipher_mode); ++ if (err) ++ { ++ grub_util_error (_("can't set cipher of cryptodisk `%s' to `%s' with mode `%s'"), ++ uuid, cipher, cipher_mode); ++ } ++ ++ grub_free (cipher); ++ grub_free (cipher_mode); ++ ++ /* This is the only hash usable by PBKDF2, and we don't ++ * have Argon2 support yet, so set it by default, ++ * otherwise grub-probe would miss the required ++ * abstraction ++ */ ++ cryptodisk->hash = grub_crypto_lookup_md_by_name ("sha256"); ++ if (cryptodisk->hash == 0) ++ { ++ grub_util_error (_("can't lookup hash sha256 by name")); ++ } ++ ++ dm_task_destroy (dmt); ++ } + } ++ dm_tree_free (tree); + grub_free (grdev); + } + else diff --git a/0002-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch b/0002-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch new file mode 100644 index 0000000..b0f3ed4 --- /dev/null +++ b/0002-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch @@ -0,0 +1,106 @@ +From 834cb2ca9ed2d9d7a6926e598accdfe280b615da Mon Sep 17 00:00:00 2001 +From: Patrick Steinhardt +Date: Thu, 21 Apr 2022 15:24:19 +1000 +Subject: [PATCH 2/5] kern/efi/mm: Always request a fixed number of pages on + init + +When initializing the EFI memory subsystem, we will by default request +a quarter of the available memory, bounded by a minimum/maximum value. +Given that we're about to extend the EFI memory system to dynamically +request additional pages from the firmware as required, this scaling of +requested memory based on available memory will not make a lot of sense +anymore. + +Remove this logic as a preparatory patch such that we'll instead defer +to the runtime memory allocator. Note that ideally, we'd want to change +this after dynamic requesting of pages has been implemented for the EFI +platform. But because we'll need to split up initialization of the +memory subsystem and the request of pages from the firmware, we'd have +to duplicate quite some logic at first only to remove it afterwards +again. This seems quite pointless, so we instead have patches slightly +out of order. + +Signed-off-by: Patrick Steinhardt +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +Tested-by: Patrick Steinhardt +--- + grub-core/kern/efi/mm.c | 35 +++-------------------------------- + 1 file changed, 3 insertions(+), 32 deletions(-) + +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index 67a691d..2874522 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -38,9 +38,8 @@ + a multiplier of 4KB. */ + #define MEMORY_MAP_SIZE 0x3000 + +-/* The minimum and maximum heap size for GRUB itself. */ +-#define MIN_HEAP_SIZE 0x100000 +-#define MAX_HEAP_SIZE (1600 * 0x100000) ++/* The default heap size for GRUB itself in bytes. */ ++#define DEFAULT_HEAP_SIZE 0x100000 + + static void *finish_mmap_buf = 0; + static grub_efi_uintn_t finish_mmap_size = 0; +@@ -514,23 +513,6 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, + return filtered_desc; + } + +-/* Return the total number of pages. */ +-static grub_efi_uint64_t +-get_total_pages (grub_efi_memory_descriptor_t *memory_map, +- grub_efi_uintn_t desc_size, +- grub_efi_memory_descriptor_t *memory_map_end) +-{ +- grub_efi_memory_descriptor_t *desc; +- grub_efi_uint64_t total = 0; +- +- for (desc = memory_map; +- desc < memory_map_end; +- desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) +- total += desc->num_pages; +- +- return total; +-} +- + /* Add memory regions. */ + static void + add_memory_regions (grub_efi_memory_descriptor_t *memory_map, +@@ -619,8 +601,6 @@ grub_efi_mm_init (void) + grub_efi_memory_descriptor_t *filtered_memory_map_end; + grub_efi_uintn_t map_size; + grub_efi_uintn_t desc_size; +- grub_efi_uint64_t total_pages; +- grub_efi_uint64_t required_pages; + int mm_status; + + /* Prepare a memory region to store two memory maps. */ +@@ -660,22 +640,13 @@ grub_efi_mm_init (void) + filtered_memory_map_end = filter_memory_map (memory_map, filtered_memory_map, + desc_size, memory_map_end); + +- /* By default, request a quarter of the available memory. */ +- total_pages = get_total_pages (filtered_memory_map, desc_size, +- filtered_memory_map_end); +- required_pages = (total_pages >> 2); +- if (required_pages < BYTES_TO_PAGES (MIN_HEAP_SIZE)) +- required_pages = BYTES_TO_PAGES (MIN_HEAP_SIZE); +- else if (required_pages > BYTES_TO_PAGES (MAX_HEAP_SIZE)) +- required_pages = BYTES_TO_PAGES (MAX_HEAP_SIZE); +- + /* Sort the filtered descriptors, so that GRUB can allocate pages + from smaller regions. */ + sort_memory_map (filtered_memory_map, desc_size, filtered_memory_map_end); + + /* Allocate memory regions for GRUB's memory management. */ + add_memory_regions (filtered_memory_map, desc_size, +- filtered_memory_map_end, required_pages); ++ filtered_memory_map_end, BYTES_TO_PAGES (DEFAULT_HEAP_SIZE)); + + #if 0 + /* For debug. */ +-- +2.35.3 + diff --git a/0002-mm-Defer-the-disk-cache-invalidation.patch b/0002-mm-Defer-the-disk-cache-invalidation.patch new file mode 100644 index 0000000..ddab6ba --- /dev/null +++ b/0002-mm-Defer-the-disk-cache-invalidation.patch @@ -0,0 +1,68 @@ +From 4284d40799aaf5aab11c690f232ce0a191dcfbdb Mon Sep 17 00:00:00 2001 +From: Gary Lin +Date: Fri, 16 Sep 2022 10:59:55 +0800 +Subject: [PATCH 2/2] mm: Defer the disk cache invalidation + +When the heap memory is used up, the memory management code invalidates +the disk caches first and then requests the additional memory regioins. +Although this could minimize the memory usage, it hurts the loading time +since the disk caches may always miss. + +This patch defers the disk cache invalidation to avoid the possible +delays. + +Signen-off-by: Gary Lin +--- + grub-core/kern/mm.c | 22 +++++++--------------- + 1 file changed, 7 insertions(+), 15 deletions(-) + +diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c +index 0bd9f75..5280e8c 100644 +--- a/grub-core/kern/mm.c ++++ b/grub-core/kern/mm.c +@@ -355,20 +355,6 @@ grub_memalign (grub_size_t align, grub_size_t size) + switch (count) + { + case 0: +- /* Invalidate disk caches. */ +- grub_disk_cache_invalidate_all (); +- count++; +- goto again; +- +-#if 0 +- case 1: +- /* Unload unneeded modules. */ +- grub_dl_unload_unneeded (); +- count++; +- goto again; +-#endif +- +- case 1: + /* Request additional pages, contiguous */ + count++; + +@@ -378,7 +364,7 @@ grub_memalign (grub_size_t align, grub_size_t size) + + /* fallthrough */ + +- case 2: ++ case 1: + /* Request additional pages, anything at all */ + count++; + +@@ -394,6 +380,12 @@ grub_memalign (grub_size_t align, grub_size_t size) + + /* fallthrough */ + ++ case 2: ++ /* Invalidate disk caches. */ ++ grub_disk_cache_invalidate_all (); ++ count++; ++ goto again; ++ + default: + break; + } +-- +2.35.3 + diff --git a/0003-disk-cryptodisk-When-cheatmounting-use-the-sector-in.patch b/0003-disk-cryptodisk-When-cheatmounting-use-the-sector-in.patch new file mode 100644 index 0000000..a80501d --- /dev/null +++ b/0003-disk-cryptodisk-When-cheatmounting-use-the-sector-in.patch @@ -0,0 +1,71 @@ +From 5b694a13545224c2d21afc3e94831be1bcc85770 Mon Sep 17 00:00:00 2001 +From: Fabian Vogt +Date: Tue, 14 Jun 2022 15:55:21 +0200 +Subject: [PATCH 03/10] disk/cryptodisk: When cheatmounting, use the sector + info of the cheat device + +When using grub-probe with cryptodisk, the mapped block device from the host +is used directly instead of decrypting the source device in GRUB code. +In that case, the sector size and count of the host device needs to be used. +This is especially important when using luks2, which does not assign +total_sectors and log_sector_size when scanning, but only later when the +segments in the JSON area are evaluated. With an unset log_sector_size, +grub_open_device complains. + +This fixes grub-probe failing with +"error: sector sizes of 1 bytes aren't supported yet." + +Signed-off-by: Fabian Vogt +--- + grub-core/disk/cryptodisk.c | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c +index 6d22bf871c..ae8790f10f 100644 +--- a/grub-core/disk/cryptodisk.c ++++ b/grub-core/disk/cryptodisk.c +@@ -698,16 +698,31 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk) + if (!dev) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device"); + +- disk->log_sector_size = dev->log_sector_size; +- + #ifdef GRUB_UTIL + if (dev->cheat) + { ++ grub_uint64_t cheat_dev_size; ++ unsigned int cheat_log_sector_size; ++ + if (!GRUB_UTIL_FD_IS_VALID (dev->cheat_fd)) + dev->cheat_fd = grub_util_fd_open (dev->cheat, GRUB_UTIL_FD_O_RDONLY); + if (!GRUB_UTIL_FD_IS_VALID (dev->cheat_fd)) + return grub_error (GRUB_ERR_IO, N_("cannot open `%s': %s"), + dev->cheat, grub_util_fd_strerror ()); ++ ++ /* Use the sector size and count of the cheat device */ ++ cheat_dev_size = grub_util_get_fd_size (dev->cheat_fd, dev->cheat, &cheat_log_sector_size); ++ if (cheat_dev_size == -1) ++ { ++ const char *errmsg = grub_util_fd_strerror (); ++ grub_util_fd_close (dev->cheat_fd); ++ dev->cheat_fd = GRUB_UTIL_FD_INVALID; ++ return grub_error (GRUB_ERR_IO, N_("failed to query size of device `%s': %s"), ++ dev->cheat, errmsg); ++ } ++ ++ dev->log_sector_size = cheat_log_sector_size; ++ dev->total_sectors = cheat_dev_size >> cheat_log_sector_size; + } + #endif + +@@ -721,6 +736,7 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk) + } + + disk->data = dev; ++ disk->log_sector_size = dev->log_sector_size; + disk->total_sectors = dev->total_sectors; + disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE; + disk->id = dev->id; +-- +2.34.1 + diff --git a/0003-kern-efi-mm-Extract-function-to-add-memory-regions.patch b/0003-kern-efi-mm-Extract-function-to-add-memory-regions.patch new file mode 100644 index 0000000..e8cf6cd --- /dev/null +++ b/0003-kern-efi-mm-Extract-function-to-add-memory-regions.patch @@ -0,0 +1,86 @@ +From b4500ff77efe3b36256fae1e456ded65fd77cf04 Mon Sep 17 00:00:00 2001 +From: Patrick Steinhardt +Date: Thu, 21 Apr 2022 15:24:20 +1000 +Subject: [PATCH 3/5] kern/efi/mm: Extract function to add memory regions + +In preparation of support for runtime-allocating additional memory +region, this patch extracts the function to retrieve the EFI memory +map and add a subset of it to GRUB's own memory regions. + +Signed-off-by: Patrick Steinhardt +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +Tested-by: Patrick Steinhardt +--- + grub-core/kern/efi/mm.c | 21 +++++++++++++++------ + 1 file changed, 15 insertions(+), 6 deletions(-) + +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index 2874522..087272f 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -592,8 +592,8 @@ print_memory_map (grub_efi_memory_descriptor_t *memory_map, + } + #endif + +-void +-grub_efi_mm_init (void) ++static grub_err_t ++grub_efi_mm_add_regions (grub_size_t required_bytes) + { + grub_efi_memory_descriptor_t *memory_map; + grub_efi_memory_descriptor_t *memory_map_end; +@@ -606,7 +606,7 @@ grub_efi_mm_init (void) + /* Prepare a memory region to store two memory maps. */ + memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); + if (! memory_map) +- grub_fatal ("cannot allocate memory"); ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory for memory map"); + + /* Obtain descriptors for available memory. */ + map_size = MEMORY_MAP_SIZE; +@@ -624,14 +624,14 @@ grub_efi_mm_init (void) + + memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (map_size)); + if (! memory_map) +- grub_fatal ("cannot allocate memory"); ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory for new memory map"); + + mm_status = grub_efi_get_memory_map (&map_size, memory_map, 0, + &desc_size, 0); + } + + if (mm_status < 0) +- grub_fatal ("cannot get memory map"); ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "error fetching memory map from EFI"); + + memory_map_end = NEXT_MEMORY_DESCRIPTOR (memory_map, map_size); + +@@ -646,7 +646,7 @@ grub_efi_mm_init (void) + + /* Allocate memory regions for GRUB's memory management. */ + add_memory_regions (filtered_memory_map, desc_size, +- filtered_memory_map_end, BYTES_TO_PAGES (DEFAULT_HEAP_SIZE)); ++ filtered_memory_map_end, BYTES_TO_PAGES (required_bytes)); + + #if 0 + /* For debug. */ +@@ -664,6 +664,15 @@ grub_efi_mm_init (void) + /* Release the memory maps. */ + grub_efi_free_pages ((grub_addr_t) memory_map, + 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); ++ ++ return GRUB_ERR_NONE; ++} ++ ++void ++grub_efi_mm_init (void) ++{ ++ if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE) != GRUB_ERR_NONE) ++ grub_fatal ("%s", grub_errmsg); + } + + #if defined (__aarch64__) || defined (__arm__) || defined (__riscv) +-- +2.35.3 + diff --git a/0004-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch b/0004-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch new file mode 100644 index 0000000..d2416a9 --- /dev/null +++ b/0004-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch @@ -0,0 +1,89 @@ +From 4287786dde414d9b0517d12762904b4b2be19d2a Mon Sep 17 00:00:00 2001 +From: Patrick Steinhardt +Date: Thu, 21 Apr 2022 15:24:21 +1000 +Subject: [PATCH 4/5] kern/efi/mm: Pass up errors from add_memory_regions() + +The function add_memory_regions() is currently only called on system +initialization to allocate a fixed amount of pages. As such, it didn't +need to return any errors: in case it failed, we cannot proceed anyway. +This will change with the upcoming support for requesting more memory +from the firmware at runtime, where it doesn't make sense anymore to +fail hard. + +Refactor the function to return an error to prepare for this. Note that +this does not change the behaviour when initializing the memory system +because grub_efi_mm_init() knows to call grub_fatal() in case +grub_efi_mm_add_regions() returns an error. + +Signed-off-by: Patrick Steinhardt +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +Tested-by: Patrick Steinhardt +--- + grub-core/kern/efi/mm.c | 22 +++++++++++++++------- + 1 file changed, 15 insertions(+), 7 deletions(-) + +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index 087272f..45ea6d5 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -514,7 +514,7 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, + } + + /* Add memory regions. */ +-static void ++static grub_err_t + add_memory_regions (grub_efi_memory_descriptor_t *memory_map, + grub_efi_uintn_t desc_size, + grub_efi_memory_descriptor_t *memory_map_end, +@@ -542,9 +542,9 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map, + GRUB_EFI_ALLOCATE_ADDRESS, + GRUB_EFI_LOADER_CODE); + if (! addr) +- grub_fatal ("cannot allocate conventional memory %p with %u pages", +- (void *) ((grub_addr_t) start), +- (unsigned) pages); ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ "Memory starting at %p (%u pages) marked as free, but EFI would not allocate", ++ (void *) ((grub_addr_t) start), (unsigned) pages); + + grub_mm_init_region (addr, PAGES_TO_BYTES (pages)); + +@@ -554,7 +554,11 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map, + } + + if (required_pages > 0) +- grub_fatal ("too little memory"); ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ "could not allocate all requested memory: %" PRIuGRUB_UINT64_T " pages still required after iterating EFI memory map", ++ required_pages); ++ ++ return GRUB_ERR_NONE; + } + + void +@@ -601,6 +605,7 @@ grub_efi_mm_add_regions (grub_size_t required_bytes) + grub_efi_memory_descriptor_t *filtered_memory_map_end; + grub_efi_uintn_t map_size; + grub_efi_uintn_t desc_size; ++ grub_err_t err; + int mm_status; + + /* Prepare a memory region to store two memory maps. */ +@@ -645,8 +650,11 @@ grub_efi_mm_add_regions (grub_size_t required_bytes) + sort_memory_map (filtered_memory_map, desc_size, filtered_memory_map_end); + + /* Allocate memory regions for GRUB's memory management. */ +- add_memory_regions (filtered_memory_map, desc_size, +- filtered_memory_map_end, BYTES_TO_PAGES (required_bytes)); ++ err = add_memory_regions (filtered_memory_map, desc_size, ++ filtered_memory_map_end, ++ BYTES_TO_PAGES (required_bytes)); ++ if (err != GRUB_ERR_NONE) ++ return err; + + #if 0 + /* For debug. */ +-- +2.35.3 + diff --git a/0004-normal-menu-Don-t-show-Booting-s-msg-when-auto-booti.patch b/0004-normal-menu-Don-t-show-Booting-s-msg-when-auto-booti.patch new file mode 100644 index 0000000..cdfbc7a --- /dev/null +++ b/0004-normal-menu-Don-t-show-Booting-s-msg-when-auto-booti.patch @@ -0,0 +1,93 @@ +From d4eb747f831d8b011c712f4335f12b572d6f32d9 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 28 Jan 2022 11:30:32 +0100 +Subject: [PATCH 04/10] normal/menu: Don't show "Booting `%s'" msg when + auto-booting with TIMEOUT_STYLE_HIDDEN + +When the user has asked the menu code to be hidden/quiet and the current +entry is being autobooted because the timeout has expired don't show +the "Booting `%s'" msg. + +This is necessary to let flicker-free boots really be flicker free, +otherwise the "Booting `%s'" msg will kick the EFI fb into text mode +and show the msg, breaking the flicker-free experience. + +Signed-off-by: Hans de Goede +--- + grub-core/normal/menu.c | 24 ++++++++++++++++-------- + 1 file changed, 16 insertions(+), 8 deletions(-) + +diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c +index 47fc12551f..470bfc839b 100644 +--- a/grub-core/normal/menu.c ++++ b/grub-core/normal/menu.c +@@ -651,13 +651,15 @@ workaround_snapshot_menu_default_entry (grub_menu_t menu, const char *name, int + entry to be executed is a result of an automatic default selection because + of the timeout. */ + static int +-run_menu (grub_menu_t menu, int nested, int *auto_boot) ++run_menu (grub_menu_t menu, int nested, int *auto_boot, int *notify_boot) + { + grub_uint64_t saved_time; + int default_entry, current_entry; + int timeout; + enum timeout_style timeout_style; + ++ *notify_boot = 1; ++ + default_entry = get_entry_number (menu, "default"); + + workaround_snapshot_menu_default_entry (menu, "default", &default_entry); +@@ -734,6 +736,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) + if (timeout == 0) + { + *auto_boot = 1; ++ *notify_boot = timeout_style != TIMEOUT_STYLE_HIDDEN; + return default_entry; + } + +@@ -894,12 +897,16 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) + + /* Callback invoked immediately before a menu entry is executed. */ + static void +-notify_booting (grub_menu_entry_t entry, +- void *userdata __attribute__((unused))) ++notify_booting (grub_menu_entry_t entry, void *userdata) + { +- grub_printf (" "); +- grub_printf_ (N_("Booting `%s'"), entry->title); +- grub_printf ("\n\n"); ++ int *notify_boot = userdata; ++ ++ if (*notify_boot) ++ { ++ grub_printf (" "); ++ grub_printf_ (N_("Booting `%s'"), entry->title); ++ grub_printf ("\n\n"); ++ } + } + + /* Callback invoked when a default menu entry executed because of a timeout +@@ -947,8 +954,9 @@ show_menu (grub_menu_t menu, int nested, int autobooted) + int boot_entry; + grub_menu_entry_t e; + int auto_boot; ++ int notify_boot; + +- boot_entry = run_menu (menu, nested, &auto_boot); ++ boot_entry = run_menu (menu, nested, &auto_boot, ¬ify_boot); + if (boot_entry < 0) + break; + +@@ -960,7 +968,7 @@ show_menu (grub_menu_t menu, int nested, int autobooted) + + if (auto_boot) + grub_menu_execute_with_fallback (menu, e, autobooted, +- &execution_callback, 0); ++ &execution_callback, ¬ify_boot); + else + grub_menu_execute_entry (e, 0); + if (autobooted) +-- +2.34.1 + diff --git a/0005-EFI-suppress-the-Welcome-to-GRUB-message-in-EFI-buil.patch b/0005-EFI-suppress-the-Welcome-to-GRUB-message-in-EFI-buil.patch new file mode 100644 index 0000000..062fdf3 --- /dev/null +++ b/0005-EFI-suppress-the-Welcome-to-GRUB-message-in-EFI-buil.patch @@ -0,0 +1,45 @@ +From d9c7bfe88ce7391618192401c426c218d2a17795 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 28 Jan 2022 11:30:33 +0100 +Subject: [PATCH 05/10] EFI: suppress the "Welcome to GRUB!" message in EFI + builds + +Grub EFI builds are now often used in combination with flicker-free +boot, but this breaks with upstream grub because the "Welcome to GRUB!" +message will kick the EFI fb into text mode and show the msg, +breaking the flicker-free experience. + +EFI systems are so fast, that when the menu or the countdown are enabled +the message will be immediately overwritten, so in these cases not +printing the message does not matter. + +And in case when the timeout_style is set to TIMEOUT_STYLE_HIDDEN, +the user has asked grub to be quiet (for example to allow flickfree +boot) annd thus the message should not be printed. + +Signed-off-by: Hans de Goede +--- + grub-core/kern/main.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c +index 42ea96e39e..35dee404e8 100644 +--- a/grub-core/kern/main.c ++++ b/grub-core/kern/main.c +@@ -272,10 +272,13 @@ grub_main (void) + + grub_boot_time ("After machine init."); + ++ /* This breaks flicker-free boot on EFI systems, so disable it there. */ ++#ifndef GRUB_MACHINE_EFI + /* Hello. */ + grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); + grub_printf ("Welcome to GRUB!\n\n"); + grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); ++#endif + + #ifndef GRUB_MACHINE_PCBIOS + /* Init verifiers API. */ +-- +2.34.1 + diff --git a/0005-kern-efi-mm-Implement-runtime-addition-of-pages.patch b/0005-kern-efi-mm-Implement-runtime-addition-of-pages.patch new file mode 100644 index 0000000..5790670 --- /dev/null +++ b/0005-kern-efi-mm-Implement-runtime-addition-of-pages.patch @@ -0,0 +1,77 @@ +From 3a2119e11b9c216f3b008a2c61aca52b91ad7547 Mon Sep 17 00:00:00 2001 +From: Patrick Steinhardt +Date: Thu, 21 Apr 2022 15:24:22 +1000 +Subject: [PATCH 5/5] kern/efi/mm: Implement runtime addition of pages + +Adjust the interface of grub_efi_mm_add_regions() to take a set of +GRUB_MM_ADD_REGION_* flags, which most notably is currently only the +GRUB_MM_ADD_REGION_CONSECUTIVE flag. This allows us to set the function +up as callback for the memory subsystem and have it call out to us in +case there's not enough pages available in the current heap. + +Signed-off-by: Patrick Steinhardt +Signed-off-by: Daniel Axtens +Reviewed-by: Daniel Kiper +Tested-by: Patrick Steinhardt +--- + grub-core/kern/efi/mm.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c +index 45ea6d5..48380d3 100644 +--- a/grub-core/kern/efi/mm.c ++++ b/grub-core/kern/efi/mm.c +@@ -518,7 +518,8 @@ static grub_err_t + add_memory_regions (grub_efi_memory_descriptor_t *memory_map, + grub_efi_uintn_t desc_size, + grub_efi_memory_descriptor_t *memory_map_end, +- grub_efi_uint64_t required_pages) ++ grub_efi_uint64_t required_pages, ++ unsigned int flags) + { + grub_efi_memory_descriptor_t *desc; + +@@ -532,6 +533,10 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map, + + start = desc->physical_start; + pages = desc->num_pages; ++ ++ if (pages < required_pages && (flags & GRUB_MM_ADD_REGION_CONSECUTIVE)) ++ continue; ++ + if (pages > required_pages) + { + start += PAGES_TO_BYTES (pages - required_pages); +@@ -597,7 +602,7 @@ print_memory_map (grub_efi_memory_descriptor_t *memory_map, + #endif + + static grub_err_t +-grub_efi_mm_add_regions (grub_size_t required_bytes) ++grub_efi_mm_add_regions (grub_size_t required_bytes, unsigned int flags) + { + grub_efi_memory_descriptor_t *memory_map; + grub_efi_memory_descriptor_t *memory_map_end; +@@ -652,7 +657,8 @@ grub_efi_mm_add_regions (grub_size_t required_bytes) + /* Allocate memory regions for GRUB's memory management. */ + err = add_memory_regions (filtered_memory_map, desc_size, + filtered_memory_map_end, +- BYTES_TO_PAGES (required_bytes)); ++ BYTES_TO_PAGES (required_bytes), ++ flags); + if (err != GRUB_ERR_NONE) + return err; + +@@ -679,8 +685,9 @@ grub_efi_mm_add_regions (grub_size_t required_bytes) + void + grub_efi_mm_init (void) + { +- if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE) != GRUB_ERR_NONE) ++ if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE, GRUB_MM_ADD_REGION_NONE) != GRUB_ERR_NONE) + grub_fatal ("%s", grub_errmsg); ++ grub_mm_add_region_fn = grub_efi_mm_add_regions; + } + + #if defined (__aarch64__) || defined (__arm__) || defined (__riscv) +-- +2.35.3 + diff --git a/0006-EFI-console-Do-not-set-colorstate-until-the-first-te.patch b/0006-EFI-console-Do-not-set-colorstate-until-the-first-te.patch new file mode 100644 index 0000000..f556bc1 --- /dev/null +++ b/0006-EFI-console-Do-not-set-colorstate-until-the-first-te.patch @@ -0,0 +1,54 @@ +From 81339347bc10ec609227361434f75c5e36b85b9f Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 28 Jan 2022 12:43:48 +0100 +Subject: [PATCH 06/10] EFI: console: Do not set colorstate until the first + text output + +GRUB_MOD_INIT(normal) does an unconditional: + +grub_env_set ("color_normal", "light-gray/black"); + +which triggers a grub_term_setcolorstate() call. The original version +of the "efi/console: Do not set text-mode until we actually need it" patch: +https://lists.gnu.org/archive/html/grub-devel/2018-03/msg00125.html + +Protected against this by caching the requested state in +grub_console_setcolorstate () and then only applying it when the first +text output actually happens. During refactoring to move the +grub_console_setcolorstate () up higher in the grub-core/term/efi/console.c +file the code to cache the color-state + bail early was accidentally +dropped. + +Restore the cache the color-state + bail early behavior from the original. + +Cc: Javier Martinez Canillas +Fixes: 2d7c3abd871f ("efi/console: Do not set text-mode until we actually need it") +Signed-off-by: Hans de Goede +--- + grub-core/term/efi/console.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/grub-core/term/efi/console.c b/grub-core/term/efi/console.c +index 2f1ae85ba7..c44b2ac318 100644 +--- a/grub-core/term/efi/console.c ++++ b/grub-core/term/efi/console.c +@@ -82,6 +82,16 @@ grub_console_setcolorstate (struct grub_term_output *term + { + grub_efi_simple_text_output_interface_t *o; + ++ if (grub_efi_is_finished || text_mode != GRUB_TEXT_MODE_AVAILABLE) ++ { ++ /* ++ * Cache colorstate changes before the first text-output, this avoids ++ * "color_normal" environment writes causing a switch to textmode. ++ */ ++ text_colorstate = state; ++ return; ++ } ++ + if (grub_efi_is_finished) + return; + +-- +2.34.1 + diff --git a/0007-EFI-console-Do-not-set-cursor-until-the-first-text-o.patch b/0007-EFI-console-Do-not-set-cursor-until-the-first-text-o.patch new file mode 100644 index 0000000..531bec5 --- /dev/null +++ b/0007-EFI-console-Do-not-set-cursor-until-the-first-text-o.patch @@ -0,0 +1,75 @@ +From 9b12dc80d4254e22c41805cecf2494a8e6a50e3e Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 28 Jan 2022 12:43:49 +0100 +Subject: [PATCH 07/10] EFI: console: Do not set cursor until the first text + output + +To allow flickerfree boot the EFI console code does not call +grub_efi_set_text_mode (1) until some text is actually output. + +Depending on if the output text is because of an error loading +e.g. the .cfg file; or because of showing the menu the cursor needs +to be on or off when the first text is shown. + +So far the cursor was hardcoded to being on, but this is causing +drawing artifacts + slow drawing of the menu as reported here: +https://bugzilla.redhat.com/show_bug.cgi?id=1946969 + +Handle the cursorstate in the same way as the colorstate to fix this, +when no text has been output yet, just cache the cursorstate and +then use the last set value when the first text is output. + +Fixes: 2d7c3abd871f ("efi/console: Do not set text-mode until we actually need it") +Signed-off-by: Hans de Goede +--- + grub-core/term/efi/console.c | 19 ++++++++++++++++--- + 1 file changed, 16 insertions(+), 3 deletions(-) + +diff --git a/grub-core/term/efi/console.c b/grub-core/term/efi/console.c +index c44b2ac318..a3622e4fe5 100644 +--- a/grub-core/term/efi/console.c ++++ b/grub-core/term/efi/console.c +@@ -31,7 +31,15 @@ typedef enum { + } + grub_text_mode; + ++typedef enum { ++ GRUB_CURSOR_MODE_UNDEFINED = -1, ++ GRUB_CURSOR_MODE_OFF = 0, ++ GRUB_CURSUR_MODE_ON ++} ++grub_cursor_mode; ++ + static grub_text_mode text_mode = GRUB_TEXT_MODE_UNDEFINED; ++static grub_cursor_mode cursor_mode = GRUB_CURSOR_MODE_UNDEFINED; + static grub_term_color_state text_colorstate = GRUB_TERM_COLOR_UNDEFINED; + + static grub_uint32_t +@@ -119,8 +127,12 @@ grub_console_setcursor (struct grub_term_output *term __attribute__ ((unused)), + { + grub_efi_simple_text_output_interface_t *o; + +- if (grub_efi_is_finished) +- return; ++ if (grub_efi_is_finished || text_mode != GRUB_TEXT_MODE_AVAILABLE) ++ { ++ /* Cache cursor changes before the first text-output */ ++ cursor_mode = on; ++ return; ++ } + + o = grub_efi_system_table->con_out; + efi_call_2 (o->enable_cursor, o, on); +@@ -143,7 +155,8 @@ grub_prepare_for_text_output (struct grub_term_output *term) + return GRUB_ERR_BAD_DEVICE; + } + +- grub_console_setcursor (term, 1); ++ if (cursor_mode != GRUB_CURSOR_MODE_UNDEFINED) ++ grub_console_setcursor (term, cursor_mode); + if (text_colorstate != GRUB_TERM_COLOR_UNDEFINED) + grub_console_setcolorstate (term, text_colorstate); + text_mode = GRUB_TEXT_MODE_AVAILABLE; +-- +2.34.1 + diff --git a/0008-linuxefi-Use-common-grub_initrd_load.patch b/0008-linuxefi-Use-common-grub_initrd_load.patch new file mode 100644 index 0000000..2f0209e --- /dev/null +++ b/0008-linuxefi-Use-common-grub_initrd_load.patch @@ -0,0 +1,156 @@ +From adf486860fe0d395579be8b01d4fda8b93377768 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Wed, 8 Jun 2022 16:04:12 +0800 +Subject: [PATCH 08/10] linuxefi: Use common grub_initrd_load + +By using the common initrd loading routine factored out allows to share between +features like concatenating initramfs component. + +For eg. + + initrdefi /initrd-5.16.15-1-default newc:grub.cfg:/grub2/grub.cfg + +The file /grub2/grub.cfg read off from root disk will be available to use as +/grub.cfg in the target initramfs loaded by grub. + +Signed-off-by: Michael Chang +--- + grub-core/loader/i386/efi/linux.c | 87 ++++--------------------------- + 1 file changed, 10 insertions(+), 77 deletions(-) + +diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c +index 6b06a8f2ff..f93395fc62 100644 +--- a/grub-core/loader/i386/efi/linux.c ++++ b/grub-core/loader/i386/efi/linux.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -146,44 +147,6 @@ grub_linuxefi_unload (void) + return GRUB_ERR_NONE; + } + +-#define BOUNCE_BUFFER_MAX 0x1000000ull +- +-static grub_ssize_t +-read(grub_file_t file, grub_uint8_t *bufp, grub_size_t len) +-{ +- grub_ssize_t bufpos = 0; +- static grub_size_t bbufsz = 0; +- static char *bbuf = NULL; +- +- if (bbufsz == 0) +- bbufsz = MIN(BOUNCE_BUFFER_MAX, len); +- +- while (!bbuf && bbufsz) +- { +- bbuf = grub_malloc(bbufsz); +- if (!bbuf) +- bbufsz >>= 1; +- } +- if (!bbuf) +- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate bounce buffer")); +- +- while (bufpos < (long long)len) +- { +- grub_ssize_t sz; +- +- sz = grub_file_read (file, bbuf, MIN(bbufsz, len - bufpos)); +- if (sz < 0) +- return sz; +- if (sz == 0) +- break; +- +- grub_memcpy(bufp + bufpos, bbuf, sz); +- bufpos += sz; +- } +- +- return bufpos; +-} +- + #define LOW_U32(val) ((grub_uint32_t)(((grub_addr_t)(val)) & 0xffffffffull)) + #define HIGH_U32(val) ((grub_uint32_t)(((grub_addr_t)(val) >> 32) & 0xffffffffull)) + +@@ -191,10 +154,8 @@ static grub_err_t + grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) + { +- grub_file_t *files = 0; +- int i, nfiles = 0; ++ struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 }; + grub_size_t size = 0; +- grub_uint8_t *ptr; + + if (argc == 0) + { +@@ -208,24 +169,10 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + +- files = grub_calloc (argc, sizeof (files[0])); +- if (!files) ++ if (grub_initrd_init (argc, argv, &initrd_ctx)) + goto fail; + +- for (i = 0; i < argc; i++) +- { +- files[i] = grub_file_open (argv[i], GRUB_FILE_TYPE_LINUX_INITRD +- | GRUB_FILE_TYPE_NO_DECOMPRESS); +- if (! files[i]) +- goto fail; +- nfiles++; +- if (grub_add (size, ALIGN_UP (grub_file_size (files[i]), 4), &size)) +- { +- grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); +- goto fail; +- } +- } +- ++ size = grub_get_initrd_size (&initrd_ctx); + initrd_mem = kernel_alloc(size, N_("can't allocate initrd")); + if (initrd_mem == NULL) + goto fail; +@@ -238,30 +185,16 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + params->ext_ramdisk_image = HIGH_U32(initrd_mem); + #endif + +- ptr = initrd_mem; +- +- for (i = 0; i < nfiles; i++) +- { +- grub_ssize_t cursize = grub_file_size (files[i]); +- if (read (files[i], ptr, cursize) != cursize) +- { +- if (!grub_errno) +- grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), +- argv[i]); +- goto fail; +- } +- ptr += cursize; +- grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4)); +- ptr += ALIGN_UP_OVERHEAD (cursize, 4); +- } ++ /* FIXME: Use bounce buffers as many UEFI machines apparently can't DMA ++ * correctly above 4GB ++ */ ++ if (grub_initrd_load (&initrd_ctx, argv, initrd_mem)) ++ goto fail; + + params->ramdisk_size = size; + + fail: +- for (i = 0; i < nfiles; i++) +- grub_file_close (files[i]); +- grub_free (files); +- ++ grub_initrd_close (&initrd_ctx); + if (initrd_mem && grub_errno) + grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)initrd_mem, BYTES_TO_PAGES(size)); + +-- +2.34.1 + diff --git a/0009-Add-crypttab_entry-to-obviate-the-need-to-input-pass.patch b/0009-Add-crypttab_entry-to-obviate-the-need-to-input-pass.patch new file mode 100644 index 0000000..72716fd --- /dev/null +++ b/0009-Add-crypttab_entry-to-obviate-the-need-to-input-pass.patch @@ -0,0 +1,338 @@ +From 749f7dee6f63217e536663aebb817aec72a65d5a Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Thu, 9 Jun 2022 21:06:00 +0800 +Subject: [PATCH 09/10] Add crypttab_entry to obviate the need to input + password twice + +This patch adds crypttab_entry command to hint grub where to put the key file +automatically loaded by linux cryptsetup. It's syntax is similar to +/etc/crypttab so that it is relatively straightforward to import. + + crypttab_entry + +For eg: + + crypttab_entry cr_root 5e1dd109e39343f984da57fd742d3f23 none + +Please note the "encrypted-device" only accepts UUID without dashes as it is +the only identification used by grub's cryptodisk device. The crypttab_entry +can also be used multiple times to specify encrypted volumes unlocked by +"cryptomount -a". + +Signed-off-by: Michael Chang +--- + grub-core/Makefile.core.def | 5 ++ + grub-core/commands/crypttab.c | 42 ++++++++++++ + grub-core/disk/cryptodisk.c | 5 ++ + grub-core/loader/linux.c | 126 ++++++++++++++++++++++++++++++++-- + include/grub/linux.h | 3 + + 5 files changed, 177 insertions(+), 4 deletions(-) + create mode 100644 grub-core/commands/crypttab.c + +Index: grub-2.06/grub-core/Makefile.core.def +=================================================================== +--- grub-2.06.orig/grub-core/Makefile.core.def ++++ grub-2.06/grub-core/Makefile.core.def +@@ -2643,3 +2643,8 @@ module = { + cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)'; + cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)'; + }; ++ ++module = { ++ name = crypttab; ++ common = commands/crypttab.c; ++}; +Index: grub-2.06/grub-core/commands/crypttab.c +=================================================================== +--- /dev/null ++++ grub-2.06/grub-core/commands/crypttab.c +@@ -0,0 +1,42 @@ ++ ++#include ++#include ++#include ++#include ++#include ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++static grub_err_t ++grub_cmd_crypttab_entry (grub_command_t cmd __attribute__ ((unused)), ++ int argc, char **argv) ++{ ++ char buf[64]; ++ const char *path = argv[2]; ++ ++ if (argc != 3) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("three arguments expected")); ++ ++ if (grub_strcmp (argv[2], "none") == 0 ++ || grub_strcmp (argv[2], "-") == 0) ++ { ++ grub_snprintf (buf, sizeof (buf), "/etc/cryptsetup-keys.d/%s.key", argv[0]); ++ path = buf; ++ } ++ ++ /*FIXME: Validate UUID string*/ ++ return grub_initrd_publish_key (argv[1], NULL, 0, path); ++} ++ ++static grub_command_t cmd; ++ ++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_MOD_FINI(crypttab) ++{ ++ grub_unregister_command (cmd); ++} +Index: grub-2.06/grub-core/disk/cryptodisk.c +=================================================================== +--- grub-2.06.orig/grub-core/disk/cryptodisk.c ++++ grub-2.06/grub-core/disk/cryptodisk.c +@@ -30,6 +30,8 @@ + + #ifdef GRUB_UTIL + #include ++#else ++#include + #endif + + GRUB_MOD_LICENSE ("GPLv3+"); +@@ -1146,6 +1148,10 @@ grub_cryptodisk_scan_device_real (const + dev = NULL; + + cleanup: ++#ifndef GRUB_UTIL ++ if (cargs->key_data) ++ grub_initrd_publish_key (dev->uuid, (const char *)cargs->key_data, cargs->key_len, NULL); ++#endif + if (askpass) + { + cargs->key_len = 0; +Index: grub-2.06/grub-core/loader/linux.c +=================================================================== +--- grub-2.06.orig/grub-core/loader/linux.c ++++ grub-2.06/grub-core/loader/linux.c +@@ -5,6 +5,7 @@ + #include + #include + #include ++#include + + struct newc_head + { +@@ -27,6 +28,7 @@ struct newc_head + struct grub_linux_initrd_component + { + grub_file_t file; ++ char *buf; + char *newc_name; + grub_off_t size; + }; +@@ -38,6 +40,18 @@ struct dir + 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) + { +@@ -149,6 +163,65 @@ insert_dir (const char *name, struct dir + return GRUB_ERR_NONE; + } + ++static grub_err_t ++grub_initrd_component (const char *buf, int bufsz, const char *newc_name, ++ struct grub_linux_initrd_context *initrd_ctx) ++{ ++ struct dir *root = 0; ++ struct grub_linux_initrd_component *comp = initrd_ctx->components + initrd_ctx->nfiles; ++ grub_size_t dir_size, name_len; ++ ++ while (*newc_name == '/') ++ newc_name++; ++ ++ initrd_ctx->size = ALIGN_UP (initrd_ctx->size, 4); ++ comp->newc_name = grub_strdup (newc_name); ++ if (!comp->newc_name || ++ insert_dir (comp->newc_name, &root, 0, &dir_size)) ++ { ++ /* FIXME: Check NULL file pointer before close */ ++ grub_initrd_close (initrd_ctx); ++ return grub_errno; ++ } ++ /* Should name_len count terminating null ? */ ++ name_len = grub_strlen (comp->newc_name) + 1; ++ if (grub_add (initrd_ctx->size, ++ ALIGN_UP (sizeof (struct newc_head) + name_len, 4), ++ &initrd_ctx->size) || ++ grub_add (initrd_ctx->size, dir_size, &initrd_ctx->size)) ++ goto overflow; ++ ++ comp->buf = grub_malloc (bufsz); ++ if (!comp->buf) ++ { ++ free_dir (root); ++ grub_initrd_close (initrd_ctx); ++ return grub_errno; ++ } ++ grub_memcpy (comp->buf, buf, bufsz); ++ initrd_ctx->nfiles++; ++ comp->size = bufsz; ++ if (grub_add (initrd_ctx->size, comp->size, ++ &initrd_ctx->size)) ++ goto overflow; ++ ++ initrd_ctx->size = ALIGN_UP (initrd_ctx->size, 4); ++ if (grub_add (initrd_ctx->size, ++ ALIGN_UP (sizeof (struct newc_head) ++ + sizeof ("TRAILER!!!") - 1, 4), ++ &initrd_ctx->size)) ++ goto overflow; ++ ++ free_dir (root); ++ root = 0; ++ return GRUB_ERR_NONE; ++ ++ overflow: ++ free_dir (root); ++ grub_initrd_close (initrd_ctx); ++ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); ++} ++ + grub_err_t + grub_initrd_init (int argc, char *argv[], + struct grub_linux_initrd_context *initrd_ctx) +@@ -156,11 +229,17 @@ grub_initrd_init (int argc, char *argv[] + int i; + int newc = 0; + struct dir *root = 0; ++ struct grub_key_publisher *pk; ++ int numkey = 0; + + initrd_ctx->nfiles = 0; + initrd_ctx->components = 0; + +- initrd_ctx->components = grub_calloc (argc, sizeof (initrd_ctx->components[0])); ++ FOR_LIST_ELEMENTS (pk, kpuber) ++ if (pk->key && pk->path) ++ numkey++; ++ ++ initrd_ctx->components = grub_calloc (argc + numkey, sizeof (initrd_ctx->components[0])); + if (!initrd_ctx->components) + return grub_errno; + +@@ -239,7 +318,10 @@ grub_initrd_init (int argc, char *argv[] + free_dir (root); + root = 0; + } +- ++ ++ FOR_LIST_ELEMENTS (pk, kpuber) ++ if (pk->key && pk->path) ++ grub_initrd_component (pk->key, pk->key_len, pk->path, initrd_ctx); + return GRUB_ERR_NONE; + + overflow: +@@ -263,7 +345,9 @@ grub_initrd_close (struct grub_linux_ini + for (i = 0; i < initrd_ctx->nfiles; i++) + { + grub_free (initrd_ctx->components[i].newc_name); +- grub_file_close (initrd_ctx->components[i].file); ++ if (initrd_ctx->components[i].file) ++ grub_file_close (initrd_ctx->components[i].file); ++ grub_free (initrd_ctx->components[i].buf); + } + grub_free (initrd_ctx->components); + initrd_ctx->components = 0; +@@ -297,7 +381,7 @@ grub_initrd_load (struct grub_linux_init + } + ptr += dir_size; + ptr = make_header (ptr, initrd_ctx->components[i].newc_name, +- grub_strlen (initrd_ctx->components[i].newc_name), ++ grub_strlen (initrd_ctx->components[i].newc_name) + 1, + 0100777, + initrd_ctx->components[i].size); + newc = 1; +@@ -312,7 +396,12 @@ grub_initrd_load (struct grub_linux_init + } + + cursize = initrd_ctx->components[i].size; +- if (grub_file_read (initrd_ctx->components[i].file, ptr, cursize) ++ if (initrd_ctx->components[i].buf) ++ { ++ grub_memcpy (ptr, initrd_ctx->components[i].buf, cursize); ++ newc = 1; ++ } ++ else if (grub_file_read (initrd_ctx->components[i].file, ptr, cursize) + != cursize) + { + if (!grub_errno) +@@ -333,3 +422,41 @@ grub_initrd_load (struct grub_linux_init + 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; ++} +Index: grub-2.06/include/grub/linux.h +=================================================================== +--- grub-2.06.orig/include/grub/linux.h ++++ grub-2.06/include/grub/linux.h +@@ -22,3 +22,6 @@ grub_initrd_close (struct grub_linux_ini + 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/0010-templates-import-etc-crypttab-to-grub.cfg.patch b/0010-templates-import-etc-crypttab-to-grub.cfg.patch new file mode 100644 index 0000000..b181685 --- /dev/null +++ b/0010-templates-import-etc-crypttab-to-grub.cfg.patch @@ -0,0 +1,81 @@ +From 2d3130c289b293269dcf558a26674f83f77729a6 Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Tue, 14 Jun 2022 17:10:01 +0800 +Subject: [PATCH 10/10] templates: import /etc/crypttab to grub.cfg + +The /etc/crypptab is used to setup location of encryption key files during +boot, among other things. It is useful to make use the information by grub to +determine where keys are being looked up. + +This script can be used to import relevant /etc/crypptab entry to grub.cfg. + +Signed-off-by: Michael Chang +--- + Makefile.util.def | 7 +++++++ + util/grub.d/05_crypttab.in | 36 ++++++++++++++++++++++++++++++++++++ + 2 files changed, 43 insertions(+) + create mode 100644 util/grub.d/05_crypttab.in + +diff --git a/Makefile.util.def b/Makefile.util.def +index 08f681cd8b..5e0ba22f3d 100644 +--- a/Makefile.util.def ++++ b/Makefile.util.def +@@ -476,6 +476,13 @@ script = { + installdir = grubconf; + }; + ++script = { ++ name = '05_crypttab'; ++ common = util/grub.d/05_crypttab.in; ++ installdir = grubconf; ++ condition = COND_HOST_LINUX; ++}; ++ + script = { + name = '10_windows'; + common = util/grub.d/10_windows.in; +diff --git a/util/grub.d/05_crypttab.in b/util/grub.d/05_crypttab.in +new file mode 100644 +index 0000000000..c539bc061e +--- /dev/null ++++ b/util/grub.d/05_crypttab.in +@@ -0,0 +1,36 @@ ++#! /bin/sh ++set -e ++ ++# grub-mkconfig helper script. ++# Copyright (C) 2022 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 . ++ ++prefix="@prefix@" ++exec_prefix="@exec_prefix@" ++datarootdir="@datarootdir@" ++ ++export TEXTDOMAIN=@PACKAGE@ ++export TEXTDOMAINDIR="@localedir@" ++ ++. "$pkgdatadir/grub-mkconfig_lib" ++ ++CRYPTTAB=/etc/crypttab ++ ++if [ -r "$CRYPTTAB" ]; then ++ awk '/UUID=/ { sub(/UUID=/,"",$2); \ ++ gsub(/-/,"",$2); \ ++ printf("crypttab_entry %s %s %s\n",$1,$2,$3) \ ++ }' "$CRYPTTAB" ++fi +-- +2.34.1 + diff --git a/efi-set-variable-with-attrs.patch b/efi-set-variable-with-attrs.patch new file mode 100644 index 0000000..d2959d0 --- /dev/null +++ b/efi-set-variable-with-attrs.patch @@ -0,0 +1,51 @@ +Index: grub-2.06/include/grub/efi/efi.h +=================================================================== +--- grub-2.06.orig/include/grub/efi/efi.h ++++ grub-2.06/include/grub/efi/efi.h +@@ -86,6 +86,11 @@ grub_efi_status_t EXPORT_FUNC (grub_efi_ + const grub_efi_guid_t *guid, + grub_size_t *datasize_out, + void **data_out); ++grub_err_t EXPORT_FUNC (grub_efi_set_variable_with_attributes) (const char *var, ++ const grub_efi_guid_t *guid, ++ grub_efi_uint32_t attributes, ++ void *data, ++ grub_size_t datasize); + grub_err_t + EXPORT_FUNC (grub_efi_set_variable) (const char *var, + const grub_efi_guid_t *guid, +Index: grub-2.06/grub-core/kern/efi/efi.c +=================================================================== +--- grub-2.06.orig/grub-core/kern/efi/efi.c ++++ grub-2.06/grub-core/kern/efi/efi.c +@@ -196,6 +196,17 @@ grub_err_t + grub_efi_set_variable(const char *var, const grub_efi_guid_t *guid, + void *data, grub_size_t datasize) + { ++ return grub_efi_set_variable_with_attributes(var, guid, ++ (GRUB_EFI_VARIABLE_NON_VOLATILE ++ | GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS ++ | GRUB_EFI_VARIABLE_RUNTIME_ACCESS), ++ data, datasize); ++} ++ ++grub_err_t ++grub_efi_set_variable_with_attributes(const char *var, const grub_efi_guid_t *guid, grub_efi_uint32_t attributes, ++ void *data, grub_size_t datasize) ++{ + grub_efi_status_t status; + grub_efi_runtime_services_t *r; + grub_efi_char16_t *var16; +@@ -211,10 +222,8 @@ grub_efi_set_variable(const char *var, c + + r = grub_efi_system_table->runtime_services; + +- status = efi_call_5 (r->set_variable, var16, guid, +- (GRUB_EFI_VARIABLE_NON_VOLATILE +- | GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS +- | GRUB_EFI_VARIABLE_RUNTIME_ACCESS), ++ status = efi_call_5 (r->set_variable, var16, guid, ++ attributes, + datasize, data); + grub_free (var16); + if (status == GRUB_EFI_SUCCESS) diff --git a/grub-install-record-pcrs.patch b/grub-install-record-pcrs.patch new file mode 100644 index 0000000..97ea0a1 --- /dev/null +++ b/grub-install-record-pcrs.patch @@ -0,0 +1,18 @@ +Index: grub-2.06/util/grub-install.c +=================================================================== +--- grub-2.06.orig/util/grub-install.c ++++ grub-2.06/util/grub-install.c +@@ -1457,6 +1457,13 @@ main (int argc, char *argv[]) + + grub_util_unlink (load_cfg); + ++ if (1) ++ { ++ load_cfg_f = grub_util_fopen (load_cfg, "wb"); ++ have_load_cfg = 1; ++ fprintf (load_cfg_f, "tpm_record_pcrs 0-9\n"); ++ } ++ + if (debug_image && debug_image[0]) + { + load_cfg_f = grub_util_fopen (load_cfg, "wb"); diff --git a/grub-read-pcr.patch b/grub-read-pcr.patch new file mode 100644 index 0000000..c4d0fa3 --- /dev/null +++ b/grub-read-pcr.patch @@ -0,0 +1,151 @@ +Index: grub-2.06/include/grub/tpm.h +=================================================================== +--- grub-2.06.orig/include/grub/tpm.h ++++ grub-2.06/include/grub/tpm.h +@@ -34,6 +34,15 @@ + + #define EV_IPL 0x0d + ++struct grub_tpm_digest { ++ const char * algorithm; ++ unsigned int size; ++ unsigned char value[1]; /* variable length */ ++}; ++ + grub_err_t grub_tpm_measure (unsigned char *buf, grub_size_t size, + grub_uint8_t pcr, const char *description); ++struct grub_tpm_digest *grub_tpm_read_pcr (grub_uint8_t index, const char *algo); ++void grub_tpm_digest_free (struct grub_tpm_digest *d); ++ + #endif +Index: grub-2.06/grub-core/commands/efi/tpm.c +=================================================================== +--- grub-2.06.orig/grub-core/commands/efi/tpm.c ++++ grub-2.06/grub-core/commands/efi/tpm.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -186,6 +187,91 @@ grub_tpm1_log_event (grub_efi_handle_t t + return grub_efi_log_event_status (status); + } + ++static void ++grub_tpm2_select_pcr(TPML_PCR_SELECTION *o, unsigned int pcrIndex, unsigned int algo) ++{ ++ TPMS_PCR_SELECTION *pcr; ++ ++ pcr = &o->pcrSelections[o->count++]; ++ pcr->hash = algo; ++ pcr->sizeOfSelect = 3; ++ pcr->pcrSelect[TPM2_PCR_TO_SELECT(pcrIndex)] |= TPM2_PCR_TO_BIT(pcrIndex); ++} ++ ++struct grub_tpm_hash_info { ++ const char *name; ++ grub_size_t size; ++ int id; ++}; ++ ++static const struct grub_tpm_hash_info * ++grub_tpm2_get_digest_info (const char *algo) ++{ ++ static struct grub_tpm_hash_info __hashes[] = { ++ { "sha256", 32, TPM_ALG_SHA256 }, /* first entry is the default */ ++ { "sha512", 64, TPM_ALG_SHA512 }, ++ { "sha1", 20, TPM_ALG_SHA1 }, ++ { NULL } ++ }; ++ struct grub_tpm_hash_info *h; ++ ++ if (algo == NULL) ++ return &__hashes[0]; ++ ++ for (h = __hashes; h->name; ++h) ++ if (!grub_strcmp(h->name, algo)) ++ return h; ++ ++ return NULL; ++} ++ ++static grub_err_t ++grub_tpm2_read_pcr (grub_int8_t pcrIndex, const char *algo, struct grub_tpm_digest **ret) ++{ ++ const struct grub_tpm_hash_info *info; ++ TPML_PCR_SELECTION inSelection, outSelection; ++ grub_uint32_t pcrUpdateCounter; ++ TPML_DIGEST digests = { 0 }; ++ TPM2B_DIGEST *d; ++ struct grub_tpm_digest *result; ++ int rc; ++ ++ info = grub_tpm2_get_digest_info (algo); ++ if (info == NULL) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Unknown digest algorithm %s"), algo); ++ ++ grub_memset(&inSelection, 0, sizeof(inSelection)); ++ grub_memset(&outSelection, 0, sizeof(outSelection)); ++ grub_tpm2_select_pcr(&inSelection, pcrIndex, info->id); ++ ++ rc = TPM2_PCR_Read( ++ NULL, ++ &inSelection, ++ &pcrUpdateCounter, ++ &outSelection, ++ &digests, ++ NULL ++ ); ++ ++ if (rc != 0) ++ return grub_error (GRUB_ERR_BAD_DEVICE, "TPM2_PCR_Read failed, status=%d", rc); ++ ++ d = &digests.digests[0]; ++ ++ *ret = result = grub_malloc (sizeof (*result) + d->size); ++ grub_memcpy (result->value, d->buffer, d->size); ++ result->algorithm = info->name; ++ result->size = d->size; ++ ++ return GRUB_ERR_NONE; ++} ++ ++void ++grub_tpm_digest_free (struct grub_tpm_digest *d) ++{ ++ grub_free (d); ++} ++ + static grub_err_t + grub_tpm2_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf, + grub_size_t size, grub_uint8_t pcr, +@@ -240,3 +326,26 @@ grub_tpm_measure (unsigned char *buf, gr + else + return grub_tpm2_log_event (tpm_handle, buf, size, pcr, description); + } ++ ++struct grub_tpm_digest * ++grub_tpm_read_pcr (grub_uint8_t pcr, const char *algo) ++{ ++ grub_efi_handle_t tpm_handle; ++ grub_efi_uint8_t protocol_version; ++ struct grub_tpm_digest *result = NULL; ++ ++ ++ if (!grub_tpm_handle_find (&tpm_handle, &protocol_version)) ++ return 0; ++ ++ if (protocol_version != 2) ++ { ++ grub_error (GRUB_ERR_BAD_DEVICE, N_("%s: TPM version %d not implemented"), __func__, protocol_version); ++ return NULL; ++ } ++ ++ if (grub_tpm2_read_pcr (pcr, algo, &result)) ++ return NULL; ++ ++ return result; ++} diff --git a/grub-unseal-debug.patch b/grub-unseal-debug.patch new file mode 100644 index 0000000..2d9225b --- /dev/null +++ b/grub-unseal-debug.patch @@ -0,0 +1,41 @@ +Index: grub-2.06/grub-core/tpm2/module.c +=================================================================== +--- grub-2.06.orig/grub-core/tpm2/module.c ++++ grub-2.06/grub-core/tpm2/module.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -449,6 +450,7 @@ grub_tpm2_protector_srk_recover (const s + { + grub_error (err, N_("Failed to unseal sealed key (TPM2_Unseal failed " + "with TSS/TPM error %u)"), rc); ++ grub_millisleep(500); + goto exit4; + } + +@@ -461,6 +463,8 @@ grub_tpm2_protector_srk_recover (const s + goto exit4; + } + ++ grub_printf("TPM2: unsealed %u bytes of key material\n", data.size); ++ + if (ctx->efivar) + { + rc = grub_tpm2_protector_publish_key (data.buffer, data.size, ctx->efivar); +Index: grub-2.06/grub-core/loader/linux.c +=================================================================== +--- grub-2.06.orig/grub-core/loader/linux.c ++++ grub-2.06/grub-core/loader/linux.c +@@ -171,6 +171,7 @@ grub_initrd_component (const char *buf, + struct grub_linux_initrd_component *comp = initrd_ctx->components + initrd_ctx->nfiles; + grub_size_t dir_size, name_len; + ++ grub_printf("Creating initrd component \"%s\" with %u bytes\n", newc_name, bufsz); + while (*newc_name == '/') + newc_name++; + diff --git a/grub2.changes b/grub2.changes index f07f217..db4b4ba 100644 --- a/grub2.changes +++ b/grub2.changes @@ -1,3 +1,59 @@ +------------------------------------------------------------------- +Mon Sep 19 04:07:36 UTC 2022 - Michael Chang + +- Add safety measure to pcr snapshot by checking platform and tpm status + * safe_tpm_pcr_snapshot.patch + +------------------------------------------------------------------- +Fri Sep 16 03:56:14 UTC 2022 - Michael Chang + +- Fix installation failure due to unavailable nvram device on + ppc64le (bsc#1201361) + * 0001-grub-install-set-point-of-no-return-for-powerpc-ieee1275.patch + +------------------------------------------------------------------- +Fri Sep 16 03:12:36 UTC 2022 - Gary Ching-Pang Lin + +- Add patches to dynamically allocate additional memory regions for + EFI systems (bsc#1202438) + * 0001-mm-Allow-dynamically-requesting-additional-memory-re.patch + * 0002-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch + * 0003-kern-efi-mm-Extract-function-to-add-memory-regions.patch + * 0004-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch + * 0005-kern-efi-mm-Implement-runtime-addition-of-pages.patch +- Enlarge the default heap size and defer the disk cache + invalidation (bsc#1202438) + * 0001-kern-efi-mm-Enlarge-the-default-heap-size.patch + * 0002-mm-Defer-the-disk-cache-invalidation.patch + +------------------------------------------------------------------- +Thu Sep 15 09:51:07 UTC 2022 - Michael Chang + +- Add patches for ALP FDE support + * 0001-devmapper-getroot-Have-devmapper-recognize-LUKS2.patch + * 0002-devmapper-getroot-Set-up-cheated-LUKS2-cryptodisk-mo.patch + * 0003-disk-cryptodisk-When-cheatmounting-use-the-sector-in.patch + * 0004-normal-menu-Don-t-show-Booting-s-msg-when-auto-booti.patch + * 0005-EFI-suppress-the-Welcome-to-GRUB-message-in-EFI-buil.patch + * 0006-EFI-console-Do-not-set-colorstate-until-the-first-te.patch + * 0007-EFI-console-Do-not-set-cursor-until-the-first-text-o.patch + * 0008-linuxefi-Use-common-grub_initrd_load.patch + * 0009-Add-crypttab_entry-to-obviate-the-need-to-input-pass.patch + * 0010-templates-import-etc-crypttab-to-grub.cfg.patch + * grub-read-pcr.patch + * efi-set-variable-with-attrs.patch + * tpm-record-pcrs.patch + * tpm-protector-dont-measure-sealed-key.patch + * tpm-protector-export-secret-key.patch + * grub-install-record-pcrs.patch + * grub-unseal-debug.patch + +------------------------------------------------------------------- +Mon Aug 29 03:48:55 UTC 2022 - Michael Chang + +- Fix out of memory error cannot be prevented via disabling tpm (bsc#1202438) + * 0001-tpm-Disable-tpm-verifier-if-tpm-is-not-present.patch + ------------------------------------------------------------------- Thu Aug 18 02:47:28 UTC 2022 - Michael Chang diff --git a/grub2.spec b/grub2.spec index 80f4f19..72705d6 100644 --- a/grub2.spec +++ b/grub2.spec @@ -423,6 +423,36 @@ Patch897: 0013-cryptodisk-Support-key-protectors.patch Patch898: 0014-util-grub-protect-Add-new-tool.patch Patch899: fix-tpm2-build.patch Patch900: 0001-crytodisk-fix-cryptodisk-module-looking-up.patch +# fde +Patch901: 0001-devmapper-getroot-Have-devmapper-recognize-LUKS2.patch +Patch902: 0002-devmapper-getroot-Set-up-cheated-LUKS2-cryptodisk-mo.patch +Patch903: 0003-disk-cryptodisk-When-cheatmounting-use-the-sector-in.patch +Patch904: 0004-normal-menu-Don-t-show-Booting-s-msg-when-auto-booti.patch +Patch905: 0005-EFI-suppress-the-Welcome-to-GRUB-message-in-EFI-buil.patch +Patch906: 0006-EFI-console-Do-not-set-colorstate-until-the-first-te.patch +Patch907: 0007-EFI-console-Do-not-set-cursor-until-the-first-text-o.patch +Patch908: 0008-linuxefi-Use-common-grub_initrd_load.patch +Patch909: 0009-Add-crypttab_entry-to-obviate-the-need-to-input-pass.patch +Patch910: 0010-templates-import-etc-crypttab-to-grub.cfg.patch +Patch911: grub-read-pcr.patch +Patch912: efi-set-variable-with-attrs.patch +Patch913: tpm-record-pcrs.patch +Patch914: tpm-protector-dont-measure-sealed-key.patch +Patch915: tpm-protector-export-secret-key.patch +Patch916: grub-install-record-pcrs.patch +Patch917: grub-unseal-debug.patch +# efi mm +Patch918: 0001-tpm-Disable-tpm-verifier-if-tpm-is-not-present.patch +Patch919: 0001-mm-Allow-dynamically-requesting-additional-memory-re.patch +Patch920: 0002-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch +Patch921: 0003-kern-efi-mm-Extract-function-to-add-memory-regions.patch +Patch922: 0004-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch +Patch923: 0005-kern-efi-mm-Implement-runtime-addition-of-pages.patch +Patch924: 0001-kern-efi-mm-Enlarge-the-default-heap-size.patch +Patch925: 0002-mm-Defer-the-disk-cache-invalidation.patch +# powerpc-ieee1275 +Patch926: 0001-grub-install-set-point-of-no-return-for-powerpc-ieee1275.patch +Patch927: safe_tpm_pcr_snapshot.patch Requires: gettext-runtime %if 0%{?suse_version} >= 1140 @@ -691,7 +721,7 @@ CD_MODULES="all_video boot cat configfile echo true \ password password_pbkdf2 png reboot search search_fs_uuid \ search_fs_file search_label sleep test video fat loadenv" PXE_MODULES="tftp http" -CRYPTO_MODULES="luks luks2 gcry_rijndael gcry_sha1 gcry_sha256 gcry_sha512" +CRYPTO_MODULES="luks luks2 gcry_rijndael gcry_sha1 gcry_sha256 gcry_sha512 crypttab" %ifarch %{efi} CD_MODULES="${CD_MODULES} chain efifwsetup efinet read tpm tpm2" PXE_MODULES="${PXE_MODULES} efinet" @@ -1214,6 +1244,7 @@ fi %dir %{_sysconfdir}/grub.d %{_sysconfdir}/grub.d/README %config(noreplace) %{_sysconfdir}/grub.d/00_header +%config(noreplace) %{_sysconfdir}/grub.d/05_crypttab %config(noreplace) %{_sysconfdir}/grub.d/10_linux %config(noreplace) %{_sysconfdir}/grub.d/20_linux_xen %config(noreplace) %{_sysconfdir}/grub.d/30_uefi-firmware diff --git a/safe_tpm_pcr_snapshot.patch b/safe_tpm_pcr_snapshot.patch new file mode 100644 index 0000000..388c1ef --- /dev/null +++ b/safe_tpm_pcr_snapshot.patch @@ -0,0 +1,90 @@ +--- + grub-core/commands/tpm.c | 28 ++++++++++++++++++++++------ + util/grub-install.c | 7 +++++-- + 2 files changed, 27 insertions(+), 8 deletions(-) + +--- a/grub-core/commands/tpm.c ++++ b/grub-core/commands/tpm.c +@@ -249,6 +249,8 @@ + return GRUB_ERR_NONE; + } + ++#ifdef GRUB_MACHINE_EFI ++ + static grub_err_t + grub_tpm_record_pcrs (grub_extcmd_context_t ctxt, int argc, char **args) + { +@@ -259,6 +261,10 @@ + grub_size_t size = 0; + int n, rv = 1; + ++ /* To prevent error: unable to read PCR from TPM, if no TPM device available */ ++ if (!grub_tpm_present()) ++ return GRUB_ERR_NONE; ++ + if (argc == 0) + pcr_bitmask = GRUB2_PCR_BITMASK_DEFAULT; + else +@@ -287,13 +293,24 @@ + return rv; + } + ++#else ++ ++static grub_err_t ++grub_tpm_record_pcrs (grub_extcmd_context_t ctxt __attribute__((unused)), ++ int argc __attribute__((unused)), ++ char **args __attribute__((unused))) ++{ ++ return GRUB_ERR_NONE; ++} ++ ++#endif ++ + static grub_extcmd_t cmd; + + GRUB_MOD_INIT (tpm) + { +- if (!grub_tpm_present()) +- return; +- grub_verifier_register (&grub_tpm_verifier); ++ if (grub_tpm_present()) ++ grub_verifier_register (&grub_tpm_verifier); + + cmd = grub_register_extcmd ("tpm_record_pcrs", grub_tpm_record_pcrs, 0, + N_("LIST_OF_PCRS"), +@@ -303,8 +320,7 @@ + + GRUB_MOD_FINI (tpm) + { +- if (!grub_tpm_present()) +- return; +- grub_verifier_unregister (&grub_tpm_verifier); ++ if (grub_tpm_present()) ++ grub_verifier_unregister (&grub_tpm_verifier); + grub_unregister_extcmd (cmd); + } +--- a/util/grub-install.c ++++ b/util/grub-install.c +@@ -1457,8 +1457,10 @@ + + grub_util_unlink (load_cfg); + +- if (1) ++ /* FIXME: It seems config.is_cryptodisk_enabled is missing here */ ++ if (platform == GRUB_INSTALL_PLATFORM_X86_64_EFI) + { ++ grub_install_push_module ("tpm"); + load_cfg_f = grub_util_fopen (load_cfg, "wb"); + have_load_cfg = 1; + fprintf (load_cfg_f, "tpm_record_pcrs 0-9\n"); +@@ -1466,7 +1468,8 @@ + + if (debug_image && debug_image[0]) + { +- load_cfg_f = grub_util_fopen (load_cfg, "wb"); ++ if (!load_cfg_f) ++ load_cfg_f = grub_util_fopen (load_cfg, "wb"); + have_load_cfg = 1; + fprintf (load_cfg_f, "set debug='%s'\n", + debug_image); diff --git a/tpm-protector-dont-measure-sealed-key.patch b/tpm-protector-dont-measure-sealed-key.patch new file mode 100644 index 0000000..8357e74 --- /dev/null +++ b/tpm-protector-dont-measure-sealed-key.patch @@ -0,0 +1,15 @@ +Index: grub-2.06/grub-core/tpm2/module.c +=================================================================== +--- grub-2.06.orig/grub-core/tpm2/module.c ++++ grub-2.06/grub-core/tpm2/module.c +@@ -139,7 +139,9 @@ grub_tpm2_protector_srk_read_keyfile (co + void *sealed_key_buffer; + grub_off_t sealed_key_read; + +- sealed_key_file = grub_file_open (filepath, GRUB_FILE_TYPE_NONE); ++ /* Using GRUB_FILE_TYPE_SIGNATURE ensures we do not hash the keyfile into PCR9 ++ * otherwise we'll never be able to predict the value of PCR9 at unseal time */ ++ sealed_key_file = grub_file_open (filepath, GRUB_FILE_TYPE_SIGNATURE); + if (!sealed_key_file) + { + grub_dprintf ("tpm2", "Could not open sealed key file.\n"); diff --git a/tpm-protector-export-secret-key.patch b/tpm-protector-export-secret-key.patch new file mode 100644 index 0000000..70eb493 --- /dev/null +++ b/tpm-protector-export-secret-key.patch @@ -0,0 +1,138 @@ +Index: grub-2.06/grub-core/tpm2/module.c +=================================================================== +--- grub-2.06.orig/grub-core/tpm2/module.c ++++ grub-2.06/grub-core/tpm2/module.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -46,6 +47,7 @@ struct grub_tpm2_protector_context + const char *keyfile; + TPM_HANDLE srk; + TPM_HANDLE nv; ++ const char *efivar; + }; + + static const struct grub_arg_option grub_tpm2_protector_init_cmd_options[] = +@@ -122,6 +124,16 @@ static const struct grub_arg_option grub + N_("Required in NV Index mode, the NV handle to read which must " + "readily exist on the TPM and which contains the key."), + }, ++ /* When publishing the unsealed key to a UEFI variable */ ++ { ++ .longarg = "efivar", ++ .shortarg = 'E', ++ .flags = 0, ++ .arg = NULL, ++ .type = ARG_TYPE_STRING, ++ .doc = ++ N_("Publish the unsealed key to the indicated UEFI variable."), ++ }, + /* End of list */ + {0, 0, 0, 0, 0, 0} + }; +@@ -302,6 +314,34 @@ grub_tpm2_protector_srk_get (const struc + } + + static grub_err_t ++grub_tpm2_protector_publish_key (grub_uint8_t *key, grub_size_t key_size, ++ const char *var_name) ++{ ++ grub_efi_guid_t vendor_guid = { 0x58aca851, 0x8af7, 0x4738, { 0xa5, 0x42, 0x26, 0x6e, 0x21, 0xf5, 0xca, 0xd9 }}; ++ grub_uint8_t *tmp_key; ++ grub_err_t err; ++ ++ /* It appears that EFI's set_var function overwrites the key. */ ++ tmp_key = grub_malloc (key_size); ++ if (!tmp_key) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("No memory left to allocate temporary key buffer")); ++ return GRUB_ERR_OUT_OF_MEMORY; ++ } ++ ++ grub_memcpy(tmp_key, key, key_size); ++ ++ err = grub_efi_set_variable_with_attributes(var_name, &vendor_guid, ++ GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS | GRUB_EFI_VARIABLE_RUNTIME_ACCESS, ++ tmp_key, key_size); ++ if (err) ++ grub_error (err, N_("Failed to export LUKS key as EFI variable %s"), var_name); ++ ++ grub_free (tmp_key); ++ return err; ++} ++ ++static grub_err_t + grub_tpm2_protector_srk_recover (const struct grub_tpm2_protector_context *ctx, + grub_uint8_t **key, grub_size_t *key_size) + { +@@ -421,6 +461,13 @@ grub_tpm2_protector_srk_recover (const s + goto exit4; + } + ++ if (ctx->efivar) ++ { ++ rc = grub_tpm2_protector_publish_key (data.buffer, data.size, ctx->efivar); ++ if (rc) ++ goto exit4; ++ } ++ + grub_memcpy (key_out, data.buffer, data.size); + + *key = key_out; +@@ -549,20 +596,32 @@ grub_tpm2_protector_check_args (struct g + } + + static grub_err_t +-grub_tpm2_protector_parse_keyfile (const char *value, const char **keyfile) ++grub_tpm2_protector_parse_string (const char *value, const char **var, const char *arg_name) + { + if (grub_strlen (value) == 0) + return GRUB_ERR_BAD_ARGUMENT; + +- *keyfile = grub_strdup (value); +- if (!*keyfile) ++ *var = grub_strdup (value); ++ if (!*var) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, +- N_("No memory to duplicate keyfile path")); ++ N_("No memory to duplicate %s argument"), arg_name); + + return GRUB_ERR_NONE; + } + + static grub_err_t ++grub_tpm2_protector_parse_keyfile (const char *value, const char **keyfile) ++{ ++ return grub_tpm2_protector_parse_string (value, keyfile, "keyfile"); ++} ++ ++static grub_err_t ++grub_tpm2_protector_parse_efivar (const char *value, const char **efivar) ++{ ++ return grub_tpm2_protector_parse_string (value, efivar, "efivar"); ++} ++ ++static grub_err_t + grub_tpm2_protector_parse_mode (const char *value, + grub_tpm2_protector_mode_t *mode) + { +@@ -650,6 +709,14 @@ grub_tpm2_protector_init_cmd_handler (gr + if (err) + return err; + } ++ ++ if (state[7].set) /* efivar */ ++ { ++ err = grub_tpm2_protector_parse_efivar (state[7].arg, ++ &grub_tpm2_protector_ctx.efivar); ++ if (err) ++ return err; ++ } + + err = grub_tpm2_protector_check_args (&grub_tpm2_protector_ctx); + diff --git a/tpm-record-pcrs.patch b/tpm-record-pcrs.patch new file mode 100644 index 0000000..4dde858 --- /dev/null +++ b/tpm-record-pcrs.patch @@ -0,0 +1,235 @@ +Index: grub-2.06/grub-core/commands/tpm.c +=================================================================== +--- grub-2.06.orig/grub-core/commands/tpm.c ++++ grub-2.06/grub-core/commands/tpm.c +@@ -26,6 +26,9 @@ + #include + #include + #include ++#include ++#include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -84,12 +87,220 @@ struct grub_file_verifier grub_tpm_verif + .verify_string = grub_tpm_verify_string, + }; + ++/* ++ * Preserve current PCR values and record them to an EFI variable ++ */ ++#define GRUB2_PCR_BITMASK_DEFAULT ((1 << 16) - 1) ++#define GRUB2_PCR_BITMASK_ALL ((1 << 24) - 1) ++ ++static const struct grub_arg_option grub_tpm_record_pcrs_options[] = ++ { ++ { ++ .longarg = "efivar", ++ .shortarg = 'E', ++ .flags = 0, ++ .arg = NULL, ++ .type = ARG_TYPE_STRING, ++ .doc = ++ N_("The EFI variable to publish the PCRs to (default GrubPcrSnapshot)"), ++ }, ++ ++ {0, 0, 0, 0, 0, 0} ++ }; ++ ++static grub_err_t ++grub_tpm_parse_pcr_index (const char *word, const char **end_ret, unsigned int *index) ++{ ++ const char *end; ++ ++ if (!grub_isdigit (word[0])) ++ return GRUB_ERR_BAD_NUMBER; ++ ++ *index = grub_strtoul(word, &end, 0); ++ if (*index > 32) ++ return GRUB_ERR_BAD_NUMBER; ++ ++ *end_ret = end; ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_tpm_parse_pcr_list (const char *arg, grub_uint32_t *bitmask) ++{ ++ const char *word, *end; ++ unsigned int index, last_index; ++ ++ if (!grub_strcmp (arg, "all")) ++ { ++ *bitmask = GRUB2_PCR_BITMASK_ALL; ++ return GRUB_ERR_NONE; ++ } ++ ++ word = arg; ++ while (1) ++ { ++ if (grub_tpm_parse_pcr_index (word, &end, &index)) ++ goto bad_pcr_index; ++ ++ if (*end == '-') ++ { ++ if (grub_tpm_parse_pcr_index (end + 1, &end, &last_index) || last_index < index) ++ goto bad_pcr_index; ++ ++ while (index <= last_index) ++ *bitmask |= (1 << (index++)); ++ } ++ else ++ *bitmask |= (1 << index); ++ ++ if (*end == '\0') ++ break; ++ ++ if (*end != ',') ++ goto bad_pcr_index; ++ ++ word = end + 1; ++ } ++ ++ return GRUB_ERR_NONE; ++ ++bad_pcr_index: ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("cannot parse PCR list \"%s\""), arg); ++} ++ ++static inline unsigned int ++nbits(grub_uint32_t mask) ++{ ++ unsigned int r = 0; ++ ++ for (; mask != 0; mask >>= 1) ++ r += (mask & 1); ++ return r; ++} ++ ++static grub_err_t ++grub_tpm_snapshot_pcrs (grub_uint32_t pcr_bitmask, const char *algo, ++ void **buffer_ret, grub_size_t *size_ret) ++{ ++ char *buffer; ++ grub_size_t size = 65536; ++ unsigned int wpos = 0; ++ grub_uint8_t pcr; ++ ++ buffer = grub_malloc (size); ++ for (pcr = 0; pcr < 32; ++pcr) ++ { ++ struct grub_tpm_digest *d; ++ unsigned int need, k; ++ ++ if (!(pcr_bitmask & (1 << pcr))) ++ continue; ++ ++ d = grub_tpm_read_pcr (pcr, algo); ++ if (d == NULL) ++ { ++ grub_error (GRUB_ERR_BAD_DEVICE, N_("unable to read PCR %d from TPM"), pcr); ++ continue; ++ } ++ ++ /* We need room for the PCR index, 2 spaces, newline, NUL. 16 should be enough. */ ++ need = 16 + grub_strlen(d->algorithm) + 2 * d->size; ++ if (wpos + need > size) ++ { ++ buffer = grub_realloc (buffer, size + need); ++ if (buffer == NULL) ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("Not enough memory when dumping PCR registers")); ++ } ++ ++ grub_snprintf (buffer + wpos, size - wpos, "%02d %s ", pcr, d->algorithm); ++ wpos = grub_strlen(buffer); ++ ++ for (k = 0; k < d->size; ++k) ++ { ++ grub_snprintf (buffer + wpos, size - wpos, "%02x", d->value[k]); ++ wpos += 2; ++ } ++ ++ buffer[wpos++] = '\n'; ++ buffer[wpos] = '\0'; ++ ++ grub_tpm_digest_free (d); ++ } ++ ++ *buffer_ret = buffer; ++ *size_ret = wpos; ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_tpm_write_pcrs_to_efi (void *data, grub_size_t size, const char *var_name) ++{ ++ grub_efi_guid_t vendor_guid = { 0x7ce323f2, 0xb841, 0x4d30, { 0xa0, 0xe9, 0x54, 0x74, 0xa7, 0x6c, 0x9a, 0x3f }}; ++ grub_err_t rc; ++ ++ rc = grub_efi_set_variable_with_attributes(var_name, &vendor_guid, ++ GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS | GRUB_EFI_VARIABLE_RUNTIME_ACCESS, ++ data, size); ++ ++ if (rc) ++ return grub_error (GRUB_ERR_BAD_DEVICE, N_("Failed to publish PCR snapshot to UEFI variable %s"), var_name); ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_tpm_record_pcrs (grub_extcmd_context_t ctxt, int argc, char **args) ++{ ++ struct grub_arg_list *state = ctxt->state; ++ grub_uint32_t pcr_bitmask = 0; ++ const char *efivar; ++ void *buffer = NULL; ++ grub_size_t size = 0; ++ int n, rv = 1; ++ ++ if (argc == 0) ++ pcr_bitmask = GRUB2_PCR_BITMASK_DEFAULT; ++ else ++ { ++ for (n = 0; n < argc; ++n) ++ if (grub_tpm_parse_pcr_list (args[n], &pcr_bitmask)) ++ return 1; ++ } ++ ++ if (grub_tpm_snapshot_pcrs (pcr_bitmask, NULL, &buffer, &size)) ++ goto out; ++ ++ if (state[0].set) ++ efivar = state[0].arg; ++ else ++ efivar = "GrubPcrSnapshot"; ++ ++ if (grub_tpm_write_pcrs_to_efi (buffer, size, efivar)) ++ goto out; ++ ++ rv = 0; ++ ++out: ++ if (buffer) ++ grub_free (buffer); ++ return rv; ++} ++ ++static grub_extcmd_t cmd; ++ + GRUB_MOD_INIT (tpm) + { + grub_verifier_register (&grub_tpm_verifier); ++ ++ cmd = grub_register_extcmd ("tpm_record_pcrs", grub_tpm_record_pcrs, 0, ++ N_("LIST_OF_PCRS"), ++ N_("Snapshot one or more PCR values and record them in an EFI variable."), ++ grub_tpm_record_pcrs_options); + } + + GRUB_MOD_FINI (tpm) + { + grub_verifier_unregister (&grub_tpm_verifier); ++ grub_unregister_extcmd (cmd); + }