Sync from SUSE:SLFO:Main grub2 revision 1dac218436a6d596013e239f4ee7d9e4

This commit is contained in:
Adrian Schröter 2024-05-03 13:19:28 +02:00
commit 5a5e453693
229 changed files with 63390 additions and 0 deletions

23
.gitattributes vendored Normal file
View File

@ -0,0 +1,23 @@
## Default LFS
*.7z filter=lfs diff=lfs merge=lfs -text
*.bsp filter=lfs diff=lfs merge=lfs -text
*.bz2 filter=lfs diff=lfs merge=lfs -text
*.gem filter=lfs diff=lfs merge=lfs -text
*.gz filter=lfs diff=lfs merge=lfs -text
*.jar filter=lfs diff=lfs merge=lfs -text
*.lz filter=lfs diff=lfs merge=lfs -text
*.lzma filter=lfs diff=lfs merge=lfs -text
*.obscpio filter=lfs diff=lfs merge=lfs -text
*.oxt filter=lfs diff=lfs merge=lfs -text
*.pdf filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.rpm filter=lfs diff=lfs merge=lfs -text
*.tbz filter=lfs diff=lfs merge=lfs -text
*.tbz2 filter=lfs diff=lfs merge=lfs -text
*.tgz filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text
*.txz filter=lfs diff=lfs merge=lfs -text
*.whl filter=lfs diff=lfs merge=lfs -text
*.xz filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.zst filter=lfs diff=lfs merge=lfs -text

View File

@ -0,0 +1,68 @@
From a326e486bdcf99e6be973ba54c0abfb6d2d95b73 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 17 Jan 2022 17:45:00 +0800
Subject: [PATCH 1/5] Add grub_envblk_buf helper function
This helps in creation and initialization of memory buffer for
environment block of given size.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/lib/envblk.c | 12 ++++++++++++
include/grub/lib/envblk.h | 1 +
util/grub-editenv.c | 4 +---
3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/grub-core/lib/envblk.c b/grub-core/lib/envblk.c
index 2e4e78b132..24efbe7ffa 100644
--- a/grub-core/lib/envblk.c
+++ b/grub-core/lib/envblk.c
@@ -23,6 +23,18 @@
#include <grub/mm.h>
#include <grub/lib/envblk.h>
+char *
+grub_envblk_buf (grub_size_t size)
+{
+ char *buf;
+
+ buf = grub_malloc (size);
+ grub_memcpy (buf, GRUB_ENVBLK_SIGNATURE, sizeof (GRUB_ENVBLK_SIGNATURE) - 1);
+ grub_memset (buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1, '#', size - sizeof (GRUB_ENVBLK_SIGNATURE) + 1);
+
+ return buf;
+}
+
grub_envblk_t
grub_envblk_open (char *buf, grub_size_t size)
{
diff --git a/include/grub/lib/envblk.h b/include/grub/lib/envblk.h
index c3e6559217..83f3fcf841 100644
--- a/include/grub/lib/envblk.h
+++ b/include/grub/lib/envblk.h
@@ -31,6 +31,7 @@ struct grub_envblk
};
typedef struct grub_envblk *grub_envblk_t;
+char *grub_envblk_buf (grub_size_t size);
grub_envblk_t grub_envblk_open (char *buf, grub_size_t size);
int grub_envblk_set (grub_envblk_t envblk, const char *name, const char *value);
void grub_envblk_delete (grub_envblk_t envblk, const char *name);
diff --git a/util/grub-editenv.c b/util/grub-editenv.c
index b8219335f7..a02d3f2a63 100644
--- a/util/grub-editenv.c
+++ b/util/grub-editenv.c
@@ -210,9 +210,7 @@ create_envblk_fs (void)
if (! fp)
grub_util_error (_("cannot open `%s': %s"), device, strerror (errno));
- buf = xmalloc (size);
- memcpy (buf, GRUB_ENVBLK_SIGNATURE, sizeof (GRUB_ENVBLK_SIGNATURE) - 1);
- memset (buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1, '#', size - sizeof (GRUB_ENVBLK_SIGNATURE) + 1);
+ buf = grub_envblk_buf (size);
if (fseek (fp, offset, SEEK_SET) < 0)
grub_util_error (_("cannot seek `%s': %s"), device, strerror (errno));
--
2.34.1

View File

@ -0,0 +1,526 @@
From db4da8095b5ba722d22502c8d090e66816a5577d Mon Sep 17 00:00:00 2001
From: Matthew Garrett <mjg@redhat.com>
Date: Fri, 6 Nov 2020 08:36:36 +0000
Subject: [PATCH 1/9] Add support for Linux EFI stub loading on aarch64.
Add support for Linux EFI stub loading on aarch64.
v1:
Make efi handoff the default loader for arm64 platform.
v2:
The efi shim_lock verifier has been moved to grub core so local
shim_lock protocol is no longer needed here for aarch64 efi to verify
the loaded kernel image. From now on the framework will take care the
verificaion, consolidating the integration of various security verifiers
like secure boot, gpg and tpm.
---
grub-core/Makefile.core.def | 4 +-
grub-core/loader/arm64/efi/linux.c | 443 +++++++++++++++++++++++++++++
include/grub/arm/linux.h | 9 +
include/grub/arm64/linux.h | 10 +
4 files changed, 465 insertions(+), 1 deletion(-)
create mode 100644 grub-core/loader/arm64/efi/linux.c
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1854,7 +1854,7 @@
arm_coreboot = loader/arm/linux.c;
arm_efi = loader/efi/linux.c;
arm_uboot = loader/arm/linux.c;
- arm64 = loader/efi/linux.c;
+ arm64 = loader/arm64/efi/linux.c;
loongarch64 = loader/efi/linux.c;
riscv32 = loader/efi/linux.c;
riscv64 = loader/efi/linux.c;
@@ -1922,7 +1922,7 @@
module = {
name = linuxefi;
- efi = lib/fake_module.c;
+ x86 = lib/fake_module.c;
enable = i386_efi;
enable = x86_64_efi;
};
--- /dev/null
+++ b/grub-core/loader/arm64/efi/linux.c
@@ -0,0 +1,411 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/charset.h>
+#include <grub/command.h>
+#include <grub/err.h>
+#include <grub/file.h>
+#include <grub/fdt.h>
+#include <grub/linux.h>
+#include <grub/loader.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+#include <grub/cpu/linux.h>
+#include <grub/efi/efi.h>
+#include <grub/efi/fdtload.h>
+#include <grub/efi/memory.h>
+#include <grub/efi/pe32.h>
+#include <grub/i18n.h>
+#include <grub/lib/cmdline.h>
+#include <grub/verify.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static grub_dl_t my_mod;
+static int loaded;
+
+static void *kernel_addr;
+static grub_uint64_t kernel_size;
+static grub_uint32_t handover_offset;
+
+static char *linux_args;
+static grub_uint32_t cmdline_size;
+
+static grub_addr_t initrd_start;
+static grub_addr_t initrd_end;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+
+typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *);
+
+static grub_err_t
+grub_efi_linux_boot (void *kernel_address, grub_off_t offset,
+ void *kernel_params)
+{
+ handover_func hf;
+
+ hf = (handover_func)((char *)kernel_address + offset);
+ hf (grub_efi_image_handle, grub_efi_system_table, kernel_params);
+
+ return GRUB_ERR_BUG;
+}
+
+#pragma GCC diagnostic pop
+
+static grub_err_t
+grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh)
+{
+ if (lh->magic != GRUB_LINUX_ARMXX_MAGIC_SIGNATURE)
+ return grub_error(GRUB_ERR_BAD_OS, "invalid magic number");
+
+ if ((lh->code0 & 0xffff) != GRUB_PE32_MAGIC)
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ N_("plain image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled"));
+
+ grub_dprintf ("linux", "UEFI stub kernel:\n");
+ grub_dprintf ("linux", "PE/COFF header @ %08x\n", lh->hdr_offset);
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+finalize_params_linux (void)
+{
+ grub_efi_loaded_image_t *loaded_image = NULL;
+ int node, retval, len;
+
+ void *fdt;
+
+ fdt = grub_fdt_load (GRUB_EFI_LINUX_FDT_EXTRA_SPACE);
+
+ if (!fdt)
+ goto failure;
+
+ node = grub_fdt_find_subnode (fdt, 0, "chosen");
+ if (node < 0)
+ node = grub_fdt_add_subnode (fdt, 0, "chosen");
+
+ if (node < 1)
+ goto failure;
+
+ /* Set initrd info */
+ if (initrd_start && initrd_end > initrd_start)
+ {
+ grub_dprintf ("linux", "Initrd @ %p-%p\n",
+ (void *) initrd_start, (void *) initrd_end);
+
+ retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-start",
+ initrd_start);
+ if (retval)
+ goto failure;
+ retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-end",
+ initrd_end);
+ if (retval)
+ goto failure;
+ }
+
+ if (grub_fdt_install() != GRUB_ERR_NONE)
+ goto failure;
+
+ grub_dprintf ("linux", "Installed/updated FDT configuration table @ %p\n",
+ fdt);
+
+ /* Convert command line to UCS-2 */
+ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
+ if (!loaded_image)
+ goto failure;
+
+ loaded_image->load_options_size = len =
+ (grub_strlen (linux_args) + 1) * sizeof (grub_efi_char16_t);
+ loaded_image->load_options =
+ grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
+ if (!loaded_image->load_options)
+ return grub_error(GRUB_ERR_BAD_OS, "failed to create kernel parameters");
+
+ loaded_image->load_options_size =
+ 2 * grub_utf8_to_utf16 (loaded_image->load_options, len,
+ (grub_uint8_t *) linux_args, len, NULL);
+
+ return GRUB_ERR_NONE;
+
+failure:
+ grub_fdt_unload();
+ return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT");
+}
+
+static void
+free_params (void)
+{
+ grub_efi_loaded_image_t *loaded_image = NULL;
+
+ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
+ if (loaded_image)
+ {
+ if (loaded_image->load_options)
+ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_efi_uintn_t)loaded_image->load_options,
+ GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
+ loaded_image->load_options = NULL;
+ loaded_image->load_options_size = 0;
+ }
+}
+
+grub_err_t
+grub_arch_efi_linux_boot_image (grub_addr_t addr,
+ grub_size_t size __attribute__ ((unused)),
+ char *args)
+{
+ grub_err_t retval;
+
+ retval = finalize_params_linux ();
+ if (retval != GRUB_ERR_NONE)
+ return grub_errno;
+
+ grub_dprintf ("linux", "linux command line: '%s'\n", args);
+
+ retval = grub_efi_linux_boot ((char *)addr, handover_offset, (void *)addr);
+
+ /* Never reached... */
+ free_params();
+ return retval;
+}
+
+static grub_err_t
+grub_linux_boot (void)
+{
+ return (grub_arch_efi_linux_boot_image ((grub_addr_t)kernel_addr, kernel_size, linux_args));
+}
+
+static grub_err_t
+grub_linux_unload (void)
+{
+ grub_dl_unref (my_mod);
+ loaded = 0;
+ if (initrd_start)
+ grub_efi_free_pages ((grub_efi_physical_address_t) initrd_start,
+ GRUB_EFI_BYTES_TO_PAGES (initrd_end - initrd_start));
+ initrd_start = initrd_end = 0;
+ grub_free (linux_args);
+ if (kernel_addr)
+ grub_efi_free_pages ((grub_addr_t) kernel_addr,
+ GRUB_EFI_BYTES_TO_PAGES (kernel_size));
+ grub_fdt_unload ();
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * As per linux/Documentation/arm/Booting
+ * ARM initrd needs to be covered by kernel linear mapping,
+ * so place it in the first 512MB of DRAM.
+ *
+ * As per linux/Documentation/arm64/booting.txt
+ * ARM64 initrd needs to be contained entirely within a 1GB aligned window
+ * of up to 32GB of size that covers the kernel image as well.
+ * Since the EFI stub loader will attempt to load the kernel near start of
+ * RAM, place the buffer in the first 32GB of RAM.
+ */
+#ifdef __arm__
+#define INITRD_MAX_ADDRESS_OFFSET (512U * 1024 * 1024)
+#else /* __aarch64__ */
+#define INITRD_MAX_ADDRESS_OFFSET (32ULL * 1024 * 1024 * 1024)
+#endif
+
+/*
+ * This function returns a pointer to a legally allocated initrd buffer,
+ * or NULL if unsuccessful
+ */
+static void *
+allocate_initrd_mem (int initrd_pages)
+{
+ grub_addr_t max_addr;
+
+ if (grub_efi_get_ram_base (&max_addr) != GRUB_ERR_NONE)
+ return NULL;
+
+ max_addr += INITRD_MAX_ADDRESS_OFFSET - 1;
+
+ return grub_efi_allocate_pages_real (max_addr, initrd_pages,
+ GRUB_EFI_ALLOCATE_MAX_ADDRESS,
+ GRUB_EFI_LOADER_DATA);
+}
+
+static grub_err_t
+grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
+ struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 };
+ int initrd_size, initrd_pages;
+ void *initrd_mem = NULL;
+
+ if (argc == 0)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+ goto fail;
+ }
+
+ if (!loaded)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("you need to load the kernel first"));
+ goto fail;
+ }
+
+ if (grub_initrd_init (argc, argv, &initrd_ctx))
+ goto fail;
+
+ initrd_size = grub_get_initrd_size (&initrd_ctx);
+ grub_dprintf ("linux", "Loading initrd\n");
+
+ initrd_pages = (GRUB_EFI_BYTES_TO_PAGES (initrd_size));
+ initrd_mem = allocate_initrd_mem (initrd_pages);
+
+ if (!initrd_mem)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+ goto fail;
+ }
+
+ if (grub_initrd_load (&initrd_ctx, initrd_mem))
+ goto fail;
+
+ initrd_start = (grub_addr_t) initrd_mem;
+ initrd_end = initrd_start + initrd_size;
+ grub_dprintf ("linux", "[addr=%p, size=0x%x]\n",
+ (void *) initrd_start, initrd_size);
+
+ fail:
+ grub_initrd_close (&initrd_ctx);
+ if (initrd_mem && !initrd_start)
+ grub_efi_free_pages ((grub_addr_t) initrd_mem, initrd_pages);
+
+ return grub_errno;
+}
+
+static grub_err_t
+grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
+ grub_file_t file = 0;
+ struct linux_arch_kernel_header lh;
+ struct grub_armxx_linux_pe_header *pe;
+ grub_err_t err;
+
+ grub_dl_ref (my_mod);
+
+ if (argc == 0)
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
+ goto fail;
+ }
+
+ file = grub_file_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL);
+ if (!file)
+ goto fail;
+
+ kernel_size = grub_file_size (file);
+
+ if (grub_file_read (file, &lh, sizeof (lh)) < (long) sizeof (lh))
+ return grub_errno;
+
+ if (grub_arch_efi_linux_check_image (&lh) != GRUB_ERR_NONE)
+ goto fail;
+
+ grub_loader_unset();
+
+ grub_dprintf ("linux", "kernel file size: %lld\n", (long long) kernel_size);
+ kernel_addr = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (kernel_size));
+ grub_dprintf ("linux", "kernel numpages: %lld\n",
+ (long long) GRUB_EFI_BYTES_TO_PAGES (kernel_size));
+ if (!kernel_addr)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+ goto fail;
+ }
+
+ grub_file_seek (file, 0);
+ if (grub_file_read (file, kernel_addr, kernel_size)
+ < (grub_int64_t) kernel_size)
+ {
+ if (!grub_errno)
+ grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
+ goto fail;
+ }
+
+ grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
+
+ pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset);
+ handover_offset = pe->opt.entry_addr;
+
+ cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE);
+ linux_args = grub_malloc (cmdline_size);
+ if (!linux_args)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+ goto fail;
+ }
+ grub_memcpy (linux_args, LINUX_IMAGE, sizeof (LINUX_IMAGE));
+ err = grub_create_loader_cmdline (argc, argv,
+ linux_args + sizeof (LINUX_IMAGE) - 1,
+ cmdline_size,
+ GRUB_VERIFY_KERNEL_CMDLINE);
+ if (err)
+ goto fail;
+
+ if (grub_errno == GRUB_ERR_NONE)
+ {
+ grub_loader_set (grub_linux_boot, grub_linux_unload, 0);
+ loaded = 1;
+ }
+
+fail:
+ if (file)
+ grub_file_close (file);
+
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ grub_dl_unref (my_mod);
+ loaded = 0;
+ }
+
+ if (linux_args && !loaded)
+ grub_free (linux_args);
+
+ if (kernel_addr && !loaded)
+ grub_efi_free_pages ((grub_addr_t) kernel_addr,
+ GRUB_EFI_BYTES_TO_PAGES (kernel_size));
+
+ return grub_errno;
+}
+
+
+static grub_command_t cmd_linux, cmd_initrd;
+
+GRUB_MOD_INIT (linux)
+{
+ cmd_linux = grub_register_command ("linux", grub_cmd_linux, 0,
+ N_("Load Linux."));
+ cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, 0,
+ N_("Load initrd."));
+ my_mod = mod;
+}
+
+GRUB_MOD_FINI (linux)
+{
+ grub_unregister_command (cmd_linux);
+ grub_unregister_command (cmd_initrd);
+}
--- a/include/grub/arm/linux.h
+++ b/include/grub/arm/linux.h
@@ -20,10 +20,22 @@
#ifndef GRUB_ARM_LINUX_HEADER
#define GRUB_ARM_LINUX_HEADER 1
+#include <grub/efi/pe32.h>
#include "system.h"
#include <grub/efi/pe32.h>
+struct grub_arm_linux_pe_header
+{
+ grub_uint32_t magic;
+ struct grub_pe32_coff_header coff;
+ struct grub_pe32_optional_header opt;
+};
+
+#if defined(__arm__)
+# define grub_armxx_linux_pe_header grub_arm_linux_pe_header
+#endif
+
#if defined GRUB_MACHINE_UBOOT
# include <grub/uboot/uboot.h>
# define LINUX_ADDRESS (start_of_ram + 0x8000)
--- /dev/null
+++ b/include/grub/arm64/linux.h
@@ -0,0 +1,39 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_ARM64_LINUX_HEADER
+#define GRUB_ARM64_LINUX_HEADER 1
+
+#include <grub/types.h>
+#include <grub/efi/pe32.h>
+
+#define GRUB_LINUX_ARM64_MAGIC_SIGNATURE 0x644d5241 /* 'ARM\x64' */
+
+struct grub_arm64_linux_pe_header
+{
+ grub_uint32_t magic;
+ struct grub_pe32_coff_header coff;
+ struct grub_pe64_optional_header opt;
+};
+
+#if defined(__aarch64__)
+# define GRUB_LINUX_ARMXX_MAGIC_SIGNATURE GRUB_LINUX_ARM64_MAGIC_SIGNATURE
+# define grub_armxx_linux_pe_header grub_arm64_linux_pe_header
+#endif
+
+#endif /* ! GRUB_ARM64_LINUX_HEADER */

View File

@ -0,0 +1,215 @@
From 82d95254ca0496c8843113665bb9a99876101025 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 8 Oct 2021 13:36:45 +0800
Subject: [PATCH 01/11] Factor out grub_efi_linux_boot
Both x86 and arm64 on efi are using handover protocol to boot linux
kernel. To enable better code reuse, factor out grub_efi_linux_boot from
arm64 so that it can be shared with x86 platform for the common fixes.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/Makefile.core.def | 1 +
grub-core/loader/arm64/efi/linux.c | 35 +-----------------
grub-core/loader/efi/linux.c | 58 ++++++++++++++++++++++++++++++
grub-core/loader/i386/efi/linux.c | 13 ++-----
include/grub/efi/linux.h | 29 +++++++++++++++
5 files changed, 92 insertions(+), 44 deletions(-)
create mode 100644 grub-core/loader/efi/linux.c
create mode 100644 include/grub/efi/linux.h
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1860,6 +1860,9 @@
riscv64 = loader/efi/linux.c;
emu = loader/emu/linux.c;
common = loader/linux.c;
+ i386_efi = loader/efi/linux_boot.c;
+ x86_64_efi = loader/efi/linux_boot.c;
+ arm64 = loader/efi/linux_boot.c;
};
module = {
--- a/grub-core/loader/arm64/efi/linux.c
+++ b/grub-core/loader/arm64/efi/linux.c
@@ -33,6 +33,7 @@
#include <grub/i18n.h>
#include <grub/lib/cmdline.h>
#include <grub/verify.h>
+#include <grub/efi/linux.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -51,40 +52,6 @@
static grub_addr_t initrd_start;
static grub_addr_t initrd_end;
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wcast-align"
-
-typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *);
-
-static grub_err_t
-grub_efi_linux_boot (void *kernel_address, grub_off_t offset,
- void *kernel_params)
-{
- grub_efi_loaded_image_t *loaded_image = NULL;
- handover_func hf;
-
- /*
- * Since the EFI loader is not calling the LoadImage() and StartImage()
- * services for loading the kernel and booting respectively, it has to
- * set the Loaded Image base address.
- */
- loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
- if (loaded_image)
- loaded_image->image_base = kernel_addr;
- else
- grub_dprintf ("linux", "Loaded Image base address could not be set\n");
-
- grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p params: %p\n",
- kernel_address, (void *)(grub_efi_uintn_t)offset, kernel_params);
- hf = (handover_func)((char *)kernel_address + offset);
- grub_dprintf ("linux", "handover_func() = %p\n", hf);
- hf (grub_efi_image_handle, grub_efi_system_table, kernel_params);
-
- return GRUB_ERR_BUG;
-}
-
-#pragma GCC diagnostic pop
-
static grub_err_t
grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh)
{
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -26,6 +26,7 @@
#include <grub/i18n.h>
#include <grub/lib/cmdline.h>
#include <grub/efi/efi.h>
+#include <grub/efi/linux.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -40,26 +41,18 @@
#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12)
-typedef void(*handover_func)(void *, grub_efi_system_table_t *, struct linux_kernel_params *);
-
static grub_err_t
grub_linuxefi_boot (void)
{
- handover_func hf;
int offset = 0;
#ifdef __x86_64__
offset = 512;
#endif
-
- hf = (handover_func)((char *)kernel_mem + handover_offset + offset);
-
asm volatile ("cli");
- hf (grub_efi_image_handle, grub_efi_system_table, params);
-
- /* Not reached */
- return GRUB_ERR_NONE;
+ return grub_efi_linux_boot ((char *)kernel_mem, handover_offset + offset,
+ params);
}
static grub_err_t
--- /dev/null
+++ b/include/grub/efi/linux.h
@@ -0,0 +1,29 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2014 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef GRUB_EFI_LINUX_HEADER
+#define GRUB_EFI_LINUX_HEADER 1
+
+#include <grub/efi/api.h>
+#include <grub/err.h>
+#include <grub/symbol.h>
+
+grub_err_t
+EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset,
+ void *kernel_param);
+
+#endif /* ! GRUB_EFI_LINUX_HEADER */
--- /dev/null
+++ b/grub-core/loader/efi/linux_boot.c
@@ -0,0 +1,58 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2014 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/err.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+#include <grub/cpu/linux.h>
+#include <grub/efi/efi.h>
+#include <grub/efi/pe32.h>
+#include <grub/efi/linux.h>
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+
+typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *);
+
+grub_err_t
+grub_efi_linux_boot (void *kernel_addr, grub_off_t offset,
+ void *kernel_params)
+{
+ grub_efi_loaded_image_t *loaded_image = NULL;
+ handover_func hf;
+
+ /*
+ * Since the EFI loader is not calling the LoadImage() and StartImage()
+ * services for loading the kernel and booting respectively, it has to
+ * set the Loaded Image base address.
+ */
+ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
+ if (loaded_image)
+ loaded_image->image_base = kernel_addr;
+ else
+ grub_dprintf ("linux", "Loaded Image base address could not be set\n");
+
+ grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p params: %p\n",
+ kernel_addr, (void *)(grub_efi_uintn_t)offset, kernel_params);
+ hf = (handover_func)((char *)kernel_addr + offset);
+ hf (grub_efi_image_handle, grub_efi_system_table, kernel_params);
+
+ return GRUB_ERR_BUG;
+}
+
+#pragma GCC diagnostic pop

View File

@ -0,0 +1,66 @@
From f76317d9dc35dbc576820ba6c2a6a8e41f5338b5 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 19 May 2022 13:08:12 +0800
Subject: [PATCH] Fix infinite boot loop on headless system in qemu
After finishing headless virtual machine installation via serial
console, the reboot fails in grub with infinte boot loop and also
keyboard input for serial console is unresponsive.
The cause of infinte loop boils down to legacy vga driver in grub
crashes when '-dispaly none' is used as qemu's display type described in
the manual as:
"Do not display video output. The guest will still see an emulated
graphics card, but its output will not be displayed tothe QEMU user.
This option differs from the -nographic option in that it only affects
what is done with video output; -nographic also changes the destination
of the serial and parallel port data."
Given there's no sensible way found to skip the emulated device from the
legacy vga module, we ended up removing it from all_video dependency so
it wouldn't be loaded by default. In any case, the vbe module remain
loaded and should fulfill the requirement of most hardwares even twenty
years old or more.
The unresponsive serial input is also fixed by ensuring that console
input is loaded via appended so that they won't fail altogether with
errors by other console device if specifying on the same list.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/genmoddep.awk | 3 +++
util/grub.d/00_header.in | 10 +++++++++-
2 files changed, 12 insertions(+), 1 deletion(-)
--- a/grub-core/genmoddep.awk
+++ b/grub-core/genmoddep.awk
@@ -98,6 +98,9 @@
}
modlist = ""
while (getline <"video.lst") {
+ if ($1 == "vga") {
+ continue;
+ }
modlist = modlist " " $1;
}
printf "all_video:%s\n", modlist;
--- a/util/grub.d/00_header.in
+++ b/util/grub.d/00_header.in
@@ -287,7 +287,15 @@
;;
x*)
cat << EOF
-terminal_output ${GRUB_TERMINAL_OUTPUT}
+
+for i in ${GRUB_TERMINAL_OUTPUT}; do
+ if [ x\${use_append} = xtrue ]; then
+ terminal_output --append \$i
+ elif terminal_output \$i; then
+ use_append=true;
+ fi
+done
+
EOF
;;
esac

View File

@ -0,0 +1,286 @@
From fe7ed9104cef56f9e532a0c9a7164393d5d69ae1 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 17 Nov 2023 12:32:59 +0800
Subject: [PATCH 1/4] Improve TPM key protection on boot interruptions
The unattended boot process for full disk encryption relies on an
authorized TPM policy to ensure the system's integrity before releasing
the key to grub. Subsequently, grub assumes responsibility for securing
the boot process, directing it towards a trusted default without any
expected interruptions. Any interruption during this process indicates
potential modification attempts, and releasing the obtained key to the
next stage should not occur in such cases.
This commit addresses a vulnerability associated with interrupted boot
processes that could potentially enable malicious modifications to the
default or trusted boot target. To reinforce system security, the code
has been updated to incorporate measures that discard the TPM protected
key in the event of boot interruptions.
Furthermore, this patch aims to enhance code readability by renaming
structures and function names related to cryptographic keys, improving
clarity and maintainability.
By implementing these changes, this enhancement seeks to fortify the
protection of TPM keys, thereby ensuring a more robust defense against
potential unauthorized modifications during the boot process.
Signed-Off-by Michael Chang <mchang@suse.com>
---
grub-core/commands/crypttab.c | 38 ++++++++++++++++++++++++++---------
grub-core/disk/cryptodisk.c | 8 +++++++-
grub-core/loader/linux.c | 6 +++---
grub-core/normal/main.c | 2 +-
grub-core/normal/menu.c | 7 +++++++
grub-core/normal/menu_entry.c | 2 +-
include/grub/crypttab.h | 18 ++++++++++-------
7 files changed, 59 insertions(+), 22 deletions(-)
diff --git a/grub-core/commands/crypttab.c b/grub-core/commands/crypttab.c
index c2217ca98..9397bede9 100644
--- a/grub-core/commands/crypttab.c
+++ b/grub-core/commands/crypttab.c
@@ -9,17 +9,20 @@
GRUB_MOD_LICENSE ("GPLv3+");
-struct grub_key_publisher *kpuber;
+grub_crypto_key_list_t *cryptokey_lst;
grub_err_t
-grub_initrd_publish_key (const char *uuid, const char *key, grub_size_t key_len, const char *path)
+grub_cryptokey_add_or_update (const char *uuid, const char *key, grub_size_t key_len, const char *path, int is_tpmkey)
{
- struct grub_key_publisher *cur = NULL;
+ grub_crypto_key_list_t *cur = NULL;
- FOR_LIST_ELEMENTS (cur, kpuber)
+ FOR_LIST_ELEMENTS (cur, cryptokey_lst)
if (grub_uuidcasecmp (cur->name, uuid, sizeof (cur->name)) == 0)
break;
+ if (!cur && !uuid)
+ return GRUB_ERR_NONE;
+
if (!cur)
cur = grub_zalloc (sizeof (*cur));
if (!cur)
@@ -44,21 +47,24 @@ grub_initrd_publish_key (const char *uuid, const char *key, grub_size_t key_len,
cur->path = grub_strdup (path);
}
+ if (is_tpmkey >= 0)
+ cur->is_tpmkey = is_tpmkey;
+
if (!cur->name)
{
cur->name = grub_strdup (uuid);
- grub_list_push (GRUB_AS_LIST_P (&kpuber), GRUB_AS_LIST (cur));
+ grub_list_push (GRUB_AS_LIST_P (&cryptokey_lst), GRUB_AS_LIST (cur));
}
return GRUB_ERR_NONE;
}
void
-grub_initrd_discard_key (void)
+grub_cryptokey_discard (void)
{
- struct grub_key_publisher *cur, *nxt;
+ grub_crypto_key_list_t *cur, *nxt;
- FOR_LIST_ELEMENTS_SAFE (cur, nxt, kpuber)
+ FOR_LIST_ELEMENTS_SAFE (cur, nxt, cryptokey_lst)
{
grub_list_remove (GRUB_AS_LIST (cur));
grub_memset (cur->key, 0, cur->key_len);
@@ -69,6 +75,20 @@ grub_initrd_discard_key (void)
}
}
+void
+grub_cryptokey_tpmkey_discard (void)
+{
+ grub_crypto_key_list_t *cur = NULL;
+
+ FOR_LIST_ELEMENTS (cur, cryptokey_lst)
+ if (cur->is_tpmkey)
+ break;
+
+ /* Discard all keys if any of them is tpm */
+ if (cur)
+ grub_cryptokey_discard();
+}
+
static grub_err_t
grub_cmd_crypttab_entry (grub_command_t cmd __attribute__ ((unused)),
int argc, char **argv)
@@ -92,7 +112,7 @@ grub_cmd_crypttab_entry (grub_command_t cmd __attribute__ ((unused)),
}
/*FIXME: Validate UUID string*/
- return grub_initrd_publish_key (argv[1], NULL, 0, path);
+ return grub_cryptokey_add_or_update (argv[1], NULL, 0, path, -1);
}
static grub_command_t cmd;
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index c79d4125a..d90ca06dc 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -1071,6 +1071,9 @@ grub_cryptodisk_scan_device_real (const char *name,
struct cryptodisk_read_hook_ctx read_hook_data = {0};
int askpass = 0;
char *part = NULL;
+#ifndef GRUB_UTIL
+ int is_tpmkey = 0;
+#endif
dev = grub_cryptodisk_get_by_source_disk (source);
@@ -1183,6 +1186,9 @@ grub_cryptodisk_scan_device_real (const char *name,
ret = grub_cryptodisk_insert (dev, name, source);
if (ret != GRUB_ERR_NONE)
goto error;
+#ifndef GRUB_UTIL
+ is_tpmkey = 1;
+#endif
goto cleanup;
}
}
@@ -1244,7 +1250,7 @@ grub_cryptodisk_scan_device_real (const char *name,
#ifndef GRUB_UTIL
if (cargs->key_data && dev)
- grub_initrd_publish_key (dev->uuid, (const char *)cargs->key_data, cargs->key_len, NULL);
+ grub_cryptokey_add_or_update (dev->uuid, (const char *)cargs->key_data, cargs->key_len, NULL, is_tpmkey);
#endif
if (askpass)
{
diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c
index 9ee8f3790..e5e792958 100644
--- a/grub-core/loader/linux.c
+++ b/grub-core/loader/linux.c
@@ -226,13 +226,13 @@ grub_initrd_init (int argc, char *argv[],
int i;
int newc = 0;
struct dir *root = 0;
- struct grub_key_publisher *pk;
+ grub_crypto_key_list_t *pk;
int numkey = 0;
initrd_ctx->nfiles = 0;
initrd_ctx->components = 0;
- FOR_LIST_ELEMENTS (pk, kpuber)
+ FOR_LIST_ELEMENTS (pk, cryptokey_lst)
if (pk->key && pk->path)
numkey++;
@@ -305,7 +305,7 @@ grub_initrd_init (int argc, char *argv[],
goto overflow;
}
- FOR_LIST_ELEMENTS (pk, kpuber)
+ FOR_LIST_ELEMENTS (pk, cryptokey_lst)
if (pk->key && pk->path)
{
grub_initrd_component (pk->key, pk->key_len, pk->path, initrd_ctx);
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index a3f711d1d..1b426af69 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -479,7 +479,7 @@ grub_cmdline_run (int nested, int force_auth)
return;
}
- grub_initrd_discard_key ();
+ grub_cryptokey_discard ();
grub_normal_reader_init (nested);
while (1)
diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
index 14b0ab1ec..1df2638d7 100644
--- a/grub-core/normal/menu.c
+++ b/grub-core/normal/menu.c
@@ -32,6 +32,7 @@
#include <grub/script_sh.h>
#include <grub/gfxterm.h>
#include <grub/dl.h>
+#include <grub/crypttab.h>
/* Time to delay after displaying an error message about a default/fallback
entry failing to boot. */
@@ -708,6 +709,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot, int *notify_boot)
if (grub_key_is_interrupt (key))
{
timeout = -1;
+ grub_cryptokey_tpmkey_discard();
break;
}
@@ -790,6 +792,11 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot, int *notify_boot)
clear_timeout ();
}
+ /* Timeout is interrupted by external input, Forget tpmkey if timeout
+ * is not cut by enter */
+ if (c != '\n' && c != '\r')
+ grub_cryptokey_tpmkey_discard();
+
switch (c)
{
case GRUB_TERM_KEY_HOME:
diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c
index 384ab9ce3..e5ba91ea4 100644
--- a/grub-core/normal/menu_entry.c
+++ b/grub-core/normal/menu_entry.c
@@ -1263,7 +1263,7 @@ grub_menu_entry_run (grub_menu_entry_t entry)
return;
}
- grub_initrd_discard_key();
+ grub_cryptokey_discard();
screen = make_screen (entry);
if (! screen)
diff --git a/include/grub/crypttab.h b/include/grub/crypttab.h
index 113c53cfc..f86404686 100644
--- a/include/grub/crypttab.h
+++ b/include/grub/crypttab.h
@@ -4,21 +4,25 @@
#include <grub/types.h>
#include <grub/err.h>
-struct grub_key_publisher
+typedef struct grub_crypto_key_list
{
- struct grub_key_publisher *next;
- struct grub_key_publisher **prev;
+ struct grub_crypto_key_list *next;
+ struct grub_crypto_key_list **prev;
char *name; /* UUID */
char *path;
char *key;
grub_size_t key_len;
-};
+ int is_tpmkey;
+} grub_crypto_key_list_t;
-extern struct grub_key_publisher *EXPORT_VAR (kpuber);
+extern grub_crypto_key_list_t *EXPORT_VAR (cryptokey_lst);
grub_err_t
-grub_initrd_publish_key (const char *uuid, const char *key, grub_size_t key_len, const char *path);
+grub_cryptokey_add_or_update (const char *uuid, const char *key, grub_size_t key_len, const char *path, int is_tpmkey);
void
-grub_initrd_discard_key (void);
+grub_cryptokey_discard (void);
+
+void
+grub_cryptokey_tpmkey_discard (void);
#endif /* ! GRUB_CRYPTTAB_HEADER */
--
2.42.1

View File

@ -0,0 +1,82 @@
From b8457f2e271917c5c83a4fee286bafedf8c5790c Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Tue, 8 Aug 2023 17:57:24 +0800
Subject: [PATCH] Make grub.cfg compatible to old binaries
The new added fwsetup test in the topmost menu is always executed
regardless older grub may not be able to handle and thus trapped in a
boot loop between grub and fwsetup.
This in particular is to make sure a smooth transition if grub is rolled
back to older release and needs to boot newer snapshots.
Also removing dashes in the UUID that every version released in the wild
can handle.
Signed-off-by: Michael Chang <mchang@suse.com>
---
util/grub-probe.c | 20 +++++++++++++++++++-
util/grub.d/30_uefi-firmware.in | 16 ++++++++++------
2 files changed, 29 insertions(+), 7 deletions(-)
diff --git a/util/grub-probe.c b/util/grub-probe.c
index e7efcc268..99c738e44 100644
--- a/util/grub-probe.c
+++ b/util/grub-probe.c
@@ -290,8 +290,26 @@ probe_cryptodisk_uuid (grub_disk_t disk, char delim)
}
if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
{
+ grub_size_t i, j;
const char *uu = grub_util_cryptodisk_get_uuid (disk);
- grub_printf ("%s%c", uu, delim);
+ grub_size_t len = grub_strlen (uu);
+ char *p = grub_malloc (len + 1);
+
+ /* Removing dash in the UUID string
+ * This keeps old grub binary to work with newer config in a system,
+ * especially for snapshots. It is a temporary change to make sure smooth
+ * transition from 2.06 to 2.12-rc1 and this hunk can be removed
+ * after 2.12-rc1 release stablized.
+ */
+ for (i = 0, j = 0; i < len; i++)
+ {
+ if (uu[i] != '-')
+ p[j++] = uu[i];
+ }
+ p[j] = '\0';
+
+ grub_printf ("%s%c", p, delim);
+ grub_free (p);
}
}
diff --git a/util/grub.d/30_uefi-firmware.in b/util/grub.d/30_uefi-firmware.in
index 1c2365ddb..96ff112e5 100644
--- a/util/grub.d/30_uefi-firmware.in
+++ b/util/grub.d/30_uefi-firmware.in
@@ -32,11 +32,15 @@ gettext_printf "Adding boot menu entry for UEFI Firmware Settings ...\n" >&2
cat << EOF
if [ "\$grub_platform" = "efi" ]; then
- fwsetup --is-supported
- if [ "\$?" = 0 ]; then
- menuentry '$LABEL' \$menuentry_id_option 'uefi-firmware' {
- fwsetup
- }
- fi
+ menuentry '$LABEL' \$menuentry_id_option 'uefi-firmware' {
+ fwsetup --is-supported
+ if [ "\$?" = 0 ]; then
+ fwsetup
+ else
+ echo "Your firmware doesn't support setup menu entry from a boot loader"
+ echo "Press any key to return ..."
+ read
+ fi
+ }
fi
EOF
--
2.41.0

View File

@ -0,0 +1,150 @@
From 80bb1b17b3f596dbd7331cf9cb20a46c8ef9800b Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Sat, 22 Aug 2020 02:32:43 +0800
Subject: [PATCH] Unify the check to enable btrfs relative path
This unified the test in grub-install and grub-mkconfig that the path to
default or selected btrfs subvolume/snapshot is used if the root file
system is btrfs and the config has enabled btrfs snapshot booting.
Signed-off-by: Michael Chang <mchang@suse.com>
---
util/grub-install.c | 67 +++++++++++++++++++++++++++------------
util/grub-mkconfig_lib.in | 3 +-
2 files changed, 48 insertions(+), 22 deletions(-)
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -886,6 +886,7 @@
const char *efi_file = NULL;
char **grub_devices;
grub_fs_t grub_fs;
+ grub_fs_t root_fs;
grub_device_t grub_dev = NULL;
enum grub_install_plat platform;
char *grubdir, *device_map;
@@ -898,6 +899,8 @@
int efidir_is_mac = 0;
int is_prep = 0;
const char *pkgdatadir;
+ char *rootdir_path;
+ char **rootdir_devices;
grub_util_host_init (&argc, &argv);
product_version = xstrdup (PACKAGE_VERSION);
@@ -911,9 +914,6 @@
grub_util_load_config (&config);
- if (config.is_suse_btrfs_snapshot_enabled)
- use_relative_path_on_btrfs = 1;
-
if (!bootloader_id && config.grub_distributor)
{
char *ptr;
@@ -1064,6 +1064,45 @@
grub_hostfs_init ();
grub_host_init ();
+ {
+ char *rootdir_grub_devname;
+ grub_device_t rootdir_grub_dev;
+ char *t = grub_util_path_concat (2, "/", rootdir);
+
+ rootdir_path = grub_canonicalize_file_name (t);
+ if (!rootdir_path)
+ grub_util_error (_("failed to get canonical path of `%s'"), t);
+
+ rootdir_devices = grub_guess_root_devices (rootdir_path);
+ if (!rootdir_devices || !rootdir_devices[0])
+ grub_util_error (_("cannot find a device for %s (is /dev mounted?)"),
+ rootdir_path);
+
+ for (curdev = rootdir_devices; *curdev; curdev++)
+ grub_util_pull_device (*curdev);
+
+ rootdir_grub_devname = grub_util_get_grub_dev (rootdir_devices[0]);
+ if (!rootdir_grub_devname)
+ grub_util_error (_("cannot find a GRUB drive for %s. Check your device.map"),
+ rootdir_devices[0]);
+
+ rootdir_grub_dev = grub_device_open (rootdir_grub_devname);
+ if (! rootdir_grub_dev)
+ grub_util_error ("%s", grub_errmsg);
+
+ root_fs = grub_fs_probe (rootdir_grub_dev);
+ if (!root_fs)
+ grub_util_error ("%s", grub_errmsg);
+
+ if (config.is_suse_btrfs_snapshot_enabled
+ && grub_strncmp(root_fs->name, "btrfs", sizeof ("btrfs") - 1) == 0)
+ use_relative_path_on_btrfs = 1;
+
+ free (t);
+ free (rootdir_grub_devname);
+ grub_device_close (rootdir_grub_dev);
+ }
+
switch (platform)
{
case GRUB_INSTALL_PLATFORM_I386_EFI:
@@ -1454,8 +1493,7 @@
debug_image);
}
- if (config.is_suse_btrfs_snapshot_enabled
- && grub_strncmp(grub_fs->name, "btrfs", sizeof ("btrfs") - 1) == 0)
+ if (use_relative_path_on_btrfs)
{
if (!load_cfg_f)
load_cfg_f = grub_util_fopen (load_cfg, "wb");
@@ -1669,21 +1707,13 @@
#ifdef __linux__
- if (config.is_suse_btrfs_snapshot_enabled
- && grub_strncmp(grub_fs->name, "btrfs", sizeof ("btrfs") - 1) == 0)
+ if (use_relative_path_on_btrfs)
{
char *subvol = NULL;
char *mount_path = NULL;
- char **rootdir_devices = NULL;
- char *t = grub_util_path_concat (2, "/", rootdir);
- char *rootdir_path = grub_canonicalize_file_name (t);
-
- if (rootdir_path && grub_util_is_directory (rootdir_path))
- rootdir_devices = grub_guess_root_devices (rootdir_path);
-
- if (rootdir_devices && rootdir_devices[0])
- if (grub_strcmp (rootdir_devices[0], grub_devices[0]) == 0)
- subvol = grub_util_get_btrfs_subvol (platdir, &mount_path);
+
+ if (grub_strcmp (rootdir_devices[0], grub_devices[0]) == 0)
+ subvol = grub_util_get_btrfs_subvol (platdir, &mount_path);
if (subvol && mount_path)
{
@@ -1708,11 +1738,6 @@
}
}
- free (t);
- free (rootdir_path);
- for (curdev = rootdir_devices; *curdev; curdev++)
- free (*curdev);
- free (rootdir_devices);
free (subvol);
free (mount_path);
}
--- a/util/grub-mkconfig_lib.in
+++ b/util/grub-mkconfig_lib.in
@@ -49,7 +49,8 @@
make_system_path_relative_to_its_root ()
{
- if [ "x${SUSE_BTRFS_SNAPSHOT_BOOTING}" = "xtrue" ] ; then
+ if [ "x${SUSE_BTRFS_SNAPSHOT_BOOTING}" = "xtrue" ] &&
+ [ "x${GRUB_FS}" = "xbtrfs" ] ; then
"${grub_mkrelpath}" -r "$1"
else
"${grub_mkrelpath}" "$1"

View File

@ -0,0 +1,289 @@
From 71575829c303fe8522b46fc96b1f99f1aa4178e7 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 19 Mar 2021 22:58:45 +0800
Subject: [PATCH] Workaround volatile efi boot variable
The efi variable in Microsoft Azure virtual machine is volatile that it cannot
persist across power cycling. If we use efi variable to communicate with efi
boot manager for booting a distribution, the process would silently fail as the
default loader in the efi system partition will start to take over the process
whenever the efi variable evaporated.
That will lead to undefined symbol error one day as the default path didn't
receive any grub update so it cannot keep up with new ABI requirement by
updated grub modules.
The patch will try to workaround the problem by providing grub update to the
default path along with the distribution specific one. To avoid negative side
effects of inadvertently overwritting other loader intended in default path,
care must be taken to ensure that:
1. The workaround only takes place on detected Azure virtual machine
2. The default path is not in use by shim for the secure boot
---
Makefile.util.def | 1 +
.../osdep/basic/efi_removable_fallback.c | 26 +++
grub-core/osdep/efi_removable_fallback.c | 5 +
.../osdep/linux/efi_removable_fallback.c | 151 ++++++++++++++++++
include/grub/util/install.h | 3 +
util/grub-install.c | 19 +++
6 files changed, 205 insertions(+)
create mode 100644 grub-core/osdep/basic/efi_removable_fallback.c
create mode 100644 grub-core/osdep/efi_removable_fallback.c
create mode 100644 grub-core/osdep/linux/efi_removable_fallback.c
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -681,6 +681,9 @@
common = grub-core/osdep/journaled_fs.c;
extra_dist = grub-core/osdep/basic/journaled_fs.c;
extra_dist = grub-core/osdep/linux/journaled_fs.c;
+ common = grub-core/osdep/efi_removable_fallback.c;
+ extra_dist = grub-core/osdep/basic/efi_removable_fallback.c;
+ extra_dist = grub-core/osdep/linux/efi_removable_fallback.c;
ldadd = '$(LIBLZMA)';
ldadd = libgrubmods.a;
--- /dev/null
+++ b/grub-core/osdep/basic/efi_removable_fallback.c
@@ -0,0 +1,26 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/util/install.h>
+
+const char *
+grub_install_efi_removable_fallback (const char *efidir, enum grub_install_plat platform)
+{
+ return NULL;
+}
+
--- /dev/null
+++ b/grub-core/osdep/efi_removable_fallback.c
@@ -0,0 +1,5 @@
+#ifdef __linux__
+#include "linux/efi_removable_fallback.c"
+#else
+#include "basic/efi_removable_fallback.c"
+#endif
--- /dev/null
+++ b/grub-core/osdep/linux/efi_removable_fallback.c
@@ -0,0 +1,151 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <grub/util/install.h>
+#include <grub/emu/exec.h>
+#include <grub/emu/misc.h>
+#include <string.h>
+
+static char *
+get_dmi_id (const char *id)
+{
+ FILE *fp;
+ char *buf = NULL;
+ size_t len = 0;
+
+ char *dmi_entry;
+
+ dmi_entry = grub_util_path_concat (2, "/sys/class/dmi/id", id);
+
+ fp = grub_util_fopen (dmi_entry, "r");
+ if (!fp)
+ {
+ free (dmi_entry);
+ return NULL;
+ }
+
+ if (getline (&buf, &len, fp) == -1)
+ {
+ fclose (fp);
+ free (dmi_entry);
+ return NULL;
+ }
+
+ fclose (fp);
+ free (dmi_entry);
+ return buf;
+}
+
+
+static struct dmi {
+ const char *id;
+ const char *val;
+} azure_dmi [3] = {
+ {"bios_vendor", "Microsoft Corporation"},
+ {"product_name", "Virtual Machine"},
+ {"sys_vendor", "Microsoft Corporation"},
+};
+
+static int
+is_azure (void)
+{
+ int i;
+ int n = sizeof (azure_dmi) / sizeof (struct dmi);
+
+ for (i = 0; i < n; ++i)
+ {
+ char *val;
+
+ val = get_dmi_id (azure_dmi[i].id);
+ if (!val)
+ break;
+ if (strncmp (val, azure_dmi[i].val, strlen (azure_dmi[i].val)) != 0)
+ {
+ free (val);
+ break;
+ }
+ free (val);
+ }
+
+ return (i == n) ? 1 : 0;
+}
+
+static int
+guess_shim_installed (const char *instdir)
+{
+ const char *shim[] = {"fallback.efi", "MokManager.efi", NULL};
+ const char **s;
+
+ for (s = shim; *s ; ++s)
+ {
+ char *p = grub_util_path_concat (2, instdir, *s);
+
+ if (access (p, F_OK) == 0)
+ {
+ free (p);
+ return 1;
+ }
+ free (p);
+ }
+
+ return 0;
+}
+
+const char *
+grub_install_efi_removable_fallback (const char *efidir, enum grub_install_plat platform)
+{
+ char *instdir;
+
+ if (!is_azure ())
+ return NULL;
+
+ instdir = grub_util_path_concat (3, efidir, "EFI", "BOOT");
+
+ if (guess_shim_installed (instdir))
+ {
+ grub_util_info ("skip removable fallback occupied by shim");
+ return NULL;
+ }
+
+ free (instdir);
+
+ switch (platform)
+ {
+ case GRUB_INSTALL_PLATFORM_I386_EFI:
+ return "BOOTIA32.EFI";
+ case GRUB_INSTALL_PLATFORM_X86_64_EFI:
+ return "BOOTX64.EFI";
+ case GRUB_INSTALL_PLATFORM_IA64_EFI:
+ return "BOOTIA64.EFI";
+ case GRUB_INSTALL_PLATFORM_ARM_EFI:
+ return "BOOTARM.EFI";
+ case GRUB_INSTALL_PLATFORM_ARM64_EFI:
+ return "BOOTAA64.EFI";
+ case GRUB_INSTALL_PLATFORM_RISCV32_EFI:
+ return "BOOTRISCV32.EFI";
+ case GRUB_INSTALL_PLATFORM_RISCV64_EFI:
+ return "BOOTRISCV64.EFI";
+ default:
+ grub_util_error ("%s", _("You've found a bug"));
+ break;
+ }
+ return NULL;
+}
+
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -303,4 +303,7 @@
int
grub_install_sync_fs_journal (const char *path);
+
+const char *
+grub_install_efi_removable_fallback (const char *efidir, enum grub_install_plat platform);
#endif
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -901,6 +901,7 @@
const char *pkgdatadir;
char *rootdir_path;
char **rootdir_devices;
+ char *efidir_root;
grub_util_host_init (&argc, &argv);
product_version = xstrdup (PACKAGE_VERSION);
@@ -1175,6 +1176,7 @@
}
if (!efidir)
grub_util_error ("%s", _("cannot find EFI directory"));
+ efidir_root = grub_strdup (efidir);
efidir_device_names = grub_guess_root_devices (efidir);
if (!efidir_device_names || !efidir_device_names[0])
grub_util_error (_("cannot find a device for %s (is /dev mounted?)"),
@@ -2217,6 +2219,23 @@
free (grub_efi_cfg);
}
}
+ if (!removable)
+ {
+ const char *f;
+
+ f = grub_install_efi_removable_fallback (efidir_root, platform);
+ if (f)
+ {
+ char *t = grub_util_path_concat (3, efidir_root, "EFI", "BOOT");
+ char *dst = grub_util_path_concat (2, t, f);
+
+ grub_install_mkdir_p (t);
+ fprintf (stderr, _("Install to %s as fallback.\n"), dst);
+ grub_install_copy_file (imgfile, dst, 1);
+ grub_free (t);
+ grub_free (dst);
+ }
+ }
if (!removable && update_nvram)
{
char * efifile_path;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,179 @@
From 10d0f70ac194931c63f2cbd6fdebd6697abae992 Mon Sep 17 00:00:00 2001
From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Date: Mon, 2 Aug 2021 23:10:01 +1000
Subject: [PATCH 1/2] arm64: Fix EFI loader kernel image allocation
We are currently allocating just enough memory for the file size,
which means that the kernel BSS is in limbo (and not even zeroed).
We are also not honoring the alignment specified in the image
PE header.
This makes us use the PE optional header in which the kernel puts the
actual size it needs, including BSS, and make sure we clear it, and
honors the specified alignment for the image.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
grub-core/loader/arm64/efi/linux.c | 92 ++++++++++++++++++++----------
1 file changed, 63 insertions(+), 29 deletions(-)
diff --git a/grub-core/loader/arm64/efi/linux.c b/grub-core/loader/arm64/efi/linux.c
index b73105347..4da49a182 100644
--- a/grub-core/loader/arm64/efi/linux.c
+++ b/grub-core/loader/arm64/efi/linux.c
@@ -39,6 +39,8 @@ GRUB_MOD_LICENSE ("GPLv3+");
static grub_dl_t my_mod;
static int loaded;
+static void *kernel_alloc_addr;
+static grub_uint32_t kernel_alloc_pages;
static void *kernel_addr;
static grub_uint64_t kernel_size;
static grub_uint32_t handover_offset;
@@ -258,9 +260,8 @@ grub_linux_unload (void)
GRUB_EFI_BYTES_TO_PAGES (initrd_end - initrd_start));
initrd_start = initrd_end = 0;
grub_free (linux_args);
- if (kernel_addr)
- grub_efi_free_pages ((grub_addr_t) kernel_addr,
- GRUB_EFI_BYTES_TO_PAGES (kernel_size));
+ if (kernel_alloc_addr)
+ grub_efi_free_pages ((grub_addr_t) kernel_alloc_addr, kernel_alloc_pages);
grub_fdt_unload ();
return GRUB_ERR_NONE;
}
@@ -365,14 +366,35 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
return grub_errno;
}
+static grub_err_t
+parse_pe_header (void *kernel, grub_uint64_t *total_size,
+ grub_uint32_t *entry_offset,
+ grub_uint32_t *alignment)
+{
+ struct linux_arch_kernel_header *lh = kernel;
+ struct grub_armxx_linux_pe_header *pe;
+
+ pe = (void *)((unsigned long)kernel + lh->hdr_offset);
+
+ if (pe->opt.magic != GRUB_PE32_PE64_MAGIC)
+ return grub_error(GRUB_ERR_BAD_OS, "Invalid PE optional header magic");
+
+ *total_size = pe->opt.image_size;
+ *entry_offset = pe->opt.entry_addr;
+ *alignment = pe->opt.section_alignment;
+
+ return GRUB_ERR_NONE;
+}
+
static grub_err_t
grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_file_t file = 0;
- struct linux_arch_kernel_header lh;
- struct grub_armxx_linux_pe_header *pe;
grub_err_t err;
+ grub_off_t filelen;
+ grub_uint32_t align = 0;
+ void *kernel = NULL;
grub_dl_ref (my_mod);
@@ -386,39 +408,49 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
if (!file)
goto fail;
- kernel_size = grub_file_size (file);
+ filelen = grub_file_size (file);
+ kernel = grub_malloc(filelen);
+ if (!kernel)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel load buffer"));
+ goto fail;
+ }
- if (grub_file_read (file, &lh, sizeof (lh)) < (long) sizeof (lh))
- return grub_errno;
+ if (grub_file_read (file, kernel, filelen) < (grub_ssize_t)filelen)
+ {
+ grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"),
+ argv[0]);
+ goto fail;
+ }
- if (grub_arch_efi_linux_check_image (&lh) != GRUB_ERR_NONE)
+ grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
+
+ if (grub_arch_efi_linux_check_image (kernel) != GRUB_ERR_NONE)
+ goto fail;
+ if (parse_pe_header (kernel, &kernel_size, &handover_offset, &align) != GRUB_ERR_NONE)
goto fail;
+ grub_dprintf ("linux", "kernel mem size : %lld\n", (long long) kernel_size);
+ grub_dprintf ("linux", "kernel entry offset : %d\n", handover_offset);
+ grub_dprintf ("linux", "kernel alignment : 0x%x\n", align);
grub_loader_unset();
- grub_dprintf ("linux", "kernel file size: %lld\n", (long long) kernel_size);
- kernel_addr = grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (kernel_size));
- grub_dprintf ("linux", "kernel numpages: %lld\n",
- (long long) GRUB_EFI_BYTES_TO_PAGES (kernel_size));
- if (!kernel_addr)
+ kernel_alloc_pages = GRUB_EFI_BYTES_TO_PAGES (kernel_size + align - 1);
+ kernel_alloc_addr = grub_efi_allocate_any_pages (kernel_alloc_pages);
+ grub_dprintf ("linux", "kernel numpages: %d\n", kernel_alloc_pages);
+ if (!kernel_alloc_addr)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
goto fail;
}
-
- grub_file_seek (file, 0);
- if (grub_file_read (file, kernel_addr, kernel_size)
- < (grub_int64_t) kernel_size)
- {
- if (!grub_errno)
- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
- goto fail;
- }
+ kernel_addr = (void *)ALIGN_UP((grub_uint64_t)kernel_alloc_addr, align);
grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
-
- pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset);
- handover_offset = pe->opt.entry_addr;
+ grub_memcpy (kernel_addr, kernel, grub_min(filelen, kernel_size));
+ if (kernel_size > filelen)
+ grub_memset ((char *)kernel_addr + filelen, 0, kernel_size - filelen);
+ grub_free(kernel);
+ kernel = NULL;
cmdline_size = grub_loader_cmdline_size (argc, argv) + sizeof (LINUX_IMAGE);
linux_args = grub_malloc (cmdline_size);
@@ -442,6 +474,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
}
fail:
+ if (kernel)
+ grub_free (kernel);
+
if (file)
grub_file_close (file);
@@ -454,9 +489,8 @@ fail:
if (linux_args && !loaded)
grub_free (linux_args);
- if (kernel_addr && !loaded)
- grub_efi_free_pages ((grub_addr_t) kernel_addr,
- GRUB_EFI_BYTES_TO_PAGES (kernel_size));
+ if (kernel_alloc_addr && !loaded)
+ grub_efi_free_pages ((grub_addr_t) kernel_alloc_addr, kernel_alloc_pages);
return grub_errno;
}
--
2.31.1

View File

@ -0,0 +1,205 @@
From e9422d6869f1b2d78a7cfbfcae1610953d87705b Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 16 Feb 2023 21:28:07 +0800
Subject: [PATCH 1/2] clean up crypttab and linux modules dependency
The linux module could have quite a few dependency to other modules, the
i386-pc build in particular has many.
linux: normal vbe video boot cmdline relocator mmap
That will be easy to cause loop dependency if one of these modules has
to require function from linux. To avoid falling into the pitfall in
future extension, we move away the key publish related function from
linux to crypttab module in that it is also a right thing to do.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/commands/crypttab.c | 48 +++++++++++++++++++++++++++++-
grub-core/disk/cryptodisk.c | 2 +-
grub-core/loader/linux.c | 55 +----------------------------------
include/grub/crypttab.h | 22 ++++++++++++++
include/grub/linux.h | 3 --
5 files changed, 71 insertions(+), 59 deletions(-)
create mode 100644 include/grub/crypttab.h
--- a/grub-core/commands/crypttab.c
+++ b/grub-core/commands/crypttab.c
@@ -3,10 +3,56 @@
#include <grub/command.h>
#include <grub/misc.h>
#include <grub/i18n.h>
-#include <grub/linux.h>
+#include <grub/mm.h>
+#include <grub/list.h>
+#include <grub/crypttab.h>
GRUB_MOD_LICENSE ("GPLv3+");
+struct grub_key_publisher *kpuber;
+
+grub_err_t
+grub_initrd_publish_key (const char *uuid, const char *key, grub_size_t key_len, const char *path)
+{
+ struct grub_key_publisher *cur = NULL;
+
+ FOR_LIST_ELEMENTS (cur, kpuber)
+ if (grub_uuidcasecmp (cur->name, uuid, sizeof (cur->name)) == 0)
+ break;
+
+ if (!cur)
+ cur = grub_zalloc (sizeof (*cur));
+ if (!cur)
+ return grub_errno;
+
+ if (key && key_len)
+ {
+ grub_free (cur->key);
+ cur->key = grub_malloc (key_len);
+ if (!cur->key)
+ {
+ grub_free (cur);
+ return grub_errno;
+ }
+ grub_memcpy (cur->key, key, key_len);
+ cur->key_len = key_len;
+ }
+
+ if (path)
+ {
+ grub_free (cur->path);
+ cur->path = grub_strdup (path);
+ }
+
+ if (!cur->name)
+ {
+ cur->name = grub_strdup (uuid);
+ grub_list_push (GRUB_AS_LIST_P (&kpuber), GRUB_AS_LIST (cur));
+ }
+
+ return GRUB_ERR_NONE;
+}
+
static grub_err_t
grub_cmd_crypttab_entry (grub_command_t cmd __attribute__ ((unused)),
int argc, char **argv)
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -31,7 +31,7 @@
#ifdef GRUB_UTIL
#include <grub/emu/hostdisk.h>
#else
-#include <grub/linux.h>
+#include <grub/crypttab.h>
#endif
GRUB_MOD_LICENSE ("GPLv3+");
--- a/grub-core/loader/linux.c
+++ b/grub-core/loader/linux.c
@@ -6,6 +6,7 @@
#include <grub/mm.h>
#include <grub/safemath.h>
#include <grub/list.h>
+#include <grub/crypttab.h>
struct newc_head
{
@@ -40,18 +41,6 @@
struct dir *child;
};
-struct grub_key_publisher
-{
- struct grub_key_publisher *next;
- struct grub_key_publisher **prev;
- char *name; /* UUID */
- char *path;
- char *key;
- grub_size_t key_len;
-};
-
-static struct grub_key_publisher *kpuber;
-
static char
hex (grub_uint8_t val)
{
@@ -436,45 +425,3 @@
root = 0;
return GRUB_ERR_NONE;
}
-
-grub_err_t
-grub_initrd_publish_key (const char *uuid, const char *key, grub_size_t key_len, const char *path)
-{
- struct grub_key_publisher *cur = NULL;
-
- FOR_LIST_ELEMENTS (cur, kpuber)
- if (grub_uuidcasecmp (cur->name, uuid, sizeof (cur->name)) == 0)
- break;
-
- if (!cur)
- cur = grub_zalloc (sizeof (*cur));
- if (!cur)
- return grub_errno;
-
- if (key && key_len)
- {
- grub_free (cur->key);
- cur->key = grub_malloc (key_len);
- if (!cur->key)
- {
- grub_free (cur);
- return grub_errno;
- }
- grub_memcpy (cur->key, key, key_len);
- cur->key_len = key_len;
- }
-
- if (path)
- {
- grub_free (cur->path);
- cur->path = grub_strdup (path);
- }
-
- if (!cur->name)
- {
- cur->name = grub_strdup (uuid);
- grub_list_push (GRUB_AS_LIST_P (&kpuber), GRUB_AS_LIST (cur));
- }
-
- return GRUB_ERR_NONE;
-}
--- /dev/null
+++ b/include/grub/crypttab.h
@@ -0,0 +1,22 @@
+#ifndef GRUB_CRYPTTAB_HEADER
+#define GRUB_CRYPTTAB_HEADER 1
+
+#include <grub/types.h>
+#include <grub/err.h>
+
+struct grub_key_publisher
+{
+ struct grub_key_publisher *next;
+ struct grub_key_publisher **prev;
+ char *name; /* UUID */
+ char *path;
+ char *key;
+ grub_size_t key_len;
+};
+
+extern struct grub_key_publisher *EXPORT_VAR (kpuber);
+
+grub_err_t
+grub_initrd_publish_key (const char *uuid, const char *key, grub_size_t key_len, const char *path);
+
+#endif /* ! GRUB_CRYPTTAB_HEADER */
--- a/include/grub/linux.h
+++ b/include/grub/linux.h
@@ -22,6 +22,3 @@
grub_err_t
grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx,
void *target);
-
-grub_err_t
-grub_initrd_publish_key (const char *uuid, const char *key, grub_size_t key_len, const char *path);

View File

@ -0,0 +1,35 @@
From 652b221a5eacb1421891c1469608028e2c2f0615 Mon Sep 17 00:00:00 2001
From: Glenn Washburn <development@efficientek.com>
Date: Fri, 18 Aug 2023 12:27:22 -0500
Subject: [PATCH] disk/cryptodisk: Fix missing change when updating to use
grub_uuidcasecmp
This was causing the cryptomount command to return failure even though
the crypto device was successfully added. Of course, this meant that any
script using the return code would behave unexpectedly.
Fixes: 3cf2e848bc03 (disk/cryptodisk: Allows UUIDs to be compared in a dash-insensitive manner)
Suggested-by: Olaf Hering <olaf@aepfle.de>
Signed-off-by: Glenn Washburn <development@efficientek.com>
---
grub-core/disk/cryptodisk.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 802b191b2..c79d4125a 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -1323,7 +1323,8 @@ grub_cryptodisk_scan_device (const char *name,
dev = grub_cryptodisk_scan_device_real (name, source, cargs);
if (dev)
{
- ret = (cargs->search_uuid != NULL && grub_strcasecmp (cargs->search_uuid, dev->uuid) == 0);
+ ret = (cargs->search_uuid != NULL
+ && grub_uuidcasecmp (cargs->search_uuid, dev->uuid, sizeof (dev->uuid)) == 0);
goto cleanup;
}
--
2.41.0

View File

@ -0,0 +1,103 @@
From 987ab0dfbe7ef42bb6386fb7b428d3b965ba6d2b Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 7 Sep 2020 17:02:57 +0800
Subject: [PATCH] efi/linux: provide linux command
The linux kernel's efi handover entry point is used to boot efistub of
the linux kernel. Since then the efistub has been improved with many new
features and fixes that ordinary 32-bit entry point cannot provide.
Besides, nearly every x86 efi kernel is built with efistub enabled so it
is of little value to keep 32-bit entry as default to boot kernel
without needed kconfig options enabled.
For all good reasons, making efi handover the default entry point for
booting kernel in x86 efi platform so that linux command works in the
same way to linuxefi. This can also reduce the complexity of providing
general grub configuation for x86 system due to the linux command may
not be available in signed image for UEFI Secure Boot and linuxefi is
not available for leagcy bios booting.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/Makefile.core.def | 6 ++++--
grub-core/gensyminfo.sh.in | 3 +++
grub-core/loader/i386/efi/linux.c | 17 +++++++++++++----
3 files changed, 20 insertions(+), 6 deletions(-)
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1840,7 +1840,9 @@
module = {
name = linux;
- x86 = loader/i386/linux.c;
+ i386_pc = loader/i386/linux.c;
+ i386_efi = loader/i386/efi/linux.c;
+ x86_64_efi = loader/i386/efi/linux.c;
i386_xen_pvh = loader/i386/linux.c;
xen = loader/i386/xen.c;
i386_pc = lib/i386/pc/vesa_modes_table.c;
@@ -1856,8 +1858,6 @@
loongarch64 = loader/efi/linux.c;
riscv32 = loader/efi/linux.c;
riscv64 = loader/efi/linux.c;
- i386_efi = loader/efi/linux.c;
- x86_64_efi = loader/efi/linux.c;
emu = loader/emu/linux.c;
common = loader/linux.c;
};
@@ -1922,7 +1922,7 @@
module = {
name = linuxefi;
- efi = loader/i386/efi/linux.c;
+ efi = lib/fake_module.c;
enable = i386_efi;
enable = x86_64_efi;
};
--- a/grub-core/gensyminfo.sh.in
+++ b/grub-core/gensyminfo.sh.in
@@ -35,3 +35,6 @@
# Print all undefined symbols used by module
@TARGET_NM@ -u @TARGET_NMFLAGS_MINUS_P@ -p $module | sed "s@^\([^ ]*\).*@undefined $modname \1@g"
+
+# Specify linuxefi module should load default linux
+test "$modname" = "linuxefi" && echo "undefined $modname grub_initrd_init" || true
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -333,20 +333,29 @@
}
static grub_command_t cmd_linux, cmd_initrd;
+static grub_command_t cmd_linuxefi, cmd_initrdefi;
-GRUB_MOD_INIT(linuxefi)
+GRUB_MOD_INIT(linux)
{
- cmd_linux =
+ cmd_linuxefi =
grub_register_command ("linuxefi", grub_cmd_linux,
0, N_("Load Linux."));
- cmd_initrd =
+ cmd_initrdefi =
grub_register_command ("initrdefi", grub_cmd_initrd,
0, N_("Load initrd."));
+ cmd_linux =
+ grub_register_command ("linux", grub_cmd_linux,
+ 0, N_("Load Linux."));
+ cmd_initrd =
+ grub_register_command ("initrd", grub_cmd_initrd,
+ 0, N_("Load initrd."));
my_mod = mod;
}
-GRUB_MOD_FINI(linuxefi)
+GRUB_MOD_FINI(linux)
{
+ grub_unregister_command (cmd_linuxefi);
+ grub_unregister_command (cmd_initrdefi);
grub_unregister_command (cmd_linux);
grub_unregister_command (cmd_initrd);
}

View File

@ -0,0 +1,39 @@
From d02304f70b5b9c79761d8084ab9dfc66d84688e2 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Wed, 30 Nov 2022 17:02:50 +0800
Subject: [PATCH] font: Try memdisk fonts with the same name
---
grub-core/font/font.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/grub-core/font/font.c b/grub-core/font/font.c
index 18de52562..92ff415bf 100644
--- a/grub-core/font/font.c
+++ b/grub-core/font/font.c
@@ -451,7 +451,21 @@ grub_font_load (const char *filename)
#endif
if (filename[0] == '(' || filename[0] == '/' || filename[0] == '+')
- file = grub_buffile_open (filename, GRUB_FILE_TYPE_FONT, 1024);
+ {
+ char *n = grub_strdup (filename);
+ char *p = grub_strrchr (n, '/');
+ if (p)
+ {
+ char *q = grub_strrchr (p, '.');
+ if (q)
+ *q = 0;
+ p++;
+ file = try_open_from_prefix ("(memdisk)", p);
+ }
+ grub_free (n);
+ if (!file)
+ file = grub_buffile_open (filename, GRUB_FILE_TYPE_FONT, 1024);
+ }
else
{
file = try_open_from_prefix ("(memdisk)", filename);
--
2.41.0

View File

@ -0,0 +1,33 @@
From f903b9a9adb64e733e581771d2a24efae7fbe529 Mon Sep 17 00:00:00 2001
From: Fabian Vogt <fvogt@suse.de>
Date: Thu, 5 Oct 2023 11:02:25 +0200
Subject: [PATCH] fs/btrfs: Zero file data not backed by extents
Implicit holes in file data need to be zeroed explicitly, instead of
just leaving the data in the buffer uninitialized.
This led to kernels randomly failing to boot in "fun" ways when loaded
from btrfs with the no_holes feature enabled, because large blocks of
zeros in the kernel file contained random data instead.
Signed-off-by: Fabian Vogt <fvogt@suse.de>
---
grub-core/fs/btrfs.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
index 19bff4610..ba0c58352 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -1603,6 +1603,8 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
csize = grub_le_to_cpu64 (key_out.offset) - pos;
if (csize > len)
csize = len;
+
+ grub_memset (buf, 0, csize);
buf += csize;
pos += csize;
len -= csize;
--
2.42.0

View File

@ -0,0 +1,93 @@
From 43651027d24e62a7a463254165e1e46e42aecdea Mon Sep 17 00:00:00 2001
From: Maxim Suhanov <dfirblog@gmail.com>
Date: Mon, 28 Aug 2023 16:31:57 +0300
Subject: [PATCH 1/6] fs/ntfs: Fix an OOB write when parsing the
$ATTRIBUTE_LIST attribute for the $MFT file
When parsing an extremely fragmented $MFT file, i.e., the file described
using the $ATTRIBUTE_LIST attribute, current NTFS code will reuse a buffer
containing bytes read from the underlying drive to store sector numbers,
which are consumed later to read data from these sectors into another buffer.
These sectors numbers, two 32-bit integers, are always stored at predefined
offsets, 0x10 and 0x14, relative to first byte of the selected entry within
the $ATTRIBUTE_LIST attribute. Usually, this won't cause any problem.
However, when parsing a specially-crafted file system image, this may cause
the NTFS code to write these integers beyond the buffer boundary, likely
causing the GRUB memory allocator to misbehave or fail. These integers contain
values which are controlled by on-disk structures of the NTFS file system.
Such modification and resulting misbehavior may touch a memory range not
assigned to the GRUB and owned by firmware or another EFI application/driver.
This fix introduces checks to ensure that these sector numbers are never
written beyond the boundary.
Fixes: CVE-2023-4692
Reported-by: Maxim Suhanov <dfirblog@gmail.com>
Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/ntfs.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
index bbdbe24ad..c3c4db117 100644
--- a/grub-core/fs/ntfs.c
+++ b/grub-core/fs/ntfs.c
@@ -184,7 +184,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
}
if (at->attr_end)
{
- grub_uint8_t *pa;
+ grub_uint8_t *pa, *pa_end;
at->emft_buf = grub_malloc (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
if (at->emft_buf == NULL)
@@ -209,11 +209,13 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
}
at->attr_nxt = at->edat_buf;
at->attr_end = at->edat_buf + u32at (pa, 0x30);
+ pa_end = at->edat_buf + n;
}
else
{
at->attr_nxt = at->attr_end + u16at (pa, 0x14);
at->attr_end = at->attr_end + u32at (pa, 4);
+ pa_end = at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
}
at->flags |= GRUB_NTFS_AF_ALST;
while (at->attr_nxt < at->attr_end)
@@ -230,6 +232,13 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
at->flags |= GRUB_NTFS_AF_GPOS;
at->attr_cur = at->attr_nxt;
pa = at->attr_cur;
+
+ if ((pa >= pa_end) || (pa_end - pa < 0x18))
+ {
+ grub_error (GRUB_ERR_BAD_FS, "can\'t parse attribute list");
+ return NULL;
+ }
+
grub_set_unaligned32 ((char *) pa + 0x10,
grub_cpu_to_le32 (at->mft->data->mft_start));
grub_set_unaligned32 ((char *) pa + 0x14,
@@ -240,6 +249,13 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
{
if (*pa != attr)
break;
+
+ if ((pa >= pa_end) || (pa_end - pa < 0x18))
+ {
+ grub_error (GRUB_ERR_BAD_FS, "can\'t parse attribute list");
+ return NULL;
+ }
+
if (read_attr
(at, pa + 0x10,
u32at (pa, 0x10) * (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR),
--
2.42.0

View File

@ -0,0 +1,51 @@
From b541e93b4dab6f652941d086af4fe2da676d0ee3 Mon Sep 17 00:00:00 2001
From: Lidong Chen <lidong.chen@oracle.com>
Date: Thu, 28 Sep 2023 22:33:44 +0000
Subject: [PATCH 1/3] fs/xfs: Incorrect short form directory data boundary
check
After parsing of the current entry, the entry pointer is advanced
to the next entry at the end of the "for" loop. In case where the
last entry is at the end of the data boundary, the advanced entry
pointer can point off the data boundary. The subsequent boundary
check for the advanced entry pointer can cause a failure.
The fix is to include the boundary check into the "for" loop
condition.
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Tested-by: Marta Lewandowska <mlewando@redhat.com>
---
grub-core/fs/xfs.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
index b91cd32b4..ebf962793 100644
--- a/grub-core/fs/xfs.c
+++ b/grub-core/fs/xfs.c
@@ -810,7 +810,8 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
if (iterate_dir_call_hook (parent, "..", &ctx))
return 1;
- for (i = 0; i < head->count; i++)
+ for (i = 0; i < head->count &&
+ (grub_uint8_t *) de < ((grub_uint8_t *) dir + grub_xfs_fshelp_size (dir->data)); i++)
{
grub_uint64_t ino;
grub_uint8_t *inopos = grub_xfs_inline_de_inopos(dir->data, de);
@@ -845,10 +846,6 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
de->name[de->len] = c;
de = grub_xfs_inline_next_de(dir->data, head, de);
-
- if ((grub_uint8_t *) de >= (grub_uint8_t *) dir + grub_xfs_fshelp_size (dir->data))
- return grub_error (GRUB_ERR_BAD_FS, "invalid XFS directory entry");
-
}
break;
}
--
2.42.1

View File

@ -0,0 +1,101 @@
From 83a6f72e1896bd012b7fbca21317e96c2c22b327 Mon Sep 17 00:00:00 2001
From: Michal Suchanek <msuchanek@suse.de>
Date: Wed, 12 Jan 2022 19:25:54 +0100
Subject: [PATCH] grub-install: Add SUSE signed image support for powerpc.
Signed-off-by: Michal Suchanek <msuchanek@suse.de>
---
grub-core/osdep/linux/platform.c | 13 +++++++++++++
include/grub/util/install.h | 3 +++
util/grub-install.c | 29 ++++++++++++++++++++++++++---
3 files changed, 42 insertions(+), 3 deletions(-)
--- a/grub-core/osdep/linux/platform.c
+++ b/grub-core/osdep/linux/platform.c
@@ -154,3 +154,16 @@
grub_util_info ("... not found");
return "i386-pc";
}
+
+int
+grub_install_get_powerpc_secure_boot (void)
+{
+ int32_t ret = -1;
+ FILE *fp = grub_util_fopen ("/proc/device-tree/ibm,secure-boot", "rb");
+ if (fp) {
+ if (fread (&ret , 1, sizeof(ret), fp) > 0)
+ ret = grub_be_to_cpu32(ret);
+ fclose(fp);
+ }
+ return ret;
+}
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -233,6 +233,9 @@
grub_install_get_default_x86_platform (void);
int
+grub_install_get_powerpc_secure_boot (void);
+
+int
grub_install_register_efi (grub_device_t efidir_grub_dev,
const char *efifile_path,
const char *efi_distributor);
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -321,10 +321,10 @@
{"suse-enable-tpm", OPTION_SUSE_ENABLE_TPM, 0, 0, N_("install TPM modules"), 0},
{"suse-force-signed", OPTION_SUSE_FORCE_SIGNED, 0, 0,
N_("force installation of signed grub" "%s."
- "This option is only available on ARM64 EFI targets."), 0},
+ "This option is only available on ARM64 EFI and powerpc targets."), 0},
{"suse-inhibit-signed", OPTION_SUSE_INHIBIT_SIGNED, 0, 0,
N_("inhibit installation of signed grub. "
- "This option is only available on ARM64 EFI targets."), 0},
+ "This option is only available on ARM64 EFI and powerpc targets."), 0},
{"debug", OPTION_DEBUG, 0, OPTION_HIDDEN, 0, 2},
{"no-floppy", OPTION_NO_FLOPPY, 0, OPTION_HIDDEN, 0, 2},
{"debug-image", OPTION_DEBUG_IMAGE, N_("STRING"), OPTION_HIDDEN, 0, 2},
@@ -1749,6 +1749,7 @@
char mkimage_target[200];
const char *core_name = NULL;
char *signed_imgfile = NULL;
+ int ppc_sb_state = -1;
switch (platform)
{
@@ -1796,11 +1797,33 @@
grub_install_get_platform_platform (platform));
break;
+
+ case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
+ ppc_sb_state = grub_install_get_powerpc_secure_boot();
+
+ if ((signed_grub_mode >= SIGNED_GRUB_FORCE) || ((signed_grub_mode == SIGNED_GRUB_AUTO) && (ppc_sb_state > 0)))
+ {
+ signed_imgfile = grub_util_path_concat (2, grub_install_source_directory, "grub.elf");
+ if (!grub_util_is_regular (signed_imgfile))
+ {
+ if ((signed_grub_mode >= SIGNED_GRUB_FORCE) || (ppc_sb_state > 1))
+ grub_util_error ("signed image `%s' does not exist\n", signed_imgfile);
+ else
+ {
+ free (signed_imgfile);
+ signed_imgfile = NULL;
+ }
+ }
+ }
+
+ if (signed_imgfile)
+ fprintf (stderr, _("Use signed file in %s for installation.\n"), signed_imgfile);
+
+ /* fallthrough. */
case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
case GRUB_INSTALL_PLATFORM_ARM_COREBOOT:
case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT:
case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
- case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
case GRUB_INSTALL_PLATFORM_I386_XEN:
case GRUB_INSTALL_PLATFORM_X86_64_XEN:
case GRUB_INSTALL_PLATFORM_I386_XEN_PVH:

View File

@ -0,0 +1,163 @@
From 58dcf7985b20de876a6fc44a591aa377d0a0302c Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 10 Feb 2022 22:16:58 +0800
Subject: [PATCH] grub-install: bailout root device probing
The root device is probed to test if the filesystem is btrfs in order to setup
boot configs for snapshot booting. However when the root device is a lvm thin
volume, due to lack in grub support, the probing will be errored out and entire
installation process aborts.
Here we call out stat to bailout the situation whenever grub fails to probe
filesystem in it's own right.
stat -f -c %T /
The command is also used by grub-mkconfig for the same purpose.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/osdep/basic/no_platform.c | 5 +++++
grub-core/osdep/unix/platform.c | 34 +++++++++++++++++++++++++++++
grub-core/osdep/windows/platform.c | 6 +++++
include/grub/util/install.h | 3 +++
util/grub-install.c | 31 ++++++++++++++++++--------
5 files changed, 70 insertions(+), 9 deletions(-)
--- a/grub-core/osdep/basic/no_platform.c
+++ b/grub-core/osdep/basic/no_platform.c
@@ -51,3 +51,8 @@
grub_util_error ("%s", _("no zIPL routines are available for your platform"));
}
+char *
+grub_install_get_filesystem (const char *path)
+{
+ return NULL;
+}
--- a/grub-core/osdep/unix/platform.c
+++ b/grub-core/osdep/unix/platform.c
@@ -250,3 +250,37 @@
"-z", dest, NULL }))
grub_util_error (_("`%s' failed.\n"), PACKAGE"-zipl-setup");
}
+
+char *
+grub_install_get_filesystem (const char *path)
+{
+ int fd;
+ pid_t pid;
+ FILE *fp;
+ ssize_t len;
+ char *buf = NULL;
+ size_t bufsz = 0;
+
+ pid = grub_util_exec_pipe ((const char * []){ "stat", "-f", "-c", "%T", path, NULL }, &fd);
+ if (!pid)
+ return NULL;
+
+ fp = fdopen (fd, "r");
+ if (!fp)
+ return NULL;
+
+ len = getline (&buf, &bufsz, fp);
+ if (len == -1)
+ {
+ free (buf);
+ fclose (fp);
+ return NULL;
+ }
+
+ fclose (fp);
+
+ if (len > 0 && buf[len - 1] == '\n')
+ buf[len - 1] = '\0';
+
+ return buf;
+}
--- a/grub-core/osdep/windows/platform.c
+++ b/grub-core/osdep/windows/platform.c
@@ -440,3 +440,9 @@
{
grub_util_error ("%s", _("no zIPL routines are available for your platform"));
}
+
+char *
+grub_install_get_filesystem (const char *path)
+{
+ return NULL;
+}
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -251,6 +251,9 @@
void
grub_install_zipl (const char *d, int i, int f);
+char *
+grub_install_get_filesystem (const char *path);
+
int
grub_install_compress_gzip (const char *src, const char *dest);
int
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -887,7 +887,6 @@
const char *efi_file = NULL;
char **grub_devices;
grub_fs_t grub_fs;
- grub_fs_t root_fs;
grub_device_t grub_dev = NULL;
enum grub_install_plat platform;
char *grubdir, *device_map;
@@ -1067,8 +1066,10 @@
grub_host_init ();
{
- char *rootdir_grub_devname;
- grub_device_t rootdir_grub_dev;
+ grub_device_t rootdir_grub_dev = NULL;
+ char *rootdir_grub_devname = NULL;
+ char *root_fs_name = NULL;
+
char *t = grub_util_path_concat (2, "/", rootdir);
rootdir_path = grub_canonicalize_file_name (t);
@@ -1089,20 +1090,32 @@
rootdir_devices[0]);
rootdir_grub_dev = grub_device_open (rootdir_grub_devname);
- if (! rootdir_grub_dev)
- grub_util_error ("%s", grub_errmsg);
+ if (!rootdir_grub_dev)
+ {
+ root_fs_name = grub_install_get_filesystem (t);
+ if (root_fs_name)
+ grub_errno = 0;
+ }
+ else
+ {
+ grub_fs_t root_fs = grub_fs_probe (rootdir_grub_dev);
+ if (root_fs)
+ root_fs_name = grub_strdup (root_fs->name);
+ }
- root_fs = grub_fs_probe (rootdir_grub_dev);
- if (!root_fs)
+ if (!root_fs_name)
grub_util_error ("%s", grub_errmsg);
if (config.is_suse_btrfs_snapshot_enabled
- && grub_strncmp(root_fs->name, "btrfs", sizeof ("btrfs") - 1) == 0)
+ && root_fs_name
+ && grub_strncmp(root_fs_name, "btrfs", sizeof ("btrfs") - 1) == 0)
use_relative_path_on_btrfs = 1;
+ free (root_fs_name);
free (t);
free (rootdir_grub_devname);
- grub_device_close (rootdir_grub_dev);
+ if (rootdir_grub_dev)
+ grub_device_close (rootdir_grub_dev);
}
switch (platform)

View File

@ -0,0 +1,110 @@
From ed0ac581ad3866197fc05c7cf48e39419a51f606 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 18 Mar 2022 13:19:33 +0800
Subject: [PATCH] grub-probe: Deduplicate probed partmap output
If the target device being probed is staked on top of other physical or logical
devices, all containing device's partition map type will be printed once if
--target=partmap is used. This usually results in duplicated output as same
partition map type.
This in turn may clutter grub.cfg with many duplicated insmod part_[a-z]+ if
the /boot is RAIDed because --target=partmap output is used to producing
partmap modules required to access disk device.
Let's deduplicate that to make the grub.cfg looks better and disciplined.
Signed-off-by: Michael Chang <mchang@suse.com>
---
util/grub-probe.c | 59 +++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 55 insertions(+), 4 deletions(-)
diff --git a/util/grub-probe.c b/util/grub-probe.c
index c08e46bbb..fb94f28fd 100644
--- a/util/grub-probe.c
+++ b/util/grub-probe.c
@@ -153,6 +153,50 @@ do_print (const char *x, void *data)
grub_printf ("%s%c", x, delim);
}
+static int
+check_duplicate_partmap (const char *name)
+{
+ static int alloc, used;
+ static char **partmaps;
+ int i;
+
+ if (!name)
+ {
+ if (partmaps)
+ {
+ for (i= 0; i < used; ++i)
+ free (partmaps[i]);
+ free (partmaps);
+ partmaps = NULL;
+ alloc = 0;
+ used = 0;
+ }
+ return 1;
+ }
+
+ for (i= 0; i < used; ++i)
+ if (strcmp (partmaps[i], name) == 0)
+ return 1;
+
+ if (alloc <= used)
+ {
+ alloc = (alloc) ? (alloc << 1) : 4;
+ partmaps = xrealloc (partmaps, alloc * sizeof (*partmaps));
+ }
+
+ partmaps[used++] = strdup (name);
+ return 0;
+}
+
+static void
+do_print_partmap (const char *x, void *data)
+{
+ char delim = *(const char *) data;
+ if (check_duplicate_partmap (x) != 0)
+ return;
+ grub_printf ("%s%c", x, delim);
+}
+
static void
probe_partmap (grub_disk_t disk, char delim)
{
@@ -165,10 +209,14 @@ probe_partmap (grub_disk_t disk, char delim)
}
for (part = disk->partition; part; part = part->parent)
- printf ("%s%c", part->partmap->name, delim);
+ {
+ if (check_duplicate_partmap (part->partmap->name) != 0)
+ continue;
+ printf ("%s%c", part->partmap->name, delim);
+ }
if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID)
- grub_diskfilter_get_partmap (disk, do_print, &delim);
+ grub_diskfilter_get_partmap (disk, do_print_partmap, &delim);
/* In case of LVM/RAID, check the member devices as well. */
if (disk->dev->disk_memberlist)
@@ -674,8 +722,11 @@ probe (const char *path, char **device_names, char delim)
probe_cryptodisk_uuid (dev->disk, delim);
else if (print == PRINT_PARTMAP)
- /* Check if dev->disk itself is contained in a partmap. */
- probe_partmap (dev->disk, delim);
+ {
+ /* Check if dev->disk itself is contained in a partmap. */
+ probe_partmap (dev->disk, delim);
+ check_duplicate_partmap (NULL);
+ }
else if (print == PRINT_PARTUUID)
{
--
2.35.1

View File

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

View File

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

View File

@ -0,0 +1,142 @@
From e9d3202d5cffb89223ff61ac93de86a0cac1b50c Mon Sep 17 00:00:00 2001
From: Diego Domingos <diegodo@linux.vnet.ibm.com>
Date: Thu, 19 Nov 2020 10:47:25 -0300
Subject: [PATCH] ieee1275: Avoiding many unecessary open/close
This patch aims to change the grub_ofdisk_open and grub_ofdisk_close behaviors. Since some devices (Fibre Channel and NVMe) can have a long time for shutdown notification, we should avoid open and close the disks as much as we can.
So, we are changing how those functions works. The grub_ofdisk_close will take care of just changing the disk element status, by doing a soft close, i.e, the firmware will not be called. On the other hand, the grub_ofdisk_open will take care of closing the current disk opened only if the disk requested in the current call is different from the current one. This close will be responsible to request the firmware to actually close the disk.
Yet, this patch modifies the grub_ofdisk_get_block_size function, avoiding open and close calls inside of it.
Thank you Michael Chang (mchang@suse.com) for all support.
Signed-off-by: Diego Domingos <diegodo@linux.vnet.ibm.com>
---
grub-core/disk/ieee1275/ofdisk.c | 64 +++++++++++++++++---------------
1 file changed, 35 insertions(+), 29 deletions(-)
--- a/grub-core/disk/ieee1275/ofdisk.c
+++ b/grub-core/disk/ieee1275/ofdisk.c
@@ -44,7 +44,7 @@
};
static grub_err_t
-grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size,
+grub_ofdisk_get_block_size (grub_uint32_t *block_size,
struct ofdisk_hash_ent *op);
#define OFDISK_HASH_SZ 8
@@ -461,6 +461,7 @@
grub_ssize_t actual;
grub_uint32_t block_size = 0;
grub_err_t err;
+ struct ofdisk_hash_ent *op;
if (grub_strncmp (name, "ieee1275/", sizeof ("ieee1275/") - 1) != 0)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
@@ -471,6 +472,35 @@
grub_dprintf ("disk", "Opening `%s'.\n", devpath);
+ op = ofdisk_hash_find (devpath);
+ if (!op)
+ op = ofdisk_hash_add (devpath, NULL);
+ if (!op)
+ {
+ grub_free (devpath);
+ return grub_errno;
+ }
+
+ /* Check if the call to open is the same to the last disk already opened */
+ if (last_devpath && !grub_strcmp(op->open_path,last_devpath))
+ {
+ goto finish;
+ }
+
+ /* If not, we need to close the previous disk and open the new one */
+ else {
+ if (last_ihandle){
+ grub_ieee1275_close (last_ihandle);
+ }
+ last_ihandle = 0;
+ last_devpath = NULL;
+
+ grub_ieee1275_open (op->open_path, &last_ihandle);
+ if (! last_ihandle)
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
+ last_devpath = op->open_path;
+ }
+
if (grub_ieee1275_finddevice (devpath, &dev))
{
grub_free (devpath);
@@ -491,25 +521,18 @@
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a block device");
}
+
+ finish:
/* XXX: There is no property to read the number of blocks. There
should be a property `#blocks', but it is not there. Perhaps it
is possible to use seek for this. */
disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN;
{
- struct ofdisk_hash_ent *op;
- op = ofdisk_hash_find (devpath);
- if (!op)
- op = ofdisk_hash_add (devpath, NULL);
- if (!op)
- {
- grub_free (devpath);
- return grub_errno;
- }
disk->id = (unsigned long) op;
disk->data = op->open_path;
- err = grub_ofdisk_get_block_size (devpath, &block_size, op);
+ err = grub_ofdisk_get_block_size (&block_size, op);
if (err)
{
grub_free (devpath);
@@ -528,13 +551,6 @@
static void
grub_ofdisk_close (grub_disk_t disk)
{
- if (disk->data == last_devpath)
- {
- if (last_ihandle)
- grub_ieee1275_close (last_ihandle);
- last_ihandle = 0;
- last_devpath = NULL;
- }
disk->data = 0;
}
@@ -681,7 +697,7 @@
}
static grub_err_t
-grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size,
+grub_ofdisk_get_block_size (grub_uint32_t *block_size,
struct ofdisk_hash_ent *op)
{
struct size_args_ieee1275
@@ -694,16 +710,6 @@
grub_ieee1275_cell_t size2;
} args_ieee1275;
- if (last_ihandle)
- grub_ieee1275_close (last_ihandle);
-
- last_ihandle = 0;
- last_devpath = NULL;
-
- grub_ieee1275_open (device, &last_ihandle);
- if (! last_ihandle)
- return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
-
*block_size = 0;
if (op->block_size_fails >= 2)

View File

@ -0,0 +1,250 @@
From c125cb45a7885d7bf168a05cfa4da3e681244649 Mon Sep 17 00:00:00 2001
From: Diego Domingos <diegodo@br.ibm.com>
Date: Tue, 15 Feb 2022 13:11:48 -0500
Subject: [PATCH 1/4] ieee1275: add support for NVMeoFC
Implements the functions to scan and discovery of NVMeoFC.
---
grub-core/disk/ieee1275/ofdisk.c | 217 ++++++++++++++++++++++++++++++-
1 file changed, 213 insertions(+), 4 deletions(-)
diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c
index 410f4b849..852bb95be 100644
--- a/grub-core/disk/ieee1275/ofdisk.c
+++ b/grub-core/disk/ieee1275/ofdisk.c
@@ -206,12 +206,10 @@ dev_iterate_real (const char *name, const char *path)
return;
}
+
static void
-dev_iterate (const struct grub_ieee1275_devalias *alias)
+dev_iterate_fcp_disks(const struct grub_ieee1275_devalias *alias)
{
- if (grub_strcmp (alias->type, "fcp") == 0)
- {
-
/* If we are dealing with fcp devices, we need
* to find the WWPNs and LUNs to iterate them */
grub_ieee1275_ihandle_t ihandle;
@@ -323,6 +321,217 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
grub_free (buf);
return;
+}
+
+static void
+dev_iterate_fcp_nvmeof (const struct grub_ieee1275_devalias *alias)
+{
+
+
+ char *bufptr;
+ grub_ieee1275_ihandle_t ihandle;
+
+
+ // Create the structs for the parameters passing to PFW
+ struct nvme_args_
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t method;
+ grub_ieee1275_cell_t ihandle;
+ grub_ieee1275_cell_t catch_result;
+ grub_ieee1275_cell_t nentries;
+ grub_ieee1275_cell_t table;
+ } nvme_discovery_controllers_args, nvme_controllers_args, nvme_namespaces_args;
+
+
+ // Create the structs for the results from PFW
+
+ struct discovery_controllers_table_struct_
+ {
+ grub_uint64_t table[256];
+ grub_uint32_t len;
+ } discovery_controllers_table;
+
+ /* struct nvme_controllers_table_entry
+ * this the return of nvme-controllers method tables, containing:
+ * - 2-byte controller ID
+ * - 256-byte transport address string
+ * - 256-byte field containing null-terminated NVM subsystem NQN string up to 223 characters
+ */
+ struct nvme_controllers_table_entry_
+ {
+ grub_uint16_t id;
+ char wwpn[256];
+ char nqn[256];
+ };
+
+ struct nvme_controllers_table_entry_* nvme_controllers_table = grub_malloc(sizeof(struct nvme_controllers_table_entry_)*256);
+
+ grub_uint32_t nvme_controllers_table_entries;
+
+ struct nvme_controllers_table_entry_real
+ {
+ grub_uint16_t id;
+ char wwpn[256];
+ char nqn[256];
+ };
+
+ /* Allocate memory for building the NVMeoF path */
+ char *buf = grub_malloc (grub_strlen (alias->path) + 512);
+ if (!buf)
+ {
+ grub_ieee1275_close(ihandle);
+ return;
+ }
+
+ /* Copy the alias->path to buf so we can work with */
+ bufptr = grub_stpcpy (buf, alias->path);
+ grub_snprintf (bufptr, 32, "/nvme-of");
+
+ /*
+ * Open the nvme-of layer
+ * Ex. /pci@bus/fibre-channel@@dev,func/nvme-of
+ */
+ if(grub_ieee1275_open (buf, &ihandle))
+ {
+ grub_dprintf("disk", "failed to open the disk while iterating FCP disk path=%s\n", buf);
+ return;
+ }
+
+ /*
+ * Call to nvme-discovery-controllers method from the nvme-of layer
+ * to get a list of the NVMe discovery controllers per the binding
+ */
+
+ INIT_IEEE1275_COMMON (&nvme_discovery_controllers_args.common, "call-method", 2, 2);
+ nvme_discovery_controllers_args.method = (grub_ieee1275_cell_t) "nvme-discovery-controllers";
+ nvme_discovery_controllers_args.ihandle = ihandle;
+
+ if (IEEE1275_CALL_ENTRY_FN (&nvme_discovery_controllers_args) == -1)
+ {
+ grub_dprintf("disk", "failed to get the targets while iterating FCP disk path=%s\n", buf);
+ grub_ieee1275_close(ihandle);
+ return;
+ }
+
+ /* After closing the device, the info is lost. So lets copy each buffer in the buffers table */
+
+ discovery_controllers_table.len = (grub_uint32_t) nvme_discovery_controllers_args.nentries;
+
+ unsigned int i=0;
+ for(i = 0; i < discovery_controllers_table.len; i++){
+ discovery_controllers_table.table[i] = ((grub_uint64_t*)nvme_discovery_controllers_args.table)[i];
+ }
+
+ grub_ieee1275_close(ihandle);
+
+ grub_dprintf("ofdisk","NVMeoF: Found %d discovery controllers\n",discovery_controllers_table.len);
+
+ /* For each nvme discovery controller */
+ int current_buffer_index;
+ for(current_buffer_index = 0; current_buffer_index < (int) discovery_controllers_table.len; current_buffer_index++){
+
+
+ grub_snprintf (bufptr, 64, "/nvme-of/controller@%" PRIxGRUB_UINT64_T ",ffff",
+ discovery_controllers_table.table[current_buffer_index]);
+
+ grub_dprintf("ofdisk","nvmeof controller=%s\n",buf);
+
+ if(grub_ieee1275_open (buf, &ihandle))
+ {
+ grub_dprintf("ofdisk", "failed to open the disk while getting nvme-controllers path=%s\n", buf);
+ continue;
+ }
+
+
+ INIT_IEEE1275_COMMON (&nvme_controllers_args.common, "call-method", 2, 2);
+ nvme_controllers_args.method = (grub_ieee1275_cell_t) "nvme-controllers";
+ nvme_controllers_args.ihandle = ihandle;
+ nvme_controllers_args.catch_result = 0;
+
+
+ if (IEEE1275_CALL_ENTRY_FN (&nvme_controllers_args) == -1)
+ {
+ grub_dprintf("ofdisk", "failed to get the nvme-controllers while iterating FCP disk path\n");
+ grub_ieee1275_close(ihandle);
+ continue;
+ }
+
+
+ /* Copy the buffer list to nvme_controllers_table */
+ nvme_controllers_table_entries = ((grub_uint32_t) nvme_controllers_args.nentries);
+ struct nvme_controllers_table_entry_* nvme_controllers_table_ = (struct nvme_controllers_table_entry_*) nvme_controllers_args.table;
+
+ for(i = 0; i < nvme_controllers_table_entries; i++){
+ nvme_controllers_table[i].id = (grub_uint16_t) nvme_controllers_table_[i].id;
+ grub_strcpy(nvme_controllers_table[i].wwpn, nvme_controllers_table_[i].wwpn);
+ grub_strcpy(nvme_controllers_table[i].nqn, nvme_controllers_table_[i].nqn);
+ }
+
+ grub_ieee1275_close(ihandle);
+
+ int nvme_controller_index;
+ int bufptr_pos2;
+ grub_dprintf("ofdisk","NVMeoF: found %d nvme controllers\n",(int) nvme_controllers_args.nentries);
+
+ /* For each nvme controller */
+ for(nvme_controller_index = 0; nvme_controller_index < (int) nvme_controllers_args.nentries; nvme_controller_index++){
+ /* Open the nvme controller
+ * /pci@bus/fibre-channel@dev,func/nvme-of/controller@transport-addr,ctlr-id:nqn=tgt-subsystem-nqn
+ */
+
+ bufptr_pos2 = grub_snprintf (bufptr, 512, "/nvme-of/controller@%s,ffff:nqn=%s",
+ nvme_controllers_table[nvme_controller_index].wwpn, nvme_controllers_table[nvme_controller_index].nqn);
+
+ grub_dprintf("ofdisk","NVMeoF: nvmeof controller=%s\n",buf);
+
+ if(grub_ieee1275_open (buf, &ihandle)){
+ grub_dprintf("ofdisk","failed to open the path=%s\n",buf);
+ continue;
+ }
+
+ INIT_IEEE1275_COMMON (&nvme_namespaces_args.common, "call-method", 2, 2);
+ nvme_namespaces_args.method = (grub_ieee1275_cell_t) "get-namespace-list";
+ nvme_namespaces_args.ihandle = ihandle;
+ nvme_namespaces_args.catch_result = 0;
+
+ if (IEEE1275_CALL_ENTRY_FN (&nvme_namespaces_args) == -1)
+ {
+ grub_dprintf("ofdisk", "failed to get the nvme-namespace-list while iterating FCP disk path\n");
+ grub_ieee1275_close(ihandle);
+ continue;
+ }
+
+ grub_uint32_t *namespaces = (grub_uint32_t*) nvme_namespaces_args.table;
+ grub_dprintf("ofdisk","NVMeoF: found %d namespaces\n",(int)nvme_namespaces_args.nentries);
+
+ grub_ieee1275_close(ihandle);
+
+ grub_uint32_t namespace_index = 0;
+ for(namespace_index=0; namespace_index < nvme_namespaces_args.nentries; namespace_index++){
+ grub_snprintf (bufptr+bufptr_pos2, 512, "/namespace@%"PRIxGRUB_UINT32_T,namespaces[namespace_index]);
+ grub_dprintf("ofdisk","NVMeoF: namespace=%s\n",buf);
+ dev_iterate_real(buf,buf);
+ }
+
+ dev_iterate_real(buf,buf);
+ }
+ }
+ grub_free(buf);
+ return;
+}
+
+static void
+dev_iterate (const struct grub_ieee1275_devalias *alias)
+{
+ if (grub_strcmp (alias->type, "fcp") == 0)
+ {
+ // Iterate disks
+ dev_iterate_fcp_disks(alias);
+
+ // Iterate NVMeoF
+ dev_iterate_fcp_nvmeof(alias);
+
}
else if (grub_strcmp (alias->type, "vscsi") == 0)
{
--
2.35.3

View File

@ -0,0 +1,146 @@
From a37d0cc089edd66ab35f1a27b0da09dd2f02deb3 Mon Sep 17 00:00:00 2001
From: Diego Domingos <diegodo@br.ibm.com>
Date: Mon, 24 Jun 2019 10:15:56 -0400
Subject: [PATCH] ieee1275: implement FCP methods for WWPN and LUNs
This patch enables the fcp-targets and fcp-luns methods which are
responsible to get WWPNs and LUNs for fibre channel devices.
Those methods are specially necessary if the boot directory and grub
installation are in different FCP disks, allowing the dev_iterate()
to find the WWPNs and LUNs when called by searchfs.uuid tool.
---
grub-core/disk/ieee1275/ofdisk.c | 117 ++++++++++++++++++++++++++++++-
1 file changed, 116 insertions(+), 1 deletion(-)
diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c
index ea7f78ac7..258a6e389 100644
--- a/grub-core/disk/ieee1275/ofdisk.c
+++ b/grub-core/disk/ieee1275/ofdisk.c
@@ -209,7 +209,122 @@ dev_iterate_real (const char *name, const char *path)
static void
dev_iterate (const struct grub_ieee1275_devalias *alias)
{
- if (grub_strcmp (alias->type, "vscsi") == 0)
+ if (grub_strcmp (alias->type, "fcp") == 0)
+ {
+
+ /* If we are dealing with fcp devices, we need
+ * to find the WWPNs and LUNs to iterate them */
+ grub_ieee1275_ihandle_t ihandle;
+ grub_uint64_t *ptr_targets, *ptr_luns, k, l;
+ unsigned int i, j, pos;
+ char *buf, *bufptr;
+
+ struct set_fcp_targets_args
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t method;
+ grub_ieee1275_cell_t ihandle;
+ grub_ieee1275_cell_t catch_result;
+ grub_ieee1275_cell_t nentries;
+ grub_ieee1275_cell_t table;
+ } args_targets;
+
+ struct set_fcp_luns_args
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t method;
+ grub_ieee1275_cell_t ihandle;
+ grub_ieee1275_cell_t wwpn_h;
+ grub_ieee1275_cell_t wwpn_l;
+ grub_ieee1275_cell_t catch_result;
+ grub_ieee1275_cell_t nentries;
+ grub_ieee1275_cell_t table;
+ } args_luns;
+
+ struct args_ret
+ {
+ grub_uint64_t addr;
+ grub_uint64_t len;
+ };
+
+ if(grub_ieee1275_open (alias->path, &ihandle))
+ {
+ grub_dprintf("disk", "failed to open the disk while iterating FCP disk path=%s\n", alias->path);
+ return;
+ }
+
+ /* Setup the fcp-targets method to call via pfw*/
+ INIT_IEEE1275_COMMON (&args_targets.common, "call-method", 2, 3);
+ args_targets.method = (grub_ieee1275_cell_t) "fcp-targets";
+ args_targets.ihandle = ihandle;
+
+ /* Setup the fcp-luns method to call via pfw */
+ INIT_IEEE1275_COMMON (&args_luns.common, "call-method", 4, 3);
+ args_luns.method = (grub_ieee1275_cell_t) "fcp-luns";
+ args_luns.ihandle = ihandle;
+
+ if (IEEE1275_CALL_ENTRY_FN (&args_targets) == -1)
+ {
+ grub_dprintf("disk", "failed to get the targets while iterating FCP disk path=%s\n", alias->path);
+ grub_ieee1275_close(ihandle);
+ return;
+ }
+
+ buf = grub_malloc (grub_strlen (alias->path) + 32 + 32);
+
+ if (!buf)
+ {
+ grub_ieee1275_close(ihandle);
+ return;
+ }
+
+ bufptr = grub_stpcpy (buf, alias->path);
+
+ /* Iterate over entries returned by pfw. Each entry contains a
+ * pointer to wwpn table and his length. */
+ struct args_ret *targets_table = (struct args_ret *)(args_targets.table);
+ for (i=0; i< args_targets.nentries; i++)
+ {
+ ptr_targets = (grub_uint64_t*)(grub_uint32_t) targets_table[i].addr;
+ /* Iterate over all wwpns in given table */
+ for(k=0;k<targets_table[i].len;k++)
+ {
+ args_luns.wwpn_l = (grub_ieee1275_cell_t) (*ptr_targets);
+ args_luns.wwpn_h = (grub_ieee1275_cell_t) (*ptr_targets >> 32);
+ pos=grub_snprintf (bufptr, 32, "/disk@%" PRIxGRUB_UINT64_T,
+ *ptr_targets++);
+ /* Get the luns for given wwpn target */
+ if (IEEE1275_CALL_ENTRY_FN (&args_luns) == -1)
+ {
+ grub_dprintf("disk", "failed to get the LUNS while iterating FCP disk path=%s\n", buf);
+ grub_ieee1275_close (ihandle);
+ grub_free (buf);
+ return;
+ }
+
+ struct args_ret *luns_table = (struct args_ret *)(args_luns.table);
+
+ /* Iterate over all LUNs */
+ for(j=0;j<args_luns.nentries; j++)
+ {
+ ptr_luns = (grub_uint64_t*) (grub_uint32_t) luns_table[j].addr;
+ for(l=0;l<luns_table[j].len;l++)
+ {
+ grub_snprintf (&bufptr[pos], 30, ",%" PRIxGRUB_UINT64_T,
+ *ptr_luns++);
+ dev_iterate_real(buf,buf);
+ }
+ }
+
+ }
+ }
+
+ grub_ieee1275_close (ihandle);
+ grub_free (buf);
+ return;
+
+ }
+ else if (grub_strcmp (alias->type, "vscsi") == 0)
{
static grub_ieee1275_ihandle_t ihandle;
struct set_color_args
--
2.31.1

View File

@ -0,0 +1,172 @@
From f4728ed5307b6be6377b7bdafcab55fd3676a761 Mon Sep 17 00:00:00 2001
From: Mukesh Kumar Chaurasiya <mchauras@linux.ibm.com>
Date: Mon, 17 Jul 2023 16:02:34 +0530
Subject: [PATCH] ieee1275/ofdisk: retry on open and read failure
Sometimes, when booting from a very busy SAN, the access to the
disk can fail and then grub will eventually drop to grub prompt.
This scenario is more frequent when deploying many machines at
the same time using the same SAN.
This patch aims to force the ofdisk module to retry the open or
read function for network disks excluding after it fails. We use
DEFAULT_RETRY_TIMEOUT, which is 15 seconds to specify the time it'll
retry to access the disk before it definitely fails. The timeout can be
changed by setting the environment variable ofdisk_retry_timeout.
If the environment variable fails to read, grub will consider the
default value of 15 seconds.
Signed-off-by: Diego Domingos <diegodo@linux.vnet.ibm.com>
Signed-off-by: Mukesh Kumar Chaurasiya <mchauras@linux.ibm.com>
---
docs/grub.texi | 8 ++++
grub-core/disk/ieee1275/ofdisk.c | 80 +++++++++++++++++++++++++++++++-
2 files changed, 86 insertions(+), 2 deletions(-)
diff --git a/docs/grub.texi b/docs/grub.texi
index d3f0f6577..c8ebc083d 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -3315,6 +3315,7 @@ These variables have special meaning to GRUB.
* net_default_ip::
* net_default_mac::
* net_default_server::
+* ofdisk_retry_timeout::
* pager::
* prefix::
* pxe_blksize::
@@ -3744,6 +3745,13 @@ The default is the value of @samp{color_normal} (@pxref{color_normal}).
@xref{Network}.
+@node ofdisk_retry_timeout
+@subsection ofdisk_retry_timeout
+
+The time in seconds till which the grub will retry to open or read a disk in
+case of failure to do so. This value defaults to 15 seconds.
+
+
@node pager
@subsection pager
diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c
index 7197d5401..f96bbb58c 100644
--- a/grub-core/disk/ieee1275/ofdisk.c
+++ b/grub-core/disk/ieee1275/ofdisk.c
@@ -24,6 +24,9 @@
#include <grub/ieee1275/ofdisk.h>
#include <grub/i18n.h>
#include <grub/time.h>
+#include <grub/env.h>
+
+#define RETRY_DEFAULT_TIMEOUT 15
static char *last_devpath;
static grub_ieee1275_ihandle_t last_ihandle;
@@ -783,7 +786,7 @@ compute_dev_path (const char *name)
}
static grub_err_t
-grub_ofdisk_open (const char *name, grub_disk_t disk)
+grub_ofdisk_open_real (const char *name, grub_disk_t disk)
{
grub_ieee1275_phandle_t dev;
char *devpath;
@@ -879,6 +882,56 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
return 0;
}
+static grub_uint64_t
+grub_ofdisk_disk_timeout (grub_disk_t disk)
+{
+ grub_uint64_t retry;
+ const char *timeout = grub_env_get ("ofdisk_retry_timeout");
+
+ if (!(grub_strstr (disk->name, "fibre-channel@") ||
+ grub_strstr (disk->name, "vfc-client")) ||
+ grub_strstr(disk->name, "nvme-of"))
+ {
+ /* Do not retry in case of non network drives */
+ return 0;
+ }
+
+ if (timeout != NULL)
+ {
+ retry = grub_strtoul (timeout, 0, 10);
+ if (grub_errno != GRUB_ERR_NONE)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ return RETRY_DEFAULT_TIMEOUT;
+ }
+ if (retry)
+ return retry;
+ }
+ return RETRY_DEFAULT_TIMEOUT;
+}
+
+static grub_err_t
+grub_ofdisk_open (const char *name, grub_disk_t disk)
+{
+ grub_err_t err;
+ grub_uint64_t timeout = grub_get_time_ms () + (grub_ofdisk_disk_timeout (disk) * 1000);
+ _Bool cont;
+ do
+ {
+ err = grub_ofdisk_open_real (name, disk);
+ cont = grub_get_time_ms () < timeout;
+ if (err == GRUB_ERR_UNKNOWN_DEVICE && cont)
+ {
+ grub_dprintf ("ofdisk","Failed to open disk %s. Retrying...\n", name);
+ grub_errno = GRUB_ERR_NONE;
+ }
+ else
+ break;
+ grub_millisleep (1000);
+ } while (cont);
+ return err;
+}
+
static void
grub_ofdisk_close (grub_disk_t disk)
{
@@ -915,7 +968,7 @@ grub_ofdisk_prepare (grub_disk_t disk, grub_disk_addr_t sector)
}
static grub_err_t
-grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
+grub_ofdisk_read_real (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
grub_err_t err;
@@ -934,6 +987,29 @@ grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
return 0;
}
+static grub_err_t
+grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
+ grub_size_t size, char *buf)
+{
+ grub_err_t err;
+ grub_uint64_t timeout = grub_get_time_ms () + (grub_ofdisk_disk_timeout (disk) * 1000);
+ _Bool cont;
+ do
+ {
+ err = grub_ofdisk_read_real (disk, sector, size, buf);
+ cont = grub_get_time_ms () < timeout;
+ if (err == GRUB_ERR_UNKNOWN_DEVICE && cont)
+ {
+ grub_dprintf ("ofdisk","Failed to read disk %s. Retrying...\n", (char*)disk->data);
+ grub_errno = GRUB_ERR_NONE;
+ }
+ else
+ break;
+ grub_millisleep (1000);
+ } while (cont);
+ return err;
+}
+
static grub_err_t
grub_ofdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, const char *buf)
--
2.41.0

View File

@ -0,0 +1,90 @@
From ca30b3c6fd8c848f510445316d0c4a8fca6061ba Mon Sep 17 00:00:00 2001
From: Diego Domingos <diegodo@br.ibm.com>
Date: Wed, 24 Jun 2020 08:17:18 -0400
Subject: [PATCH 1/2] ieee1275/powerpc: implements fibre channel discovery for
ofpathname
grub-ofpathname doesn't work with fibre channel because there is no
function currently implemented for it.
This patch enables it by prividing a function that looks for the port
name, building the entire path for OF devices.
---
grub-core/osdep/linux/ofpath.c | 48 ++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
index a6153d359..f2bc9fc5c 100644
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -399,6 +399,37 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
}
#endif
+static void
+of_fc_port_name(const char *path, const char *subpath, char *port_name)
+{
+ char *bname, *basepath, *p;
+ int fd;
+
+ bname = xmalloc(sizeof(char)*150);
+ basepath = xmalloc(strlen(path));
+
+ /* Generate the path to get port name information from the drive */
+ strncpy(basepath,path,subpath-path);
+ basepath[subpath-path-1] = '\0';
+ p = get_basename(basepath);
+ snprintf(bname,sizeof(char)*150,"%s/fc_transport/%s/port_name",basepath,p);
+
+ /* Read the information from the port name */
+ fd = open (bname, O_RDONLY);
+ if (fd < 0)
+ grub_util_error (_("cannot open `%s': %s"), bname, strerror (errno));
+
+ if (read(fd,port_name,sizeof(char)*19) < 0)
+ grub_util_error (_("cannot read `%s': %s"), bname, strerror (errno));
+
+ sscanf(port_name,"0x%s",port_name);
+
+ close(fd);
+
+ free(bname);
+ free(basepath);
+}
+
static int
vendor_is_ATA(const char *path)
{
@@ -577,6 +608,16 @@ of_path_of_scsi(const char *sys_devname __attribute__((unused)), const char *dev
digit_string = trailing_digits (device);
if (strncmp (of_path, "/vdevice/", sizeof ("/vdevice/") - 1) == 0)
{
+ if(strstr(of_path,"vfc-client"))
+ {
+ char * port_name = xmalloc(sizeof(char)*17);
+ of_fc_port_name(sysfs_path, p, port_name);
+
+ snprintf(disk,sizeof(disk),"/%s@%s", disk_name, port_name);
+ free(port_name);
+ }
+ else
+ {
unsigned long id = 0x8000 | (tgt << 8) | (bus << 5) | lun;
if (*digit_string == '\0')
{
@@ -590,6 +631,13 @@ of_path_of_scsi(const char *sys_devname __attribute__((unused)), const char *dev
snprintf(disk, sizeof (disk),
"/%s@%04lx000000000000:%c", disk_name, id, 'a' + (part - 1));
}
+ }
+ } else if (strstr(of_path,"fibre-channel")||(strstr(of_path,"vfc-client"))){
+ char * port_name = xmalloc(sizeof(char)*17);
+ of_fc_port_name(sysfs_path, p, port_name);
+
+ snprintf(disk,sizeof(disk),"/%s@%s", disk_name, port_name);
+ free(port_name);
}
else
{
--
2.26.2

View File

@ -0,0 +1,396 @@
From 6444774dae24f439dae3b4bc8d73449d50f06240 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 31 Dec 2020 21:54:07 +0800
Subject: [PATCH] install: fix software raid1 on esp
While running grub-install on an efi system where efi system partition
is configured as mdadm software raid1, it fails with errors like this:
grub2-install: info: copying `/boot/grub2/x86_64-efi/core.efi' -> `/boot/efi/EFI/opensuse/grubx64.efi'.
grub2-install: info: Registering with EFI: distributor = `opensuse', path = `\EFI\opensuse\grubx64.efi', ESP at mduuid/9182c46b9d469f79b48850b68f3371a5.
grub2-install: info: executing efibootmgr --version </dev/null >/dev/null.
grub2-install: info: executing modprobe -q efivars.
grub2-install: info: executing efibootmgr -c -d.
efibootmgr: option requires an argument -- 'd'
efibootmgr version 14
usage: efibootmgr [options]
This should work with mdadm raid1 with metadata 0.9 and 1.0 whose
superblocks are at the end of device. However
grub_install_register_efi() doesn't seem to work if the target is
multiple devices so that it errors out.
The patch changes grub_install_register_efi() to accept multiple devices
that can be used to creating efi boot entries for probed raid1 member
devices on mounted efi system partition.
This patch also adds check for metadata 0.9 or 1.0 or the validation
will fail to continue the install.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/disk/diskfilter.c | 27 +++----
grub-core/disk/mdraid1x_linux.c | 3 +
grub-core/osdep/basic/no_platform.c | 3 +-
grub-core/osdep/unix/platform.c | 57 +++++++++++----
grub-core/osdep/windows/platform.c | 3 +-
include/grub/diskfilter.h | 3 +-
include/grub/util/install.h | 5 +-
util/grub-install.c | 107 ++++++++++++++++++++++++++--
8 files changed, 171 insertions(+), 37 deletions(-)
--- a/grub-core/disk/diskfilter.c
+++ b/grub-core/disk/diskfilter.c
@@ -159,8 +159,8 @@
for (m = arr->pvs; m; m = m->next)
if (m->disk && m->disk->id == disk->id
&& m->disk->dev->id == disk->dev->id
- && m->part_start == grub_partition_get_start (disk->partition)
- && m->part_size == grub_disk_native_sectors (disk))
+ && grub_partition_get_start (m->disk->partition) == grub_partition_get_start (disk->partition)
+ && grub_disk_native_sectors (m->disk) == grub_disk_native_sectors (disk))
return 0;
}
@@ -1340,19 +1340,23 @@
? (grub_memcmp (pv->id.uuid, id->uuid, id->uuidlen) == 0)
: (pv->id.id == id->id))
{
+ char *part_name = NULL;
struct grub_diskfilter_lv *lv;
/* FIXME: Check whether the update time of the superblocks are
the same. */
- if (pv->disk && grub_disk_native_sectors (disk) >= pv->part_size)
+ if (pv->disk && grub_disk_native_sectors (disk) >= grub_disk_native_sectors (pv->disk))
return GRUB_ERR_NONE;
- pv->disk = grub_disk_open (disk->name);
+ if (disk->partition)
+ {
+ char *p = grub_partition_get_name (disk->partition);
+ if (p)
+ part_name = grub_xasprintf ("%s,%s", disk->name, p);
+ grub_free (p);
+ }
+ pv->disk = grub_disk_open (part_name ? : disk->name);
+ grub_free (part_name);
if (!pv->disk)
return grub_errno;
- /* This could happen to LVM on RAID, pv->disk points to the
- raid device, we shouldn't change it. */
- pv->start_sector -= pv->part_start;
- pv->part_start = grub_partition_get_start (disk->partition);
- pv->part_size = grub_disk_native_sectors (disk);
#ifdef GRUB_UTIL
{
@@ -1369,7 +1373,6 @@
#endif
if (start_sector != (grub_uint64_t)-1)
pv->start_sector = start_sector;
- pv->start_sector += pv->part_start;
/* Add the device to the array. */
for (lv = array->lvs; lv; lv = lv->next)
if (!lv->became_readable_at && lv->fullname && is_lv_readable (lv, 0))
@@ -1457,8 +1460,8 @@
{
if (pv->disk && pv->disk->id == disk->id
&& pv->disk->dev->id == disk->dev->id
- && pv->part_start == grub_partition_get_start (disk->partition)
- && pv->part_size == grub_disk_native_sectors (disk))
+ && grub_partition_get_start (pv->disk->partition) == grub_partition_get_start (disk->partition)
+ && grub_disk_native_sectors (pv->disk) == grub_disk_native_sectors (disk))
{
if (vg_out)
*vg_out = vg;
--- a/grub-core/disk/mdraid1x_linux.c
+++ b/grub-core/disk/mdraid1x_linux.c
@@ -208,6 +208,9 @@
grub_le_to_cpu32 (sb.chunksize),
grub_le_to_cpu32 (sb.layout),
grub_le_to_cpu32 (sb.level));
+#ifdef GRUB_UTIL
+ array->mdraid1x_minor_version = minor_version;
+#endif
return array;
}
--- a/grub-core/osdep/basic/no_platform.c
+++ b/grub-core/osdep/basic/no_platform.c
@@ -33,7 +33,8 @@
void
grub_install_register_efi (grub_device_t efidir_grub_dev,
const char *efifile_path,
- const char *efi_distributor)
+ const char *efi_distributor,
+ const char *force_disk)
{
grub_util_error ("%s", _("no EFI routines are available for your platform"));
}
--- a/grub-core/osdep/unix/platform.c
+++ b/grub-core/osdep/unix/platform.c
@@ -132,15 +132,14 @@
}
int
-grub_install_register_efi (grub_device_t efidir_grub_dev,
+grub_install_register_efi (const grub_disk_t *efidir_grub_disk,
const char *efifile_path,
- const char *efi_distributor)
+ const char *efi_distributor,
+ const char *force_disk)
{
- const char * efidir_disk;
- int efidir_part;
int ret;
- efidir_disk = grub_util_biosdisk_get_osdev (efidir_grub_dev->disk);
- efidir_part = efidir_grub_dev->disk->partition ? efidir_grub_dev->disk->partition->number + 1 : 1;
+ const grub_disk_t *curdisk;
+ int ndev = 0;
if (grub_util_exec_redirect_null ((const char * []){ "efibootmgr", "--version", NULL }))
{
@@ -158,22 +157,50 @@
if (ret)
return ret;
- char *efidir_part_str = xasprintf ("%d", efidir_part);
+ for (curdisk = efidir_grub_disk; *curdisk; curdisk++)
+ ndev++;
- if (!verbosity)
- ret = grub_util_exec ((const char * []){ "efibootmgr", "-q",
+ for (curdisk = efidir_grub_disk; *curdisk; curdisk++)
+ {
+ const char * efidir_disk;
+ int efidir_part;
+ char *efidir_part_str;
+ char *new_efi_distributor = NULL;
+ grub_disk_t disk = *curdisk;
+
+ efidir_disk = force_disk ? : grub_util_biosdisk_get_osdev (disk);
+ if (!efidir_disk)
+ grub_util_error (_("%s: no device for efi"), disk->name);
+
+ efidir_part = disk->partition ? disk->partition->number + 1 : 1;
+ efidir_part_str = xasprintf ("%d", efidir_part);
+ if (ndev > 1)
+ {
+ const char *p = grub_strrchr (efidir_disk, '/');
+ new_efi_distributor = xasprintf ("%s (%s%d)\n",
+ efi_distributor,
+ p ? p + 1: efidir_disk,
+ efidir_part);
+ }
+
+ if (!verbosity)
+ ret = grub_util_exec ((const char * []){ "efibootmgr", "-q",
"-c", "-d", efidir_disk,
"-p", efidir_part_str, "-w",
- "-L", efi_distributor, "-l",
+ "-L", new_efi_distributor ? : efi_distributor, "-l",
efifile_path, NULL });
- else
- ret = grub_util_exec ((const char * []){ "efibootmgr",
+ else
+ ret = grub_util_exec ((const char * []){ "efibootmgr",
"-c", "-d", efidir_disk,
"-p", efidir_part_str, "-w",
- "-L", efi_distributor, "-l",
+ "-L", new_efi_distributor ? : efi_distributor, "-l",
efifile_path, NULL });
- free (efidir_part_str);
- return ret;
+ free (efidir_part_str);
+ free (new_efi_distributor);
+ if (ret)
+ return ret;
+ }
+ return 0;
}
void
--- a/grub-core/osdep/windows/platform.c
+++ b/grub-core/osdep/windows/platform.c
@@ -204,7 +204,8 @@
int
grub_install_register_efi (grub_device_t efidir_grub_dev,
const char *efifile_path,
- const char *efi_distributor)
+ const char *efi_distributor,
+ const char *force_disk)
{
grub_uint16_t *boot_order, *new_boot_order;
grub_uint16_t *distributor16;
--- a/include/grub/diskfilter.h
+++ b/include/grub/diskfilter.h
@@ -49,6 +49,7 @@
#ifdef GRUB_UTIL
struct grub_diskfilter *driver;
+ grub_uint8_t mdraid1x_minor_version;
#endif
};
@@ -66,8 +67,6 @@
/* Optional. */
char *name;
grub_disk_t disk;
- grub_disk_addr_t part_start;
- grub_disk_addr_t part_size;
grub_disk_addr_t start_sector; /* Sector number where the data area starts. */
struct grub_diskfilter_pv *next;
/* Optional. */
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -236,9 +236,10 @@
grub_install_get_powerpc_secure_boot (void);
int
-grub_install_register_efi (grub_device_t efidir_grub_dev,
+grub_install_register_efi (const grub_disk_t *efidir_grub_disk,
const char *efifile_path,
- const char *efi_distributor);
+ const char *efi_distributor,
+ const char *force_disk);
void
grub_install_register_ieee1275 (int is_prep, const char *install_device,
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -1719,6 +1719,40 @@
}
}
prefix_drive = xasprintf ("(%s)", grub_drives[0]);
+
+ if (platform == GRUB_INSTALL_PLATFORM_X86_64_EFI
+ && grub_dev->disk
+ && grub_dev->disk->partition
+ && grub_fs->fs_uuid)
+ {
+ int raid_level;
+ char *uuid = NULL;
+ char *escaped_relpath = NULL;
+
+ raid_level = probe_raid_level (grub_dev->disk);
+ if (raid_level != 1)
+ goto out;
+
+ escaped_relpath = escape (relative_grubdir);
+ if (!escaped_relpath)
+ goto out;
+
+ if (grub_fs->fs_uuid (grub_dev, &uuid) || !uuid)
+ {
+ grub_print_error ();
+ grub_errno = 0;
+ goto out;
+ }
+
+ if (!load_cfg_f)
+ load_cfg_f = grub_util_fopen (load_cfg, "wb");
+ have_load_cfg = 1;
+ fprintf (load_cfg_f, "search --no-floppy --fs-uuid --set=root --hint='%s' %s\n", grub_drives[0], uuid);
+ fprintf (load_cfg_f, "set prefix=($root)'%s'\n", escaped_relpath);
+ grub_install_push_module ("search");
+ out:
+ grub_free (escaped_relpath);
+ }
}
#ifdef __linux__
@@ -2258,9 +2292,13 @@
{
/* Try to make this image bootable using the EFI Boot Manager, if available. */
int ret;
- ret = grub_install_register_efi (efidir_grub_dev,
+ grub_disk_t efidir_grub_disk[2];
+ efidir_grub_disk[0] = efidir_grub_dev->disk;
+ efidir_grub_disk[1] = NULL;
+ ret = grub_install_register_efi (efidir_grub_disk,
"\\System\\Library\\CoreServices",
- efi_distributor);
+ efi_distributor,
+ NULL);
if (ret)
grub_util_error (_("efibootmgr failed to register the boot entry: %s"),
strerror (ret));
@@ -2314,7 +2352,11 @@
{
char * efifile_path;
char * part;
+ int raid_level;
int ret;
+ grub_disk_t *efidir_grub_disk;
+ grub_disk_memberlist_t list = NULL, cur;
+ char * force_disk = NULL;
/* Try to make this image bootable using the EFI Boot Manager, if available. */
if (!efi_distributor || efi_distributor[0] == '\0')
@@ -2331,8 +2373,65 @@
efidir_grub_dev->disk->name,
(part ? ",": ""), (part ? : ""));
grub_free (part);
- ret = grub_install_register_efi (efidir_grub_dev,
- efifile_path, efi_distributor);
+
+ raid_level = probe_raid_level (efidir_grub_dev->disk);
+ if (raid_level >= 0 && raid_level != 1)
+ grub_util_warn (_("unsupported raid level %d detected for efi system partition"), raid_level);
+ if (raid_level == 1 && !efidir_grub_dev->disk->partition)
+ {
+ const char *raidname = NULL;
+
+ if (efidir_grub_dev->disk->dev->disk_raidname)
+ raidname = efidir_grub_dev->disk->dev->disk_raidname (efidir_grub_dev->disk);
+ if (raidname
+ && (grub_strncmp (raidname, "mdraid09", sizeof ("mdraid09")) == 0
+ || (grub_strcmp (raidname, "mdraid1x") == 0
+ && ((struct grub_diskfilter_lv *) efidir_grub_dev->disk->data)->vg->mdraid1x_minor_version == 0)))
+ {
+ if (efidir_grub_dev->disk->dev->disk_memberlist)
+ list = efidir_grub_dev->disk->dev->disk_memberlist (efidir_grub_dev->disk);
+ }
+ else
+ {
+ grub_util_warn (_("this array has metadata at the start and may not be suitable as a efi system partition."
+ " please ensure that your firmware understands md/v1.x metadata, or use --metadata=0.90"
+ " to create the array."));
+ /* Try to continue regardless metadata, nothing to lose here */
+ if (efidir_grub_dev->disk->dev->disk_memberlist)
+ list = efidir_grub_dev->disk->dev->disk_memberlist (efidir_grub_dev->disk);
+ }
+ }
+ else if (raid_level == 1)
+ force_disk = grub_util_get_os_disk (install_device);
+ if (list)
+ {
+ int i;
+ int ndisk = 0;
+
+ for (cur = list; cur; cur = cur->next)
+ ++ndisk;
+ efidir_grub_disk = xcalloc (ndisk + 1, sizeof (*efidir_grub_disk));
+ for (cur = list, i = 0; i < ndisk; cur = cur->next, i++)
+ efidir_grub_disk[i] = cur->disk;
+ efidir_grub_disk[ndisk] = NULL;
+ }
+ else
+ {
+ efidir_grub_disk = xcalloc (2, sizeof (*efidir_grub_disk));
+ efidir_grub_disk[0] = efidir_grub_dev->disk;
+ efidir_grub_disk[1] = NULL;
+ }
+ ret = grub_install_register_efi (efidir_grub_disk,
+ efifile_path, efi_distributor,
+ force_disk);
+ while (list)
+ {
+ cur = list;
+ list = list->next;
+ grub_free (cur);
+ }
+ grub_free (force_disk);
+ grub_free (efidir_grub_disk);
if (ret)
grub_util_error (_("efibootmgr failed to register the boot entry: %s"),
strerror (ret));

View File

@ -0,0 +1,229 @@
From 4bcf6f747c3ab0b998c6f5a361804e38bc9c4334 Mon Sep 17 00:00:00 2001
From: Stefan Berger <stefanb@linux.ibm.com>
Date: Wed, 4 Oct 2023 11:32:35 -0400
Subject: [PATCH] kern/ieee1275/init: Restrict high memory in presence of
fadump on ppc64
When a kernel dump is present then restrict the high memory regions to
avoid allocating memory where the kernel dump resides. Use the
ibm,kernel-dump node under /rtas to determine whether a kernel dump
exists and up to which limit GRUB can use available memory. Set the
upper_mem_limit to the size of the kernel dump section of type
REAL_MODE_REGION and therefore only allow GRUB's memory usage for high
addresses from RMO_ADDR_MAX to upper_mem_limit. This means that GRUB can
use high memory in the range of RMO_ADDR_MAX (768MB) to upper_mem_limit
and the kernel-dump memory regions above upper_mem_limit remain
untouched. This change has no effect on memory allocations below
linux_rmo_save (typically at 640MB).
Also, fall back to allocating below rmo_linux_save in case the chunk of
memory there would be larger than the chunk of memory above RMO_ADDR_MAX.
This can for example occur if a free memory area is found starting at 300MB
extending up to 1GB but a kernel dump is located at 768MB and therefore
does not allow the allocation of the high memory area but requiring to use
the chunk starting at 300MB to avoid an unnecessary out-of-memory condition.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Hari Bathini <hbathini@linux.ibm.com>
Cc: Pavithra Prakash <pavrampu@in.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Carolyn Scherrer <cpscherr@us.ibm.com>
Cc: Mahesh Salgaonkar <mahesh@linux.ibm.com>
Cc: Sourabh Jain <sourabhjain@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/kern/ieee1275/init.c | 144 ++++++++++++++++++++++++++++++++-
1 file changed, 142 insertions(+), 2 deletions(-)
diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
index bd9a4804b..d6c9c9049 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -17,6 +17,8 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <stddef.h> /* offsetof() */
+
#include <grub/kernel.h>
#include <grub/dl.h>
#include <grub/disk.h>
@@ -196,6 +198,96 @@ grub_claim_heap (void)
#else
/* Helpers for mm on powerpc. */
+/* ibm,kernel-dump data structures */
+struct kd_section
+{
+ grub_uint32_t flags;
+ grub_uint16_t src_datatype;
+#define KD_SRC_DATATYPE_REAL_MODE_REGION 0x0011
+ grub_uint16_t error_flags;
+ grub_uint64_t src_address;
+ grub_uint64_t num_bytes;
+ grub_uint64_t act_bytes;
+ grub_uint64_t dst_address;
+} GRUB_PACKED;
+
+#define MAX_KD_SECTIONS 10
+
+struct kernel_dump
+{
+ grub_uint32_t format;
+ grub_uint16_t num_sections;
+ grub_uint16_t status_flags;
+ grub_uint32_t offset_1st_section;
+ grub_uint32_t num_blocks;
+ grub_uint64_t start_block;
+ grub_uint64_t num_blocks_avail;
+ grub_uint32_t offet_path_string;
+ grub_uint32_t max_time_allowed;
+ struct kd_section kds[MAX_KD_SECTIONS]; /* offset_1st_section should point to kds[0] */
+} GRUB_PACKED;
+
+/*
+ * Determine if a kernel dump exists and if it does, then determine the highest
+ * address that grub can use for memory allocations.
+ * The caller must have initialized *highest to rmo_top. *highest will not
+ * be modified if no kernel dump is found.
+ */
+static void
+check_kernel_dump (grub_uint64_t *highest)
+{
+ struct kernel_dump kernel_dump;
+ grub_ssize_t kernel_dump_size;
+ grub_ieee1275_phandle_t rtas;
+ struct kd_section *kds;
+ grub_size_t i;
+
+ /* If there's a kernel-dump it must have at least one section */
+ if (grub_ieee1275_finddevice ("/rtas", &rtas) ||
+ grub_ieee1275_get_property (rtas, "ibm,kernel-dump", &kernel_dump,
+ sizeof (kernel_dump), &kernel_dump_size) ||
+ kernel_dump_size <= (grub_ssize_t) offsetof (struct kernel_dump, kds[1]))
+ return;
+
+ kernel_dump_size = grub_min (kernel_dump_size, (grub_ssize_t) sizeof (kernel_dump));
+
+ if (grub_be_to_cpu32 (kernel_dump.format) != 1)
+ {
+ grub_printf (_("Error: ibm,kernel-dump has an unexpected format version '%u'\n"),
+ grub_be_to_cpu32 (kernel_dump.format));
+ return;
+ }
+
+ if (grub_be_to_cpu16 (kernel_dump.num_sections) > MAX_KD_SECTIONS)
+ {
+ grub_printf (_("Error: Too many kernel dump sections: %d\n"),
+ grub_be_to_cpu32 (kernel_dump.num_sections));
+ return;
+ }
+
+ for (i = 0; i < grub_be_to_cpu16 (kernel_dump.num_sections); i++)
+ {
+ kds = (struct kd_section *) ((grub_addr_t) &kernel_dump +
+ grub_be_to_cpu32 (kernel_dump.offset_1st_section) +
+ i * sizeof (struct kd_section));
+ /* sanity check the address is within the 'kernel_dump' struct */
+ if ((grub_addr_t) kds > (grub_addr_t) &kernel_dump + kernel_dump_size + sizeof (*kds))
+ {
+ grub_printf (_("Error: 'kds' address beyond last available section\n"));
+ return;
+ }
+
+ if ((grub_be_to_cpu16 (kds->src_datatype) == KD_SRC_DATATYPE_REAL_MODE_REGION) &&
+ (grub_be_to_cpu64 (kds->src_address) == 0))
+ {
+ *highest = grub_min (*highest, grub_be_to_cpu64 (kds->num_bytes));
+ break;
+ }
+ }
+
+ return;
+}
+
/*
* How much memory does OF believe exists in total?
*
@@ -275,10 +367,31 @@ regions_claim (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type,
*
* Finally, we also want to make sure that when grub loads the kernel,
* it isn't going to use up all the memory we're trying to reserve! So
- * enforce our entire RUNTIME_MIN_SPACE here:
+ * enforce our entire RUNTIME_MIN_SPACE here (no fadump):
+ *
+ * | Top of memory == upper_mem_limit -|
+ * | |
+ * | available |
+ * | |
+ * |---------- 768 MB ----------|
+ * | |
+ * | reserved |
+ * | |
+ * |--- 768 MB - runtime min space ---|
+ * | |
+ * | available |
+ * | |
+ * |---------- 0 MB ----------|
+ *
+ * In case fadump is used, we allow the following:
*
* |---------- Top of memory ----------|
* | |
+ * | unavailable |
+ * | (kernel dump area) |
+ * | |
+ * |--------- upper_mem_limit ---------|
+ * | |
* | available |
* | |
* |---------- 768 MB ----------|
@@ -333,17 +446,44 @@ regions_claim (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type,
}
else
{
+ grub_uint64_t upper_mem_limit = rmo_top;
+ grub_uint64_t orig_addr = addr;
+
+ check_kernel_dump (&upper_mem_limit);
+
/*
* we order these cases to prefer higher addresses and avoid some
* splitting issues
+ * The following shows the order of variables:
+ * no kernel dump: linux_rmo_save < RMO_ADDR_MAX <= upper_mem_limit == rmo_top
+ * with kernel dump: liuxx_rmo_save < RMO_ADDR_MAX <= upper_mem_limit <= rmo_top
*/
- if (addr < RMO_ADDR_MAX && (addr + len) > RMO_ADDR_MAX)
+ if (addr < RMO_ADDR_MAX && (addr + len) > RMO_ADDR_MAX && upper_mem_limit >= RMO_ADDR_MAX)
{
grub_dprintf ("ieee1275",
"adjusting region for RUNTIME_MIN_SPACE: (%llx -> %llx) -> (%llx -> %llx)\n",
addr, addr + len, RMO_ADDR_MAX, addr + len);
len = (addr + len) - RMO_ADDR_MAX;
addr = RMO_ADDR_MAX;
+
+ /* We must not exceed the upper_mem_limit (assuming it's >= RMO_ADDR_MAX) */
+ if (addr + len > upper_mem_limit)
+ {
+ /* take the bigger chunk from either below linux_rmo_save or above upper_mem_limit */
+ len = upper_mem_limit - addr;
+ if (orig_addr < linux_rmo_save && linux_rmo_save - orig_addr > len)
+ {
+ /* lower part is bigger */
+ addr = orig_addr;
+ len = linux_rmo_save - addr;
+ }
+
+ grub_dprintf ("ieee1275", "re-adjusted region to: (%llx -> %llx)\n",
+ addr, addr + len);
+
+ if (len == 0)
+ return 0;
+ }
}
else if ((addr < linux_rmo_save) && ((addr + len) > linux_rmo_save))
{
--
2.42.0

View File

@ -0,0 +1,109 @@
From c2475f1337dff2e2a3e45514119d5186e55753c1 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 13 Aug 2020 09:36:45 +0800
Subject: [PATCH] kern/mm.c : Make grub_calloc inline
To circumvent the situation that symbol 'grub_calloc' not found would
happen if system is using stray grub (ie not managed by system update)
as stage1 that can be too old to load updated modules.
---
grub-core/kern/mm.c | 28 ----------------------------
include/grub/mm.h | 32 +++++++++++++++++++++++++++++++-
2 files changed, 31 insertions(+), 29 deletions(-)
--- a/grub-core/kern/mm.c
+++ b/grub-core/kern/mm.c
@@ -63,14 +63,10 @@
#include <config.h>
#include <grub/mm.h>
-#include <grub/misc.h>
-#include <grub/err.h>
#include <grub/types.h>
#include <grub/disk.h>
#include <grub/dl.h>
-#include <grub/i18n.h>
#include <grub/mm_private.h>
-#include <grub/safemath.h>
#ifdef MM_DEBUG
# undef grub_calloc
@@ -553,30 +549,6 @@
return 0;
}
-/*
- * Allocate NMEMB instances of SIZE bytes and return the pointer, or error on
- * integer overflow.
- */
-void *
-grub_calloc (grub_size_t nmemb, grub_size_t size)
-{
- void *ret;
- grub_size_t sz = 0;
-
- if (grub_mul (nmemb, size, &sz))
- {
- grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
- return NULL;
- }
-
- ret = grub_memalign (0, sz);
- if (!ret)
- return NULL;
-
- grub_memset (ret, 0, sz);
- return ret;
-}
-
/* Allocate SIZE bytes and return the pointer. */
void *
grub_malloc (grub_size_t size)
--- a/include/grub/mm.h
+++ b/include/grub/mm.h
@@ -47,7 +47,6 @@
#endif
void grub_mm_init_region (void *addr, grub_size_t size);
-void *EXPORT_FUNC(grub_calloc) (grub_size_t nmemb, grub_size_t size);
void *EXPORT_FUNC(grub_malloc) (grub_size_t size);
void *EXPORT_FUNC(grub_zalloc) (grub_size_t size);
void EXPORT_FUNC(grub_free) (void *ptr);
@@ -55,6 +54,37 @@
#ifndef GRUB_MACHINE_EMU
void *EXPORT_FUNC(grub_memalign) (grub_size_t align, grub_size_t size);
#endif
+#if !defined(GRUB_UTIL) && !defined (GRUB_MACHINE_EMU)
+#include <grub/misc.h>
+#include <grub/err.h>
+#include <grub/i18n.h>
+#include <grub/safemath.h>
+/*
+ * Allocate NMEMB instances of SIZE bytes and return the pointer, or error on
+ * integer overflow.
+ */
+static inline void *
+grub_calloc (grub_size_t nmemb, grub_size_t size)
+{
+ void *ret;
+ grub_size_t sz = 0;
+
+ if (grub_mul (nmemb, size, &sz))
+ {
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
+ return NULL;
+ }
+
+ ret = grub_memalign (0, sz);
+ if (!ret)
+ return NULL;
+
+ grub_memset (ret, 0, sz);
+ return ret;
+}
+#else
+void *EXPORT_FUNC(grub_calloc) (grub_size_t nmemb, grub_size_t size);
+#endif
void grub_mm_check_real (const char *file, int line);
#define grub_mm_check() grub_mm_check_real (GRUB_FILE, __LINE__);

View File

@ -0,0 +1,142 @@
From 06af22d6c893b0249712e9a486e0cbae15160e5c Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 23 Oct 2023 16:11:53 +0800
Subject: [PATCH] luks2: Use grub-tpm2 token for TPM2-protected volume unlock
This commit enables the use of the grub-tpm2 token for unlocking LUKS2
volumes protected by TPM2. The token tracks keyslots associated with a
sealed key, making the unsealing process more efficient and secure.
Signed-Off-by Michael Chang <mchang@suse.com>
---
grub-core/disk/luks2.c | 81 ++++++++++++++++++++++++++++++++++++++++--
1 file changed, 79 insertions(+), 2 deletions(-)
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index d5106402f..fe5ba777a 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -124,6 +124,14 @@ struct grub_luks2_digest
};
typedef struct grub_luks2_digest grub_luks2_digest_t;
+struct grub_luks2_token_tpm
+{
+ grub_uint64_t idx;
+ grub_uint64_t keyslots;
+ const char *timestamp;
+};
+typedef struct grub_luks2_token_tpm grub_luks2_token_tpm_t;
+
gcry_err_code_t AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src,
grub_uint8_t * dst, grub_size_t blocksize,
grub_size_t blocknumbers);
@@ -257,6 +265,39 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
return GRUB_ERR_NONE;
}
+static grub_err_t
+luks2_parse_token_tpm (grub_luks2_token_tpm_t *out, const grub_json_t *token)
+{
+ grub_json_t keyslots, o;
+ grub_size_t i, size;
+ grub_uint64_t bit;
+ const char *type;
+
+ if (grub_json_getstring (&type, token, "type"))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid token type");
+ else if (grub_strcmp (type, "grub-tpm2"))
+ return GRUB_ERR_NONE;
+
+ if (grub_json_getvalue (&keyslots, token, "keyslots") ||
+ grub_json_getstring (&out->timestamp, token, "timestamp"))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing token parameters");
+
+ if (grub_json_getsize (&size, &keyslots))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "Token references no keyslots");
+
+ out->keyslots = 0;
+ for (i = 0; i < size; i++)
+ {
+ if (grub_json_getchild (&o, &keyslots, i) ||
+ grub_json_getuint64 (&bit, &o, NULL))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid keyslot");
+ out->keyslots |= (1 << bit);
+ }
+
+ return GRUB_ERR_NONE;
+}
+
static grub_err_t
luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_segment_t *s,
const grub_json_t *root, grub_size_t keyslot_json_idx)
@@ -561,13 +602,14 @@ luks2_recover_key (grub_disk_t source,
{
grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
char cipher[32], *json_header = NULL, *ptr;
- grub_size_t candidate_key_len = 0, json_idx, size;
+ grub_size_t candidate_key_len = 0, json_idx, size, tsize;
grub_luks2_header_t header;
grub_luks2_keyslot_t keyslot;
grub_luks2_digest_t digest;
grub_luks2_segment_t segment;
+ grub_luks2_token_tpm_t token_tpm;
gcry_err_code_t gcry_ret;
- grub_json_t *json = NULL, keyslots;
+ grub_json_t *json = NULL, keyslots, tokens;
grub_err_t ret;
if (cargs->key_data == NULL || cargs->key_len == 0)
@@ -605,6 +647,37 @@ luks2_recover_key (grub_disk_t source,
goto err;
}
+ token_tpm.keyslots = 0;
+ tsize = 0;
+ if (cargs->protectors)
+ {
+ int i;
+ for (i = 0; cargs->protectors[i]; i++)
+ if (grub_strcmp(cargs->protectors[i], "tpm2") == 0)
+ break;
+
+ if (!cargs->protectors[i] ||
+ cargs->key_cache[i].invalid ||
+ grub_json_getvalue (&tokens, json, "tokens") ||
+ grub_json_getsize (&tsize, &tokens))
+ grub_dprintf ("luks2", "No valid token or not a tpm2 protector\n");
+ }
+
+ for (json_idx = 0; json_idx < tsize; json_idx++)
+ {
+ grub_json_t token;
+
+ if (grub_json_getchild (&token, &tokens, json_idx) ||
+ grub_json_getuint64 (&token_tpm.idx, &token, NULL) ||
+ grub_json_getchild (&token, &token, 0) ||
+ luks2_parse_token_tpm (&token_tpm, &token))
+ {
+ grub_dprintf ("luks2", "Could not parse token index %" PRIuGRUB_SIZE "\n", json_idx);
+ grub_errno = GRUB_ERR_NONE;
+ continue;
+ }
+ }
+
if (grub_disk_native_sectors (source) == GRUB_DISK_SIZE_UNKNOWN)
{
/* FIXME: Allow use of source disk, and maybe cause errors in read. */
@@ -641,6 +714,10 @@ luks2_recover_key (grub_disk_t source,
continue;
}
+ if (token_tpm.keyslots &&
+ !(token_tpm.keyslots & (1 << keyslot.idx)))
+ continue;
+
grub_dprintf ("luks2", "Trying keyslot \"%" PRIuGRUB_UINT64_T "\"\n", keyslot.idx);
/* Sector size should be one of 512, 1024, 2048, or 4096. */
--
2.42.0

View File

@ -0,0 +1,76 @@
From 1fdc9daf97a1518960e5603dd43a5f353cb3ca89 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 30 Nov 2023 13:45:13 +0800
Subject: [PATCH 1/2] mkstandalone: ensure stable timestamps for generated
images
This change mirrors a previous fix [1] but is specific to images
generated by grub-mkstandalone.
The former fix (85a7be241) focused on utilizing a stable timestamp
during binary generation in the util/mkimage context. This commit
extends that approach to the images produced by grub-mkstandalone,
ensuring consistency and stability in timestamps across all generated
binaries.
[1] 85a7be241 util/mkimage: Use stable timestamp when generating
binaries.
Signed-off-by: Michael Chang <mchang@suse.com>
Signed-off-by: Bernhard Wiedemann <bwiedemann@suse.com>
---
util/grub-mkstandalone.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/util/grub-mkstandalone.c b/util/grub-mkstandalone.c
index bdbeea6a6..8e1229925 100644
--- a/util/grub-mkstandalone.c
+++ b/util/grub-mkstandalone.c
@@ -30,6 +30,9 @@
#pragma GCC diagnostic error "-Wmissing-prototypes"
#pragma GCC diagnostic error "-Wmissing-declarations"
+/* use 2015-01-01T00:00:00+0000 as a stock timestamp */
+#define STABLE_EMBEDDING_TIMESTAMP 1420070400
+
static char *output_image;
static char **files;
static int nfiles;
@@ -184,7 +187,6 @@ add_tar_file (const char *from,
struct head hd;
grub_util_fd_t in;
ssize_t r;
- grub_uint32_t mtime = 0;
grub_uint32_t size;
COMPILE_TIME_ASSERT (sizeof (hd) == 512);
@@ -192,8 +194,6 @@ add_tar_file (const char *from,
if (grub_util_is_special_file (from))
return;
- mtime = grub_util_get_mtime (from);
-
optr = tcn = xmalloc (strlen (to) + 1);
for (iptr = to; *iptr == '/'; iptr++);
for (; *iptr; iptr++)
@@ -234,7 +234,7 @@ add_tar_file (const char *from,
memcpy (hd.gid, "0001750", 7);
set_tar_value (hd.size, optr - tcn, 12);
- set_tar_value (hd.mtime, mtime, 12);
+ set_tar_value (hd.mtime, STABLE_EMBEDDING_TIMESTAMP, 12);
hd.typeflag = 'L';
memcpy (hd.magic, MAGIC, sizeof (hd.magic));
memcpy (hd.uname, "grub", 4);
@@ -264,7 +264,7 @@ add_tar_file (const char *from,
memcpy (hd.gid, "0001750", 7);
set_tar_value (hd.size, size, 12);
- set_tar_value (hd.mtime, mtime, 12);
+ set_tar_value (hd.mtime, STABLE_EMBEDDING_TIMESTAMP, 12);
hd.typeflag = '0';
memcpy (hd.magic, MAGIC, sizeof (hd.magic));
memcpy (hd.uname, "grub", 4);
--
2.43.0

View File

@ -0,0 +1,58 @@
From b0f9dcabe96e5689ecfba9b6abcd27e685eabd48 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Wed, 11 May 2022 09:56:11 -0400
Subject: [PATCH] ofdisk: improve boot time by lookup boot disk first
While booting lvm, grub will try to build up logical volumes via hooks
to disk iteration where on-disk metadata can be read and parsed. However
the process can become very slow on multipath as reachable disks are
duplicated by multiple I/O paths and they all get inspected.
Fortunately grub allows lvm to be lazy binding and opportunistic that
root volume can be created when it's needed using a smaller set of
discovered disks. The disk iteration can also be controlled by pull
methods to only returning specified disks. That said we may be able to
take advantage of existing design to cause less overhead in lvm
construction.
This patch will return boot disks in OpenFirmware so they can be used
first. If lvm managed to create root volume out of those boot disks then
it is all very nice as they are readily available. Otherwise disk
scanning will be performed to present all discoverable disks to grub as
what it was done in the past. The result maybe again time consuming but
we have nothing to lose here.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/disk/ieee1275/ofdisk.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
--- a/grub-core/disk/ieee1275/ofdisk.c
+++ b/grub-core/disk/ieee1275/ofdisk.c
@@ -491,10 +491,11 @@
{
unsigned i;
- if (pull != GRUB_DISK_PULL_NONE)
+ if (pull > GRUB_DISK_PULL_REMOVABLE)
return 0;
- scan ();
+ if (pull == GRUB_DISK_PULL_REMOVABLE)
+ scan ();
for (i = 0; i < ARRAY_SIZE (ofdisk_hash); i++)
{
@@ -532,6 +533,12 @@
if (!ent->is_boot && ent->is_removable)
continue;
+ if (pull == GRUB_DISK_PULL_NONE && !ent->is_boot)
+ continue;
+
+ if (pull == GRUB_DISK_PULL_REMOVABLE && ent->is_boot)
+ continue;
+
if (hook (ent->grub_shortest, hook_data))
return 1;
}

View File

@ -0,0 +1,52 @@
From 468628bdc39800341e7aa6ff7795cc0d93cfaf3f Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Tue, 11 Apr 2023 10:59:34 +0800
Subject: [PATCH 1/2] openfw: Ensure get_devargs and get_devname functions are
consistent
Commit 165c9b234 changed the logic of ieee1275_get_devargs() to use the
first or second occurrence of a colon as a separator between device name
and arguments. However, this didn't align with the complementary
function ieee1275_get_devname, which uses the first occurrence of a
colon after the namespace keyword as arguments for the nvme-of device.
This commit addresses the inconsistency by ensuring that both functions
follow a common logic. Now, get_devargs and get_devname functions are
consistent with each other, making it easier to understand and maintain
the codebase.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/kern/ieee1275/openfw.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c
index e2ffec32d..3bbd07d95 100644
--- a/grub-core/kern/ieee1275/openfw.c
+++ b/grub-core/kern/ieee1275/openfw.c
@@ -354,13 +354,16 @@ static char *
grub_ieee1275_get_devargs (const char *path)
{
char *colon = grub_strchr (path, ':');
- char *colon_check = colon;
- /* Find the last occurence of colon */
- while(colon_check){
- colon = colon_check;
- colon_check = grub_strchr (colon+1, ':');
- }
+ /* Use the same logic in grub_ieee1275_get_devname for nvme-of arguments */
+ if (grub_strstr(path, "nvme-of"))
+ {
+ char *namespace_split = grub_strstr(path,"/namespace@");
+ if (namespace_split)
+ colon = grub_strchr (namespace_split, ':');
+ else
+ colon = NULL;
+ }
if (! colon)
return 0;
--
2.39.2

View File

@ -0,0 +1,177 @@
From 5affde982dea827580e36ccc658e439397f51ce8 Mon Sep 17 00:00:00 2001
From: Hernan Gatta <hegatta@linux.microsoft.com>
Date: Tue, 1 Feb 2022 05:02:53 -0800
Subject: [PATCH 1/5] protectors: Add key protectors framework
A key protector encapsulates functionality to retrieve an unlocking key
for a fully-encrypted disk from a specific source. A key protector
module registers itself with the key protectors framework when it is
loaded and unregisters when unloaded. Additionally, a key protector may
accept parameters that describe how it should operate.
The key protectors framework, besides offering registration and
unregistration functions, also offers a one-stop routine for finding and
invoking a key protector by name. If a key protector with the specified
name exists and if an unlocking key is successfully retrieved by it, the
function returns to the caller the retrieved key and its length.
Signed-off-by: Hernan Gatta <hegatta@linux.microsoft.com>
Signed-off-by: Gary Lin <glin@suse.com>
---
grub-core/Makefile.am | 1 +
grub-core/Makefile.core.def | 1 +
grub-core/kern/protectors.c | 75 +++++++++++++++++++++++++++++++++++++
include/grub/protector.h | 48 ++++++++++++++++++++++++
4 files changed, 125 insertions(+)
create mode 100644 grub-core/kern/protectors.c
create mode 100644 include/grub/protector.h
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -90,6 +90,7 @@
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/parser.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/protector.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/stack_protector.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -149,6 +149,7 @@
common = kern/misc.c;
common = kern/parser.c;
common = kern/partition.c;
+ common = kern/protectors.c;
common = kern/rescue_parser.c;
common = kern/rescue_reader.c;
common = kern/term.c;
--- /dev/null
+++ b/grub-core/kern/protectors.c
@@ -0,0 +1,75 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2022 Microsoft Corporation
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/list.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/protector.h>
+
+struct grub_key_protector *grub_key_protectors = NULL;
+
+grub_err_t
+grub_key_protector_register (struct grub_key_protector *protector)
+{
+ if (protector == NULL || protector->name == NULL || grub_strlen(protector->name) == 0)
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ if (grub_key_protectors &&
+ grub_named_list_find (GRUB_AS_NAMED_LIST (grub_key_protectors),
+ protector->name))
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ grub_list_push (GRUB_AS_LIST_P (&grub_key_protectors),
+ GRUB_AS_LIST (protector));
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_key_protector_unregister (struct grub_key_protector *protector)
+{
+ if (protector == NULL)
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ grub_list_remove (GRUB_AS_LIST (protector));
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_key_protector_recover_key (const char *protector, grub_uint8_t **key,
+ grub_size_t *key_size)
+{
+ struct grub_key_protector *kp = NULL;
+
+ if (grub_key_protectors == NULL)
+ return GRUB_ERR_OUT_OF_RANGE;
+
+ if (protector == NULL || grub_strlen (protector) == 0)
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ kp = grub_named_list_find (GRUB_AS_NAMED_LIST (grub_key_protectors),
+ protector);
+ if (kp == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
+ N_("A key protector with name '%s' could not be found. "
+ "Is the name spelled correctly and is the "
+ "corresponding module loaded?"), protector);
+
+ return kp->recover_key (key, key_size);
+}
--- /dev/null
+++ b/include/grub/protector.h
@@ -0,0 +1,48 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2022 Microsoft Corporation
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_PROTECTOR_HEADER
+#define GRUB_PROTECTOR_HEADER 1
+
+#include <grub/err.h>
+#include <grub/types.h>
+
+struct grub_key_protector
+{
+ struct grub_key_protector *next;
+ struct grub_key_protector **prev;
+
+ const char *name;
+
+ grub_err_t (*recover_key) (grub_uint8_t **key, grub_size_t *key_size);
+};
+
+extern struct grub_key_protector *EXPORT_VAR (grub_key_protectors);
+
+grub_err_t
+EXPORT_FUNC (grub_key_protector_register) (struct grub_key_protector *protector);
+
+grub_err_t
+EXPORT_FUNC (grub_key_protector_unregister) (struct grub_key_protector *protector);
+
+grub_err_t
+EXPORT_FUNC (grub_key_protector_recover_key) (const char *protector,
+ grub_uint8_t **key,
+ grub_size_t *key_size);
+
+#endif /* ! GRUB_PROTECTOR_HEADER */

View File

@ -0,0 +1,80 @@
From c3efb4ecbe91b63c127b92122dad3fa53d4efc69 Mon Sep 17 00:00:00 2001
From: Patrick Colp <patrick.colp@oracle.com>
Date: Mon, 31 Jul 2023 07:01:45 -0700
Subject: [PATCH 1/4] protectors: Implement NV index
Currently with the TPM2 protector, only SRK mode is supported and
NV index support is just a stub. Implement the NV index option.
Note: This only extends support on the unseal path. grub2_protect
has not been updated. tpm2-tools can be used to insert a key into
the NV index.
An example of inserting a key using tpm2-tools:
# Get random key.
tpm2_getrandom 32 > key.dat
# Create primary object.
tpm2_createprimary -C o -g sha256 -G rsa -c primary.ctx
# Create policy object. `pcrs.dat` contains the PCR values to seal against.
tpm2_startauthsession -S session.dat
tpm2_policypcr -S session.dat -l sha256:7,11 -f pcrs.dat -L policy.dat
tpm2_flushcontext session.dat
# Seal key into TPM.
cat key.dat | tpm2_create -C primary.ctx -u key.pub -r key.priv -L policy.dat -i-
tpm2_load -C primary.ctx -u key.pub -r key.priv -n sealing.name -c sealing.ctx
tpm2_evictcontrol -C o -c sealing.ctx 0x81000000
Then to unseal the key in grub, add this to grub.cfg:
tpm2_key_protector_init --mode=nv --nvindex=0x81000000 --pcrs=7,11
cryptomount -u <UUID> --protector tpm2
Signed-off-by: Patrick Colp <patrick.colp@oracle.com>
---
grub-core/tpm2/module.c | 25 ++++++++++++++++++++-----
1 file changed, 20 insertions(+), 5 deletions(-)
diff --git a/grub-core/tpm2/module.c b/grub-core/tpm2/module.c
index 5274296b7..d3a64187a 100644
--- a/grub-core/tpm2/module.c
+++ b/grub-core/tpm2/module.c
@@ -757,12 +757,27 @@ static grub_err_t
grub_tpm2_protector_nv_recover (const struct grub_tpm2_protector_context *ctx,
grub_uint8_t **key, grub_size_t *key_size)
{
- (void)ctx;
- (void)key;
- (void)key_size;
+ TPM_HANDLE sealed_handle = ctx->nv;
+ tpm2key_policy_t policy_seq = NULL;
+ grub_err_t err;
+
+ /* Create a basic policy sequence based on the given PCR selection */
+ err = grub_tpm2_protector_simple_policy_seq (ctx, &policy_seq);
+ if (err != GRUB_ERR_NONE)
+ goto exit;
+
+ err = grub_tpm2_protector_unseal (policy_seq, sealed_handle, key, key_size);
+
+ /* Pop error messages on success */
+ if (err == GRUB_ERR_NONE)
+ while (grub_error_pop ());
+
+exit:
+ TPM2_FlushContext (sealed_handle);
- return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
- N_("NV Index mode is not implemented yet"));
+ grub_tpm2key_free_policy_seq (policy_seq);
+
+ return err;
}
static grub_err_t
--
2.35.3

View File

@ -0,0 +1,40 @@
From 60d1d3b959e72c2cbd014be311c350a9b11b1289 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Tue, 7 Sep 2021 10:06:50 +0800
Subject: [PATCH] templates: Follow the path of usr merged kernel config
The background for usr merge can be found at:
https://www.freedesktop.org/wiki/Software/systemd/TheCaseForTheUsrMerge/
This patch adapts related mkconfig scripts to follow the usr merge for
looking up kernel configs.
Signed-off-by: Michael Chang <mchang@suse.com>
---
util/grub.d/10_linux.in | 2 +-
util/grub.d/20_linux_xen.in | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -351,7 +351,7 @@
fi
config=
- for i in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" ; do
+ for i in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" "/usr/lib/modules/${version}/config" ; do
if test -e "${i}" ; then
config="${i}"
break
--- a/util/grub.d/20_linux_xen.in
+++ b/util/grub.d/20_linux_xen.in
@@ -307,7 +307,7 @@
version=$(echo $basename | sed -e "s,^[^0-9]*-,,g")
dirname=$(dirname $i)
config=
- for j in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" ; do
+ for j in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" "/usr/lib/modules/${version}/config" ; do
if test -e "${j}" ; then
config="${j}"
break

View File

@ -0,0 +1,204 @@
From 5a417f32f1afe0ffca7f5cbff67145a157b1589b Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Tue, 7 Feb 2023 18:31:12 +0800
Subject: [PATCH 1/4] tpm2: Add TPM2 types, structures, and command constants
Add new TPM2 types and structures as the preparation to support
authorized policy.
* New types:
TPM_ALG_ECDAA, TPM_ALG_ECDSA, TPM_ALG_ECSCHNORR, TPM_ALG_RSASSA,
TPM_ALG_RSAPSS, TPM_ALG_SM2, and TPMI_ALG_SIG_SCHEME
* New structures:
TPMS_EMPTY, TPMS_SIGNATURE_RSA, TPMS_SIGNATURE_ECC,
TPMS_SIGNATURE_ECDSA, TPMS_SIGNATURE_ECDAA, TPMS_SIGNATURE_SM2,
TPMS_SIGNATURE_ECSCHNORR, TPMU_SIGNATURE, and TPMT_TK_VERIFIED
* New command constants:
TPM_CC_LoadExternal, TPM_CC_HashSequenceStart, TPM_CC_SequenceUpdate,
TPM_CC_SequenceComplete, TPM_CC_Hash, TPM_CC_VerifySignature,
TPM_CC_PolicyAuthorize
Signed-off-by: Gary Lin <glin@suse.com>
---
include/grub/tpm2/internal/structs.h | 86 ++++++++++++++++++++++++++++
include/grub/tpm2/internal/types.h | 42 +++++++++-----
2 files changed, 114 insertions(+), 14 deletions(-)
diff --git a/include/grub/tpm2/internal/structs.h b/include/grub/tpm2/internal/structs.h
index 72d71eb70..db9eb6cf6 100644
--- a/include/grub/tpm2/internal/structs.h
+++ b/include/grub/tpm2/internal/structs.h
@@ -672,4 +672,90 @@ struct TPMT_TK_CREATION
};
typedef struct TPMT_TK_CREATION TPMT_TK_CREATION;
+/* TPMS_EMPTY Structure */
+struct TPMS_EMPTY {
+ grub_uint8_t empty[1]; /* a structure with no member */
+};
+typedef struct TPMS_EMPTY TPMS_EMPTY;
+
+/* TPMS_SIGNATURE_RSA Structure */
+struct TPMS_SIGNATURE_RSA {
+ TPMI_ALG_HASH hash;
+ TPM2B_PUBLIC_KEY_RSA sig;
+};
+typedef struct TPMS_SIGNATURE_RSA TPMS_SIGNATURE_RSA;
+
+/* Definition of Types for RSA Signature */
+typedef TPMS_SIGNATURE_RSA TPMS_SIGNATURE_RSASSA;
+typedef TPMS_SIGNATURE_RSA TPMS_SIGNATURE_RSAPSS;
+
+/* TPMS_SIGNATURE_ECC Structure */
+struct TPMS_SIGNATURE_ECC {
+ TPMI_ALG_HASH hash;
+ TPM2B_ECC_PARAMETER signatureR;
+ TPM2B_ECC_PARAMETER signatureS;
+};
+typedef struct TPMS_SIGNATURE_ECC TPMS_SIGNATURE_ECC;
+
+/* Definition of Types for ECC TPMS_SIGNATURE_ECC */
+typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_ECDSA;
+typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_ECDAA;
+typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_SM2;
+typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_ECSCHNORR;
+
+/* TPMU_SIGNATURE Structure */
+union TPMU_SIGNATURE {
+ TPMS_SIGNATURE_RSASSA rsassa;
+ TPMS_SIGNATURE_RSAPSS rsapss;
+ TPMS_SIGNATURE_ECDSA ecdsa;
+ TPMS_SIGNATURE_ECDAA ecdaa;
+ TPMS_SIGNATURE_SM2 sm2;
+ TPMS_SIGNATURE_ECSCHNORR ecschnorr;
+ TPMT_HA hmac;
+ TPMS_SCHEME_HASH any;
+ TPMS_EMPTY null;
+};
+typedef union TPMU_SIGNATURE TPMU_SIGNATURE;
+
+/* TPMT_SIGNATURE Structure */
+struct TPMT_SIGNATURE {
+ TPMI_ALG_SIG_SCHEME sigAlg;
+ TPMU_SIGNATURE signature;
+};
+typedef struct TPMT_SIGNATURE TPMT_SIGNATURE;
+
+static inline TPMI_ALG_HASH
+TPMT_SIGNATURE_get_hash_alg (TPMT_SIGNATURE *sig)
+{
+ switch (sig->sigAlg)
+ {
+ case TPM_ALG_RSASSA:
+ return sig->signature.rsassa.hash;
+ case TPM_ALG_RSAPSS:
+ return sig->signature.rsapss.hash;
+ case TPM_ALG_ECDSA:
+ return sig->signature.ecdsa.hash;
+ case TPM_ALG_ECDAA:
+ return sig->signature.ecdaa.hash;
+ case TPM_ALG_SM2:
+ return sig->signature.sm2.hash;
+ case TPM_ALG_ECSCHNORR:
+ return sig->signature.ecschnorr.hash;
+ case TPM_ALG_HMAC:
+ return sig->signature.hmac.hashAlg;
+ default:
+ break;
+ }
+
+ return TPM_ALG_NULL;
+}
+
+/* TPMT_TK_VERIFIED Structure */
+struct TPMT_TK_VERIFIED {
+ TPM_ST tag;
+ TPMI_RH_HIERARCHY hierarchy;
+ TPM2B_DIGEST digest;
+};
+typedef struct TPMT_TK_VERIFIED TPMT_TK_VERIFIED;
+
#endif /* ! GRUB_TPM2_INTERNAL_STRUCTS_HEADER */
diff --git a/include/grub/tpm2/internal/types.h b/include/grub/tpm2/internal/types.h
index 9714f75d4..a1902ef0c 100644
--- a/include/grub/tpm2/internal/types.h
+++ b/include/grub/tpm2/internal/types.h
@@ -181,6 +181,9 @@ typedef grub_uint16_t TPM_ALG_ID;
#define TPM_ALG_CFB ((TPM_ALG_ID) 0x0043)
#define TPM_ALG_ECB ((TPM_ALG_ID) 0x0044)
#define TPM_ALG_ECC ((TPM_ALG_ID) 0x0023)
+#define TPM_ALG_ECDAA ((TPM_ALG_ID) 0x001A)
+#define TPM_ALG_ECDSA ((TPM_ALG_ID) 0x0018)
+#define TPM_ALG_ECSCHNORR ((TPM_ALG_ID) 0x001C)
#define TPM_ALG_HMAC ((TPM_ALG_ID) 0x0005)
#define TPM_ALG_KDF1_SP800_108 ((TPM_ALG_ID) 0x0022)
#define TPM_ALG_KDF1_SP800_56A ((TPM_ALG_ID) 0x0020)
@@ -189,10 +192,13 @@ typedef grub_uint16_t TPM_ALG_ID;
#define TPM_ALG_MGF1 ((TPM_ALG_ID) 0x0007)
#define TPM_ALG_NULL ((TPM_ALG_ID) 0x0010)
#define TPM_ALG_RSA ((TPM_ALG_ID) 0x0001)
+#define TPM_ALG_RSASSA ((TPM_ALG_ID) 0x0014)
+#define TPM_ALG_RSAPSS ((TPM_ALG_ID) 0x0016)
#define TPM_ALG_SHA1 ((TPM_ALG_ID) 0x0004)
#define TPM_ALG_SHA256 ((TPM_ALG_ID) 0x000B)
#define TPM_ALG_SHA384 ((TPM_ALG_ID) 0x000C)
#define TPM_ALG_SHA512 ((TPM_ALG_ID) 0x000D)
+#define TPM_ALG_SM2 ((TPM_ALG_ID) 0x001B)
#define TPM_ALG_SM3_256 ((TPM_ALG_ID) 0x0012)
#define TPM_ALG_SM4 ((TPM_ALG_ID) 0x0013)
#define TPM_ALG_SYMCIPHER ((TPM_ALG_ID) 0x0025)
@@ -299,20 +305,27 @@ typedef grub_uint16_t TPM2_ECC_CURVE;
/* TPM_CC Constants */
typedef grub_uint32_t TPM_CC;
-#define TPM_CC_EvictControl ((TPM_CC) 0x00000120)
-#define TPM_CC_CreatePrimary ((TPM_CC) 0x00000131)
-#define TPM_CC_Create ((TPM_CC) 0x00000153)
-#define TPM_CC_FlushContext ((TPM_CC) 0x00000165)
-#define TPM_CC_ReadPublic ((TPM_CC) 0x00000173)
-#define TPM_CC_StartAuthSession ((TPM_CC) 0x00000176)
-#define TPM_CC_PolicyPCR ((TPM_CC) 0x0000017f)
-#define TPM_CC_NV_Read ((TPM_CC) 0x0000014e)
-#define TPM_CC_NV_ReadPublic ((TPM_CC) 0x00000169)
-#define TPM_CC_GetCapability ((TPM_CC) 0x0000017a)
-#define TPM_CC_PCR_Read ((TPM_CC) 0x0000017e)
-#define TPM_CC_Load ((TPM_CC) 0x00000157)
-#define TPM_CC_Unseal ((TPM_CC) 0x0000015e)
-#define TPM_CC_PolicyGetDigest ((TPM_CC) 0x00000189)
+#define TPM_CC_EvictControl ((TPM_CC) 0x00000120)
+#define TPM_CC_CreatePrimary ((TPM_CC) 0x00000131)
+#define TPM_CC_Create ((TPM_CC) 0x00000153)
+#define TPM_CC_FlushContext ((TPM_CC) 0x00000165)
+#define TPM_CC_ReadPublic ((TPM_CC) 0x00000173)
+#define TPM_CC_StartAuthSession ((TPM_CC) 0x00000176)
+#define TPM_CC_PolicyPCR ((TPM_CC) 0x0000017f)
+#define TPM_CC_NV_Read ((TPM_CC) 0x0000014e)
+#define TPM_CC_NV_ReadPublic ((TPM_CC) 0x00000169)
+#define TPM_CC_GetCapability ((TPM_CC) 0x0000017a)
+#define TPM_CC_PCR_Read ((TPM_CC) 0x0000017e)
+#define TPM_CC_Load ((TPM_CC) 0x00000157)
+#define TPM_CC_LoadExternal ((TPM_CC) 0x00000167)
+#define TPM_CC_Unseal ((TPM_CC) 0x0000015e)
+#define TPM_CC_PolicyGetDigest ((TPM_CC) 0x00000189)
+#define TPM_CC_HashSequenceStart ((TPM_CC) 0x00000186)
+#define TPM_CC_SequenceUpdate ((TPM_CC) 0x0000015c)
+#define TPM_CC_SequenceComplete ((TPM_CC) 0x0000013e)
+#define TPM_CC_Hash ((TPM_CC) 0x0000017d)
+#define TPM_CC_VerifySignature ((TPM_CC) 0x00000177)
+#define TPM_CC_PolicyAuthorize ((TPM_CC) 0x0000016a)
/* Hash algorithm sizes */
#define TPM_SHA1_DIGEST_SIZE 20
@@ -354,6 +367,7 @@ typedef TPM_ALG_ID TPMI_ALG_ECC_SCHEME;
typedef TPM_ALG_ID TPMI_ALG_ASYM_SCHEME;
typedef TPM_ALG_ID TPMI_ALG_RSA_SCHEME;
typedef TPM_ALG_ID TPMI_ALG_SYM;
+typedef TPM_ALG_ID TPMI_ALG_SIG_SCHEME;
/* TPM_KEY_BITS Type */
typedef grub_uint16_t TPM_KEY_BITS;
--
2.35.3

View File

@ -0,0 +1,83 @@
From 6c06378c1bf6ae21788427e62ab0011b7f1bc2f0 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 25 Nov 2022 16:11:24 +0800
Subject: [PATCH] xen_boot: add missing grub_arch_efi_linux_load_image_header
The new xen_boot module has used grub_arch_efi_linux_load_image_header
exported by grub-core/loader/arm64/linux.c. It is not a problem for
upstream but many downstream projects may not use it and take
grub-core/loader/arm64/efi/linux.c as a replacement as PE entry is the
preferred way in combination with shim loader.
This patch did a trivial workaround just adding back the dropped
defintion to the xen_boot itself.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/loader/arm64/xen_boot.c | 50 +++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c
index 26e1472c9..b82a2db89 100644
--- a/grub-core/loader/arm64/xen_boot.c
+++ b/grub-core/loader/arm64/xen_boot.c
@@ -84,6 +84,56 @@ static int loaded;
static struct xen_boot_binary *xen_hypervisor;
static struct xen_boot_binary *module_head;
+/* The function is exported by grub-core/loader/arm64/linux.c that is not built
+ * because we use PE entry provided by grub-core/loader/arm64/efi/linux.c
+ */
+static bool initrd_use_loadfile2 = false;
+
+grub_err_t
+grub_arch_efi_linux_load_image_header (grub_file_t file,
+ struct linux_arch_kernel_header * lh)
+{
+ grub_file_seek (file, 0);
+ if (grub_file_read (file, lh, sizeof (*lh)) < (grub_ssize_t) sizeof (*lh))
+ return grub_error(GRUB_ERR_FILE_READ_ERROR, "failed to read Linux image header");
+
+ if ((lh->code0 & 0xffff) != GRUB_PE32_MAGIC)
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ N_("plain image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled"));
+
+ grub_dprintf ("linux", "UEFI stub kernel:\n");
+ grub_dprintf ("linux", "PE/COFF header @ %08x\n", lh->hdr_offset);
+
+ /*
+ * The PE/COFF spec permits the COFF header to appear anywhere in the file, so
+ * we need to double check whether it was where we expected it, and if not, we
+ * must load it from the correct offset into the pe_image_header field of
+ * struct linux_arch_kernel_header.
+ */
+ if ((grub_uint8_t *) lh + lh->hdr_offset != (grub_uint8_t *) &lh->pe_image_header)
+ {
+ if (grub_file_seek (file, lh->hdr_offset) == (grub_off_t) -1
+ || grub_file_read (file, &lh->pe_image_header,
+ sizeof (struct grub_pe_image_header))
+ != sizeof (struct grub_pe_image_header))
+ return grub_error (GRUB_ERR_FILE_READ_ERROR, "failed to read COFF image header");
+ }
+
+ /*
+ * Linux kernels built for any architecture are guaranteed to support the
+ * LoadFile2 based initrd loading protocol if the image version is >= 1.
+ */
+ if (lh->pe_image_header.optional_header.major_image_version >= 1)
+ initrd_use_loadfile2 = true;
+ else
+ initrd_use_loadfile2 = false;
+
+ grub_dprintf ("linux", "LoadFile2 initrd loading %sabled\n",
+ initrd_use_loadfile2 ? "en" : "dis");
+
+ return GRUB_ERR_NONE;
+}
+
static __inline grub_addr_t
xen_boot_address_align (grub_addr_t start, grub_size_t align)
{
--
2.41.0

View File

@ -0,0 +1,60 @@
From b5c3492f31a98f5ef0f9bec2c0665ad0b71ad5cb Mon Sep 17 00:00:00 2001
From: Sebastian Krahmer <krahmer@suse.com>
Date: Tue, 28 Nov 2017 17:24:38 +0800
Subject: [PATCH] AUDIT-0: http boot tracker bug
Fixing a memory leak in case of error, and a integer overflow, leading to a
heap overflow due to overly large chunk sizes.
We need to check against some maximum value, otherwise values like 0xffffffff
will eventually lead in the allocation functions to small sized buffers, since
the len is rounded up to the next reasonable alignment. The following memcpy
will then smash the heap, leading to RCE.
This is no big issue for pure http boot, since its going to execute an
untrusted kernel anyway, but it will break trusted boot scenarios, where only
signed code is allowed to be executed.
v2: Fix GCC 13 build failure (bsc#1201089)
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/net/efi/net.c | 4 +++-
grub-core/net/http.c | 5 ++++-
2 files changed, 7 insertions(+), 2 deletions(-)
--- a/grub-core/net/efi/net.c
+++ b/grub-core/net/efi/net.c
@@ -654,8 +654,10 @@
rd = efi_net_interface (read, file, chunk, sz);
- if (rd <= 0)
+ if (rd <= 0) {
+ grub_free (chunk);
return rd;
+ }
if (buf)
{
--- a/grub-core/net/http.c
+++ b/grub-core/net/http.c
@@ -31,7 +31,8 @@
enum
{
- HTTP_PORT = 80
+ HTTP_PORT = 80,
+ HTTP_MAX_CHUNK_SIZE = GRUB_INT_MAX
};
@@ -86,6 +87,8 @@
if (data->in_chunk_len == 2)
{
data->chunk_rem = grub_strtoul (ptr, 0, 16);
+ if (data->chunk_rem > HTTP_MAX_CHUNK_SIZE)
+ return GRUB_ERR_NET_PACKET_TOO_BIG;
grub_errno = GRUB_ERR_NONE;
if (data->chunk_rem == 0)
{

View File

@ -0,0 +1,53 @@
From c0d00403a297d6023eab6189ba87dc8a3f6d1e85 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 7 Feb 2022 20:44:40 +0800
Subject: [PATCH 2/5] Add grub_disk_write_tail helper function
This helps in writing data to partition where the end of buffer is
aligned to end of partition.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/lib/disk.c | 18 ++++++++++++++++++
include/grub/disk.h | 3 +++
2 files changed, 21 insertions(+)
--- a/grub-core/lib/disk.c
+++ b/grub-core/lib/disk.c
@@ -52,6 +52,24 @@
}
grub_err_t
+grub_disk_write_tail (grub_disk_t disk, grub_size_t size, const void *buf)
+{
+ grub_partition_t part;
+ grub_disk_addr_t sector;
+ grub_off_t offset;
+
+ if (!disk->partition)
+ return GRUB_ERR_NONE;
+
+ part = disk->partition;
+ sector = part->len;
+ sector -= (size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS;
+ offset = size & (GRUB_DISK_SECTOR_SIZE - 1);
+
+ return grub_disk_write (disk, sector, offset, size, buf);
+}
+
+grub_err_t
grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector,
grub_off_t offset, grub_size_t size, const void *buf)
{
--- a/include/grub/disk.h
+++ b/include/grub/disk.h
@@ -252,6 +252,9 @@
grub_off_t offset,
grub_size_t size,
void *buf);
+grub_err_t grub_disk_write_tail (grub_disk_t disk,
+ grub_size_t size,
+ const void *buf);
grub_err_t grub_disk_write (grub_disk_t disk,
grub_disk_addr_t sector,
grub_off_t offset,

View File

@ -0,0 +1,57 @@
From 337b3d963d28b3544e8817428fb68ca559613a39 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 9 Sep 2021 10:59:28 -0400
Subject: [PATCH 2/2] Arm: check for the PE magic for the compiled arch
In "arm64: Fix EFI loader kernel image allocation", Ben fixed the kernel
alignment to match the alignment given in the PE header. In doing so, a
check for valid PE magic was added, which was hard-coded to the value
seen on Aarch64 (GRUB_PE32_PE64_MAGIC).
Unfortunately, this code is shared between 64-bit and 32-bit, and so
that value broke 32-bit Arm systems.
This patch adds a constant definition for GRUB_PE32_PEXX_MAGIC, which is
either GRUB_PE32_PE64_MAGIC or GRUB_PE32_PE32_MAGIC, depending on which
platform is being built, and uses it in the header magic check.
Resolves: rhbz#2000756
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/loader/arm64/efi/linux.c | 2 +-
include/grub/arm/linux.h | 1 +
include/grub/arm64/linux.h | 1 +
3 files changed, 3 insertions(+), 1 deletion(-)
--- a/grub-core/loader/arm64/efi/linux.c
+++ b/grub-core/loader/arm64/efi/linux.c
@@ -376,7 +376,7 @@
pe = (void *)((unsigned long)kernel + lh->hdr_offset);
- if (pe->opt.magic != GRUB_PE32_PE64_MAGIC)
+ if (pe->opt.magic != GRUB_PE32_PEXX_MAGIC)
return grub_error(GRUB_ERR_BAD_OS, "Invalid PE optional header magic");
*total_size = pe->opt.image_size;
--- a/include/grub/arm/linux.h
+++ b/include/grub/arm/linux.h
@@ -33,6 +33,7 @@
};
#if defined(__arm__)
+# define GRUB_PE32_PEXX_MAGIC GRUB_PE32_PE32_MAGIC
# define grub_armxx_linux_pe_header grub_arm_linux_pe_header
#endif
--- a/include/grub/arm64/linux.h
+++ b/include/grub/arm64/linux.h
@@ -33,6 +33,7 @@
#if defined(__aarch64__)
# define GRUB_LINUX_ARMXX_MAGIC_SIGNATURE GRUB_LINUX_ARM64_MAGIC_SIGNATURE
+# define GRUB_PE32_PEXX_MAGIC GRUB_PE32_PE64_MAGIC
# define grub_armxx_linux_pe_header grub_arm64_linux_pe_header
#endif

View File

@ -0,0 +1,92 @@
From e72dcb40356f56efd86ab88c2f5cb7411d1e898b Mon Sep 17 00:00:00 2001
From: Matthew Garrett <mjg59@coreos.com>
Date: Tue, 14 Jul 2015 16:58:51 -0700
Subject: [PATCH 02/11] Fix race in EFI validation
---
grub-core/loader/i386/efi/linux.c | 40 +++++++------------------------
1 file changed, 9 insertions(+), 31 deletions(-)
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
index 06814cae3..1e09c88ab 100644
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -154,7 +154,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_file_t file = 0;
struct linux_i386_kernel_header lh;
grub_ssize_t len, start, filelen;
- void *kernel;
+ void *kernel = NULL;
grub_err_t err;
grub_dl_ref (my_mod);
@@ -185,10 +185,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
- grub_file_seek (file, 0);
-
- grub_free(kernel);
-
params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384));
if (! params)
@@ -199,13 +195,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_memset (params, 0, 16384);
- if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
- {
- if (!grub_errno)
- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
- argv[0]);
- goto fail;
- }
+ grub_memcpy (&lh, kernel, sizeof (lh));
if (lh.boot_flag != grub_cpu_to_le16 (0xaa55))
{
@@ -271,26 +261,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
- if (grub_file_seek (file, start) == (grub_off_t) -1)
- {
- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
- argv[0]);
- goto fail;
- }
-
- if (grub_file_read (file, kernel_mem, len) != len && !grub_errno)
- {
- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
- argv[0]);
- }
-
- if (grub_errno == GRUB_ERR_NONE)
- {
- grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
- loaded = 1;
- lh.code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem;
- }
+ grub_memcpy (kernel_mem, (char *)kernel + start, len);
+ grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
+ loaded=1;
+ lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem;
/* Grub linuxefi erroneously initialize linux's boot_params with non-zero values. (bsc#1025563)
From https://www.kernel.org/doc/Documentation/x86/boot.txt:
@@ -307,6 +282,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
if (file)
grub_file_close (file);
+ if (kernel)
+ grub_free (kernel);
+
if (grub_errno != GRUB_ERR_NONE)
{
grub_dl_unref (my_mod);
--
2.31.1

View File

@ -0,0 +1,57 @@
From f01314a822dbe9ad39b2f7d0f3717ef6e4c24f4a Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 15 Apr 2022 21:45:04 +0800
Subject: [PATCH 2/2] Mark environmet blocks as used for image embedding.
Now that grub will attempt to use full btrfs bootloader area, the
embedded image could have overlapped with environment blocks if it's
size grows too much. Let's define a dedicated area for environment
blocks to the used block mappings for the embedding process so it can be
skipped.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/fs/btrfs.c | 3 ++-
include/grub/fs.h | 2 ++
util/grub-editenv.c | 2 +-
3 files changed, 5 insertions(+), 2 deletions(-)
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -2637,7 +2637,7 @@
static const struct {
struct embed_region available;
- struct embed_region used[6];
+ struct embed_region used[7];
} btrfs_head = {
.available = {0, GRUB_DISK_KiB_TO_SECTORS (1024)}, /* The first 1 MiB. */
.used = {
@@ -2645,6 +2645,7 @@
{GRUB_DISK_KiB_TO_SECTORS (64) - 1, 1}, /* Overflow guard. */
{GRUB_DISK_KiB_TO_SECTORS (64), GRUB_DISK_KiB_TO_SECTORS (4)}, /* 4 KiB superblock. */
{GRUB_DISK_KiB_TO_SECTORS (68), 1}, /* Overflow guard. */
+ {GRUB_DISK_KiB_TO_SECTORS (ENV_BTRFS_OFFSET) - 1, 3}, /* Environment Block. */
{GRUB_DISK_KiB_TO_SECTORS (1024) - 1, 1}, /* Overflow guard. */
{0, 0} /* Array terminator. */
}
--- a/include/grub/fs.h
+++ b/include/grub/fs.h
@@ -128,4 +128,6 @@
grub_fs_t EXPORT_FUNC(grub_fs_probe) (grub_device_t device);
+#define ENV_BTRFS_OFFSET (256)
+
#endif /* ! GRUB_FS_HEADER */
--- a/util/grub-editenv.c
+++ b/util/grub-editenv.c
@@ -128,7 +128,7 @@
int offset;
int size;
} fs_envblk_spec[] = {
- { "btrfs", 256 * 1024, GRUB_DISK_SECTOR_SIZE },
+ { "btrfs", ENV_BTRFS_OFFSET * 1024, GRUB_DISK_SECTOR_SIZE },
{ NULL, 0, 0 }
};

View File

@ -0,0 +1,59 @@
From 9f18541245858f53fea72d8d60304f9015d88b5f Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 17 Mar 2023 22:00:23 +0800
Subject: [PATCH 2/2] Restrict cryptsetup key file permission for better
security
GRUB's default permission 777 for concatenated initrd files was too
permissive for the cryptsetup key file, causing a complaint from
systemd-cryptsetup during boot. This commit replaces the 0777 permission
with a more secure 0400 permission for the key file.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/loader/linux.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--- a/grub-core/loader/linux.c
+++ b/grub-core/loader/linux.c
@@ -32,6 +32,7 @@
char *buf;
char *newc_name;
grub_off_t size;
+ grub_uint32_t mode;
};
struct dir
@@ -203,6 +204,7 @@
grub_memcpy (comp->buf, buf, bufsz);
initrd_ctx->nfiles++;
comp->size = bufsz;
+ comp->mode = 0100400;
if (grub_add (initrd_ctx->size, comp->size,
&initrd_ctx->size))
goto overflow;
@@ -272,6 +274,7 @@
grub_initrd_close (initrd_ctx);
return grub_errno;
}
+ initrd_ctx->components[i].mode = 0100777;
name_len = grub_strlen (initrd_ctx->components[i].newc_name) + 1;
if (grub_add (initrd_ctx->size,
ALIGN_UP (sizeof (struct newc_head) + name_len, 4),
@@ -374,6 +377,7 @@
if (initrd_ctx->components[i].newc_name)
{
grub_size_t dir_size;
+ grub_uint32_t mode = initrd_ctx->components[i].mode;
if (insert_dir (initrd_ctx->components[i].newc_name, &root, ptr,
&dir_size))
@@ -385,7 +389,7 @@
ptr += dir_size;
ptr = make_header (ptr, initrd_ctx->components[i].newc_name,
grub_strlen (initrd_ctx->components[i].newc_name) + 1,
- 0100777,
+ mode,
initrd_ctx->components[i].size);
newc = 1;
}

View File

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

View File

@ -0,0 +1,40 @@
From e27acddebd30175587155613042abffd2e9a5de8 Mon Sep 17 00:00:00 2001
From: Mark Salter <msalter@redhat.com>
Date: Mon, 17 Apr 2017 08:44:29 -0400
Subject: [PATCH 2/9] arm64: make sure fdt has #address-cells and #size-cells
properties
Recent upstream changes to kexec-tools relies on #address-cells
and #size-cells properties in the FDT. If grub2 needs to create
a chosen node, it is likely because firmware did not provide one.
In that case, set #address-cells and #size-cells properties to
make sure they exist.
---
grub-core/loader/arm64/efi/linux.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
--- a/grub-core/loader/arm64/efi/linux.c
+++ b/grub-core/loader/arm64/efi/linux.c
@@ -99,7 +99,21 @@
node = grub_fdt_find_subnode (fdt, 0, "chosen");
if (node < 0)
- node = grub_fdt_add_subnode (fdt, 0, "chosen");
+ {
+ /*
+ * If we have to create a chosen node, Make sure we
+ * have #address-cells and #size-cells properties.
+ */
+ retval = grub_fdt_set_prop32(fdt, 0, "#address-cells", 2);
+ if (retval)
+ goto failure;
+
+ retval = grub_fdt_set_prop32(fdt, 0, "#size-cells", 2);
+ if (retval)
+ goto failure;
+
+ node = grub_fdt_add_subnode (fdt, 0, "chosen");
+ }
if (node < 1)
goto failure;

View File

@ -0,0 +1,47 @@
From 42cb0ebbffd660608612f9e32150a6596c6933c4 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 17 Aug 2020 17:25:56 +0800
Subject: [PATCH 2/2] cmdline: Provide cmdline functions as module
The command line processing is needed by many loader modules, hence we should
make it a sharable one rather than belonging to linux loader. This can cut the
dependency to linux module among multiple loaders like multiboot linuxefi and
so on to make custom boot image much more flexible to compose.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/Makefile.core.def | 6 +++++-
grub-core/lib/cmdline.c | 3 +++
2 files changed, 8 insertions(+), 1 deletion(-)
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1860,7 +1860,6 @@
x86_64_efi = loader/efi/linux.c;
emu = loader/emu/linux.c;
common = loader/linux.c;
- common = lib/cmdline.c;
};
module = {
@@ -2611,3 +2610,8 @@
efi = commands/bli.c;
enable = efi;
};
+
+module = {
+ name = cmdline;
+ common = lib/cmdline.c;
+};
--- a/grub-core/lib/cmdline.c
+++ b/grub-core/lib/cmdline.c
@@ -19,6 +19,9 @@
#include <grub/lib/cmdline.h>
#include <grub/misc.h>
+#include <grub/dl.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
static unsigned int check_arg (char *c, int *has_space)
{

View File

@ -0,0 +1,41 @@
From 7cc578baf26986c2badce998125b429a2aeb4d33 Mon Sep 17 00:00:00 2001
From: Patrick Colp <patrick.colp@oracle.com>
Date: Sun, 30 Jul 2023 12:58:18 -0700
Subject: [PATCH 2/4] cryptodisk: Fallback to passphrase
If a protector is specified, but it fails to unlock the disk, fall back
to asking for the passphrase. However, an error was set indicating that
the protector(s) failed. Later code (e.g., LUKS code) fails as
`grub_errno` is now set. Print the existing errors out first, before
proceeding with the passphrase.
Signed-off-by: Patrick Colp <patrick.colp@oracle.com>
---
grub-core/disk/cryptodisk.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 6620fca00..cf37a0934 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -1191,11 +1191,16 @@ grub_cryptodisk_scan_device_real (const char *name,
source->name, source->partition != NULL ? "," : "",
part != NULL ? part : N_("UNKNOWN"), dev->uuid);
grub_free (part);
- goto error;
}
if (!cargs->key_len)
{
+ if (grub_errno)
+ {
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+ }
+
/* Get the passphrase from the user, if no key data. */
askpass = 1;
part = grub_partition_get_name (source->partition);
--
2.35.3

View File

@ -0,0 +1,88 @@
From 2271da7522d8406c528d2a9079d810e140f8041a Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 3 Feb 2023 19:40:31 +0800
Subject: [PATCH 2/2] discard cached key before entering grub shell and editor
mode
The cached key is cleared in case of anyone poking around it by means of
the interactive shell offerings.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/commands/crypttab.c | 16 ++++++++++++++++
grub-core/normal/main.c | 2 ++
grub-core/normal/menu_entry.c | 3 +++
include/grub/crypttab.h | 2 ++
4 files changed, 23 insertions(+)
--- a/grub-core/commands/crypttab.c
+++ b/grub-core/commands/crypttab.c
@@ -53,6 +53,22 @@
return GRUB_ERR_NONE;
}
+void
+grub_initrd_discard_key (void)
+{
+ struct grub_key_publisher *cur, *nxt;
+
+ FOR_LIST_ELEMENTS_SAFE (cur, nxt, kpuber)
+ {
+ grub_list_remove (GRUB_AS_LIST (cur));
+ grub_memset (cur->key, 0, cur->key_len);
+ grub_free (cur->name);
+ grub_free (cur->path);
+ grub_free (cur->key);
+ grub_free (cur);
+ }
+}
+
static grub_err_t
grub_cmd_crypttab_entry (grub_command_t cmd __attribute__ ((unused)),
int argc, char **argv)
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -37,6 +37,7 @@
#ifdef GRUB_MACHINE_IEEE1275
#include <grub/ieee1275/ieee1275.h>
#endif
+#include <grub/crypttab.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -478,6 +479,7 @@
return;
}
+ grub_initrd_discard_key ();
grub_normal_reader_init (nested);
while (1)
--- a/grub-core/normal/menu_entry.c
+++ b/grub-core/normal/menu_entry.c
@@ -28,6 +28,7 @@
#include <grub/i18n.h>
#include <grub/charset.h>
#include <grub/safemath.h>
+#include <grub/crypttab.h>
enum update_mode
{
@@ -1262,6 +1263,8 @@
return;
}
+ grub_initrd_discard_key();
+
screen = make_screen (entry);
if (! screen)
return;
--- a/include/grub/crypttab.h
+++ b/include/grub/crypttab.h
@@ -19,4 +19,6 @@
grub_err_t
grub_initrd_publish_key (const char *uuid, const char *key, grub_size_t key_len, const char *path);
+void
+grub_initrd_discard_key (void);
#endif /* ! GRUB_CRYPTTAB_HEADER */

View File

@ -0,0 +1,58 @@
From 0ed2458cc4eff6d9a9199527e2a0b6d445802f94 Mon Sep 17 00:00:00 2001
From: Maxim Suhanov <dfirblog@gmail.com>
Date: Mon, 28 Aug 2023 16:32:33 +0300
Subject: [PATCH 2/6] fs/ntfs: Fix an OOB read when reading data from the
resident $DATA attribute
When reading a file containing resident data, i.e., the file data is stored in
the $DATA attribute within the NTFS file record, not in external clusters,
there are no checks that this resident data actually fits the corresponding
file record segment.
When parsing a specially-crafted file system image, the current NTFS code will
read the file data from an arbitrary, attacker-chosen memory offset and of
arbitrary, attacker-chosen length.
This allows an attacker to display arbitrary chunks of memory, which could
contain sensitive information like password hashes or even plain-text,
obfuscated passwords from BS EFI variables.
This fix implements a check to ensure that resident data is read from the
corresponding file record segment only.
Fixes: CVE-2023-4693
Reported-by: Maxim Suhanov <dfirblog@gmail.com>
Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/ntfs.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
index c3c4db117..a68e173d8 100644
--- a/grub-core/fs/ntfs.c
+++ b/grub-core/fs/ntfs.c
@@ -401,7 +401,18 @@ read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, grub_uint8_t *dest,
{
if (ofs + len > u32at (pa, 0x10))
return grub_error (GRUB_ERR_BAD_FS, "read out of range");
- grub_memcpy (dest, pa + u32at (pa, 0x14) + ofs, len);
+
+ if (u32at (pa, 0x10) > (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
+ return grub_error (GRUB_ERR_BAD_FS, "resident attribute too large");
+
+ if (pa >= at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
+ return grub_error (GRUB_ERR_BAD_FS, "resident attribute out of range");
+
+ if (u16at (pa, 0x14) + u32at (pa, 0x10) >
+ (grub_addr_t) at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR) - (grub_addr_t) pa)
+ return grub_error (GRUB_ERR_BAD_FS, "resident attribute out of range");
+
+ grub_memcpy (dest, pa + u16at (pa, 0x14) + ofs, len);
return 0;
}
--
2.42.0

View File

@ -0,0 +1,171 @@
From 4a6a5c4a6bb2426235364be9f3698763ddcf4775 Mon Sep 17 00:00:00 2001
From: Jon DeVree <nuxi@vault24.org>
Date: Tue, 17 Oct 2023 23:03:47 -0400
Subject: [PATCH 2/3] fs/xfs: Fix XFS directory extent parsing
The XFS directory entry parsing code has never been completely correct
for extent based directories. The parser correctly handles the case
where the directory is contained in a single extent, but then mistakenly
assumes the data blocks for the multiple extent case are each identical
to the single extent case. The difference in the format of the data
blocks between the two cases is tiny enough that its gone unnoticed for
a very long time.
A recent change introduced some additional bounds checking into the XFS
parser. Like GRUB's existing parser, it is correct for the single extent
case but incorrect for the multiple extent case. When parsing a directory
with multiple extents, this new bounds checking is sometimes (but not
always) tripped and triggers an "invalid XFS directory entry" error. This
probably would have continued to go unnoticed but the /boot/grub/<arch>
directory is large enough that it often has multiple extents.
The difference between the two cases is that when there are multiple
extents, the data blocks do not contain a trailer nor do they contain
any leaf information. That information is stored in a separate set of
extents dedicated to just the leaf information. These extents come after
the directory entry extents and are not included in the inode size. So
the existing parser already ignores the leaf extents.
The only reason to read the trailer/leaf information at all is so that
the parser can avoid misinterpreting that data as directory entries. So
this updates the parser as follows:
For the single extent case the parser doesn't change much:
1. Read the size of the leaf information from the trailer
2. Set the end pointer for the parser to the start of the leaf
information. (The previous bounds checking set the end pointer to the
start of the trailer, so this is actually a small improvement.)
3. Set the entries variable to the expected number of directory entries.
For the multiple extent case:
1. Set the end pointer to the end of the block.
2. Do not set up the entries variable. Figuring out how many entries are
in each individual block is complex and does not seem worth it when
it appears to be safe to just iterate over the entire block.
The bounds check itself was also dependent upon the faulty XFS parser
because it accidentally used "filename + length - 1". Presumably this
was able to pass the fuzzer because in the old parser there was always
8 bytes of slack space between the tail pointer and the actual end of
the block. Since this is no longer the case the bounds check needs to be
updated to "filename + length + 1" in order to prevent a regression in
the handling of corrupt fliesystems.
Notes:
* When there is only one extent there will only ever be one block. If
more than one block is required then XFS will always switch to holding
leaf information in a separate extent.
* B-tree based directories seems to be parsed properly by the same code
that handles multiple extents. This is unlikely to ever occur within
/boot though because its only used when there are an extremely large
number of directory entries.
Fixes: ef7850c75 (fs/xfs: Fix issues found while fuzzing the XFS filesystem)
Fixes: b2499b29c (Adds support for the XFS filesystem.)
Fixes: https://savannah.gnu.org/bugs/?64376
Signed-off-by: Jon DeVree <nuxi@vault24.org>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Tested-by: Marta Lewandowska <mlewando@redhat.com>
---
grub-core/fs/xfs.c | 52 +++++++++++++++++++++++++++++++++-------------
1 file changed, 38 insertions(+), 14 deletions(-)
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
index ebf962793..18edfcff4 100644
--- a/grub-core/fs/xfs.c
+++ b/grub-core/fs/xfs.c
@@ -223,6 +223,12 @@ struct grub_xfs_inode
/* Size of struct grub_xfs_inode v2, up to unused4 member included. */
#define XFS_V2_INODE_SIZE (XFS_V3_INODE_SIZE - 76)
+struct grub_xfs_dir_leaf_entry
+{
+ grub_uint32_t hashval;
+ grub_uint32_t address;
+} GRUB_PACKED;
+
struct grub_xfs_dirblock_tail
{
grub_uint32_t leaf_count;
@@ -874,9 +880,8 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
{
struct grub_xfs_dir2_entry *direntry =
grub_xfs_first_de(dir->data, dirblock);
- int entries;
- struct grub_xfs_dirblock_tail *tail =
- grub_xfs_dir_tail(dir->data, dirblock);
+ int entries = -1;
+ char *end = dirblock + dirblk_size;
numread = grub_xfs_read_file (dir, 0, 0,
blk << dirblk_log2,
@@ -887,14 +892,27 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
return 0;
}
- entries = (grub_be_to_cpu32 (tail->leaf_count)
- - grub_be_to_cpu32 (tail->leaf_stale));
+ /*
+ * Leaf and tail information are only in the data block if the number
+ * of extents is 1.
+ */
+ if (dir->inode.nextents == grub_cpu_to_be32_compile_time (1))
+ {
+ struct grub_xfs_dirblock_tail *tail = grub_xfs_dir_tail (dir->data, dirblock);
+
+ end = (char *) tail;
+
+ /* Subtract the space used by leaf nodes. */
+ end -= grub_be_to_cpu32 (tail->leaf_count) * sizeof (struct grub_xfs_dir_leaf_entry);
- if (!entries)
- continue;
+ entries = grub_be_to_cpu32 (tail->leaf_count) - grub_be_to_cpu32 (tail->leaf_stale);
+
+ if (!entries)
+ continue;
+ }
/* Iterate over all entries within this block. */
- while ((char *)direntry < (char *)tail)
+ while ((char *) direntry < (char *) end)
{
grub_uint8_t *freetag;
char *filename;
@@ -914,7 +932,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
}
filename = (char *)(direntry + 1);
- if (filename + direntry->len - 1 > (char *) tail)
+ if (filename + direntry->len + 1 > (char *) end)
return grub_error (GRUB_ERR_BAD_FS, "invalid XFS directory entry");
/* The byte after the filename is for the filetype, padding, or
@@ -928,11 +946,17 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
return 1;
}
- /* Check if last direntry in this block is
- reached. */
- entries--;
- if (!entries)
- break;
+ /*
+ * The expected number of directory entries is only tracked for the
+ * single extent case.
+ */
+ if (dir->inode.nextents == grub_cpu_to_be32_compile_time (1))
+ {
+ /* Check if last direntry in this block is reached. */
+ entries--;
+ if (!entries)
+ break;
+ }
/* Select the next directory entry. */
direntry = grub_xfs_next_de(dir->data, direntry);
--
2.42.1

View File

@ -0,0 +1,373 @@
From 9e61624db77e5073961126457f599bc70e877fd1 Mon Sep 17 00:00:00 2001
From: Diego Domingos <diegodo@br.ibm.com>
Date: Tue, 15 Mar 2022 15:59:41 -0400
Subject: [PATCH 2/4] ieee1275/ofpath: enable NVMeoF logical device translation
This patch add code to enable the translation of logical devices to the of NVMeoFC paths.
---
grub-core/osdep/linux/ofpath.c | 260 +++++++++++++++++++++++++++++++--
include/grub/util/ofpath.h | 29 ++++
2 files changed, 280 insertions(+), 9 deletions(-)
diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
index 89beceef4..212782d3f 100644
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -137,7 +137,7 @@ trim_newline (char *path)
*end-- = '\0';
}
-#define MAX_DISK_CAT 64
+#define MAX_DISK_CAT 512
static char *
find_obppath (const char *sysfs_path_orig)
@@ -313,6 +313,69 @@ get_basename(char *p)
return ret;
}
+
+void
+add_filename_to_pile(char *filename, struct ofpath_files_list_root* root){
+ struct ofpath_files_list_node* file;
+
+ file = malloc(sizeof(struct ofpath_files_list_node));
+
+ file->filename = filename;
+
+ if(root->first == NULL){
+ root->items = 1;
+ root->first = file;
+ file->next = NULL;
+ } else {
+ root->items++;
+ file->next = root->first;
+ root->first = file;
+ }
+}
+
+
+void
+find_file(char* filename, char* directory, struct ofpath_files_list_root* root, int max_depth, int depth){
+ struct dirent *ep;
+ struct stat statbuf;
+ DIR *dp;
+
+ if(depth > max_depth){
+ return;
+ }
+
+ if((dp = opendir(directory)) == NULL){
+
+ return;
+ }
+
+ while((ep = readdir(dp)) != NULL){
+
+ char* full_path = malloc(1024*sizeof(char));
+ snprintf(full_path,1024,"%s/%s",directory,ep->d_name);
+
+ lstat(full_path,&statbuf);
+
+ if(S_ISLNK(statbuf.st_mode)){
+
+ continue;
+ }
+
+ if(!strcmp(ep->d_name,".") || !strcmp(ep->d_name,"..")){
+ continue;
+ }
+
+ if(!strcmp(ep->d_name,filename)){
+ add_filename_to_pile(full_path, root);
+ }
+
+ find_file(filename, full_path, root, max_depth, depth+1);
+
+ }
+ closedir(dp);
+}
+
+
static char *
of_path_of_vdisk(const char *sys_devname __attribute__((unused)),
const char *device,
@@ -351,7 +414,142 @@ of_path_of_ide(const char *sys_devname __attribute__((unused)), const char *devi
return ret;
}
-#ifdef __sparc__
+char*
+of_find_fc_host(char* host_wwpn){
+
+ FILE* fp;
+ char *buf;
+ char portname_filename[sizeof("port_name")] = "port_name";
+ char devices_path[sizeof("/sys/devices")] = "/sys/devices";
+
+ struct ofpath_files_list_root* portnames_file_list;
+
+ portnames_file_list=malloc(sizeof(portnames_file_list));
+ portnames_file_list->items=0;
+ portnames_file_list->first=NULL;
+
+ find_file(portname_filename, devices_path, portnames_file_list, 10, 0);
+
+ struct ofpath_files_list_node* node = portnames_file_list->first;
+ while(node != NULL){
+ fp = fopen(node->filename,"r");
+ buf = malloc(sizeof(char)*512);
+ fscanf(fp, "%s", buf);
+ fclose(fp);
+ if((strcmp(buf,host_wwpn) == 0) && grub_strstr(node->filename, "fc_host")){
+ return node->filename;
+ }
+ node = node->next;
+ }
+
+ return NULL;
+}
+
+void
+of_path_get_nvmeof_adapter_info(char* sysfs_path,
+ struct ofpath_nvmeof_info* nvmeof_info){
+
+ FILE *fp;
+ char *buf, *buf2, *buf3;
+
+ nvmeof_info->host_wwpn = malloc(sizeof(char)*256);
+ nvmeof_info->target_wwpn = malloc(sizeof(char)*256);
+ nvmeof_info->nqn = malloc(sizeof(char)*256);
+
+ buf = malloc(sizeof(char)*512);
+ snprintf(buf,512,"%s/subsysnqn",sysfs_path);
+ fp = fopen(buf,"r");
+ fscanf(fp, "%s", nvmeof_info->nqn);
+ fclose(fp);
+
+ snprintf(buf,512,"%s/cntlid",sysfs_path);
+ fp = fopen(buf,"r");
+ fscanf(fp, "%u", &(nvmeof_info->cntlid));
+ fclose(fp);
+
+ //snprintf(buf,512,"%s/nsid",sysfs_path);
+ //fp = fopen(buf,"r");
+ //fscanf(fp, "%u", &(nvmeof_info->nsid));
+ //fclose(fp);
+
+ snprintf(buf,512,"%s/address",sysfs_path);
+ fp = fopen(buf,"r");
+ buf2 = malloc(sizeof(char)*512);
+ fscanf(fp, "%s", buf2);
+ fclose(fp);
+
+ nvmeof_info->host_wwpn = strrchr(buf2,'-')+1;
+
+ buf3=strchr(buf2,'-')+1;
+ buf3=strchr(buf3,'-')+1;
+ nvmeof_info->target_wwpn = buf3;
+ buf3 = strchr(nvmeof_info->target_wwpn,',');
+ *buf3 = '\0';
+
+
+ free(buf);
+
+ return;
+}
+
+#define MAX_NVME_NSID_DIGITS 6
+
+static char *
+of_path_get_nvme_controller_name_node(const char* devname)
+{
+ char *controller_node, *end;
+
+ controller_node = strdup(devname);
+
+ end = grub_strchr(controller_node+1, 'n');
+
+ if(end != NULL){
+ *end = '\0';
+ }
+
+ return controller_node;
+}
+
+unsigned int
+of_path_get_nvme_nsid(const char* devname)
+{
+ unsigned int nsid;
+ char *sysfs_path, *buf;
+ FILE *fp;
+
+ buf=malloc(sizeof(char)*512);
+
+ sysfs_path = block_device_get_sysfs_path_and_link (devname);
+
+ snprintf(buf,512,"%s/%s/nsid",sysfs_path,devname);
+ fp = fopen(buf,"r");
+ fscanf(fp, "%u", &(nsid));
+ fclose(fp);
+
+ free(sysfs_path);
+ free(buf);
+
+ return nsid;
+
+}
+
+static char *
+nvme_get_syspath(const char *nvmedev)
+{
+ char *sysfs_path, *controller_node;
+ sysfs_path = block_device_get_sysfs_path_and_link (nvmedev);
+
+ if(strstr(sysfs_path,"nvme-subsystem")){
+ controller_node = of_path_get_nvme_controller_name_node(nvmedev);
+ strcat(sysfs_path,"/");
+ strcat(sysfs_path,controller_node);
+ sysfs_path = xrealpath(sysfs_path);
+ }
+
+ return sysfs_path;
+}
+
+
static char *
of_path_of_nvme(const char *sys_devname __attribute__((unused)),
const char *device,
@@ -360,6 +558,7 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
{
char *sysfs_path, *of_path, disk[MAX_DISK_CAT];
const char *digit_string, *part_end;
+ int chars_written;
digit_string = trailing_digits (device);
part_end = devicenode + strlen (devicenode) - 1;
@@ -379,15 +578,61 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
/* Remove the p. */
*end = '\0';
sscanf (digit_string, "%d", &part);
- snprintf (disk, sizeof (disk), "/disk@1:%c", 'a' + (part - 1));
- sysfs_path = block_device_get_sysfs_path_and_link (nvmedev);
+
+ sysfs_path = nvme_get_syspath(nvmedev);
+
+ /* If is a NVMeoF */
+ if(strstr(sysfs_path,"nvme-fabrics")){
+ struct ofpath_nvmeof_info* nvmeof_info;
+ nvmeof_info = malloc(sizeof(nvmeof_info));
+
+ of_path_get_nvmeof_adapter_info(sysfs_path, nvmeof_info);
+
+ sysfs_path = of_find_fc_host(nvmeof_info->host_wwpn);
+
+ chars_written = snprintf(disk,sizeof(disk),"/nvme-of/controller@%s,%x:nqn=%s",
+ nvmeof_info->target_wwpn,
+ 0xffff,
+ nvmeof_info->nqn);
+
+ unsigned int nsid = of_path_get_nvme_nsid(nvmedev);
+
+ if(nsid){
+ snprintf(disk+chars_written,sizeof(disk) - chars_written,
+ "/namespace@%x:%d",nsid, part);
+ }
+
+ } else {
+ snprintf (disk, sizeof (disk), "/disk@1:%c", 'a' + (part - 1));
+ }
free (nvmedev);
}
else
{
/* We do not have the parition. */
- snprintf (disk, sizeof (disk), "/disk@1");
- sysfs_path = block_device_get_sysfs_path_and_link (device);
+ sysfs_path = nvme_get_syspath (device);
+ if(strstr(sysfs_path,"nvme-fabrics")){
+ struct ofpath_nvmeof_info* nvmeof_info;
+ nvmeof_info = malloc(sizeof(nvmeof_info));
+
+ of_path_get_nvmeof_adapter_info(sysfs_path, nvmeof_info);
+
+ sysfs_path = of_find_fc_host(nvmeof_info->host_wwpn);
+
+ chars_written = snprintf(disk,sizeof(disk),"/nvme-of/controller@%s,%x:nqn=%s",
+ nvmeof_info->target_wwpn,
+ 0xffff,
+ nvmeof_info->nqn);
+
+ unsigned int nsid = of_path_get_nvme_nsid(device);
+ if(nsid){
+ snprintf(disk+chars_written,sizeof(disk) - chars_written,
+ "/namespace@%x",nsid);
+ }
+ } else {
+ snprintf (disk, sizeof (disk), "/disk@1");
+ }
+
}
of_path = find_obppath (sysfs_path);
@@ -398,7 +643,6 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
free (sysfs_path);
return of_path;
}
-#endif
static void
of_fc_port_name(const char *path, const char *subpath, char *port_name)
@@ -840,11 +1084,9 @@ grub_util_devname_to_ofpath (const char *sys_devname)
/* All the models I've seen have a devalias "floppy".
New models have no floppy at all. */
ofpath = xstrdup ("floppy");
-#ifdef __sparc__
else if (device[0] == 'n' && device[1] == 'v' && device[2] == 'm'
&& device[3] == 'e')
ofpath = of_path_of_nvme (name_buf, device, devnode, devicenode);
-#endif
else
{
grub_util_warn (_("unknown device type %s"), device);
diff --git a/include/grub/util/ofpath.h b/include/grub/util/ofpath.h
index b43c523cb..a0ec30620 100644
--- a/include/grub/util/ofpath.h
+++ b/include/grub/util/ofpath.h
@@ -3,4 +3,33 @@
char *grub_util_devname_to_ofpath (const char *devname);
+struct ofpath_files_list_node {
+ char* filename;
+ struct ofpath_files_list_node* next;
+};
+
+struct ofpath_files_list_root {
+ int items;
+ struct ofpath_files_list_node* first;
+};
+
+struct ofpath_nvmeof_info {
+ char* host_wwpn;
+ char* target_wwpn;
+ char* nqn;
+ int cntlid;
+ int nsid;
+};
+
+void of_path_get_nvmeof_adapter_info(char* sysfs_path,
+ struct ofpath_nvmeof_info* nvmeof_info);
+
+unsigned int of_path_get_nvme_nsid(const char* devname);
+
+void add_filename_to_pile(char *filename, struct ofpath_files_list_root* root);
+
+void find_file(char* filename, char* directory, struct ofpath_files_list_root* root, int max_depth, int depth);
+
+char* of_find_fc_host(char* host_wwpn);
+
#endif /* ! GRUB_OFPATH_MACHINE_UTIL_HEADER */
--
2.35.3

View File

@ -0,0 +1,107 @@
From 8b31ebfa42eb5af0633191d26fcdcea8c539e521 Mon Sep 17 00:00:00 2001
From: Diego Domingos <diegodo@br.ibm.com>
Date: Wed, 24 Jun 2020 08:22:50 -0400
Subject: [PATCH 2/2] ieee1275/powerpc: enables device mapper discovery
this patch enables the device mapper discovery on ofpath.c. Currently,
when we are dealing with a device like /dev/dm-* the ofpath returns null
since there is no function implemented to handle this case.
This patch implements a function that will look into /sys/block/dm-*
devices and search recursively inside slaves directory to find the root
disk.
v2:
Fix gcc-12 error: pointer 'device_path' may be used after 'free'
[-Werror=use-after-free]
---
grub-core/osdep/linux/ofpath.c | 64 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 63 insertions(+), 1 deletion(-)
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -37,6 +37,7 @@
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>
+#include <dirent.h>
#ifdef __sparc__
typedef enum
@@ -754,13 +755,74 @@
return new;
}
+static char *
+get_slave_from_dm(const char * device){
+ char *curr_device, *tmp;
+ char *directory;
+ char *ret = NULL;
+
+ directory = grub_strdup (device);
+ tmp = get_basename(directory);
+ curr_device = grub_strdup (tmp);
+ *tmp = '\0';
+
+ /* Recursively check for slaves devices so we can find the root device */
+ while ((curr_device[0] == 'd') && (curr_device[1] == 'm') && (curr_device[2] == '-')){
+ DIR *dp;
+ struct dirent *ep;
+ char* device_path;
+
+ device_path = grub_xasprintf ("/sys/block/%s/slaves", curr_device);
+ dp = opendir(device_path);
+ free(device_path);
+
+ if (dp != NULL)
+ {
+ ep = readdir (dp);
+ while (ep != NULL){
+
+ /* avoid some system directories */
+ if (!strcmp(ep->d_name,"."))
+ goto next_dir;
+ if (!strcmp(ep->d_name,".."))
+ goto next_dir;
+
+ free (curr_device);
+ free (ret);
+ curr_device = grub_strdup (ep->d_name);
+ ret = grub_xasprintf ("%s%s", directory, curr_device);
+ break;
+
+ next_dir:
+ ep = readdir (dp);
+ continue;
+ }
+ closedir (dp);
+ }
+ else
+ grub_util_warn (_("cannot open directory `/sys/block/%s/slaves'"), curr_device);
+ }
+
+ free (directory);
+ free (curr_device);
+
+ return ret;
+}
+
char *
grub_util_devname_to_ofpath (const char *sys_devname)
{
- char *name_buf, *device, *devnode, *devicenode, *ofpath;
+ char *name_buf, *device, *devnode, *devicenode, *ofpath, *realname;
name_buf = xrealpath (sys_devname);
+ realname = get_slave_from_dm (name_buf);
+ if (realname)
+ {
+ free (name_buf);
+ name_buf = realname;
+ }
+
device = get_basename (name_buf);
devnode = strip_trailing_digits (name_buf);
devicenode = strip_trailing_digits (device);

View File

@ -0,0 +1,75 @@
From bb9bbe0f66a8462a1b2477fbc2aa1d70973035d4 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 30 Nov 2023 16:30:45 +0800
Subject: [PATCH 2/2] mkstandalone: ensure deterministic tar file creation by
sorting contents
The add_tar_files() function currently iterates through a directory's
content using readdir(), which doesn't guarantee a specific order. This
lack of deterministic behavior impacts reproducibility in the build
process.
This commit resolves the issue by introducing sorting functionality. The
list retrieved by readdir() is now sorted alphabetically before
incorporation into the tar archive, ensuring consistent and predictable
file ordering within the archive.
Signed-off-by: Michael Chang <mchang@suse.com>
Signed-off-by: Bernhard Wiedemann <bwiedemann@suse.com>
---
util/grub-mkstandalone.c | 26 +++++++++++++++++++++++---
1 file changed, 23 insertions(+), 3 deletions(-)
diff --git a/util/grub-mkstandalone.c b/util/grub-mkstandalone.c
index 8e1229925..e4b5bcab4 100644
--- a/util/grub-mkstandalone.c
+++ b/util/grub-mkstandalone.c
@@ -205,22 +205,42 @@ add_tar_file (const char *from,
{
grub_util_fd_dir_t d;
grub_util_fd_dirent_t de;
+ char **from_files;
+ grub_size_t alloc = 8, used = 0;
+ grub_size_t i;
d = grub_util_fd_opendir (from);
+ from_files = xmalloc (alloc * sizeof (*from_files));
while ((de = grub_util_fd_readdir (d)))
{
- char *fp, *tfp;
if (strcmp (de->d_name, ".") == 0)
continue;
if (strcmp (de->d_name, "..") == 0)
continue;
- fp = grub_util_path_concat (2, from, de->d_name);
- tfp = xasprintf ("%s/%s", to, de->d_name);
+ if (alloc <= used)
+ {
+ alloc <<= 1;
+ from_files = xrealloc (from_files, alloc * sizeof (*from_files));
+ }
+ from_files[used++] = xstrdup(de->d_name);
+ }
+ qsort (from_files, used, sizeof (*from_files), grub_qsort_strcmp);
+
+ for (i = 0; i < used; i++)
+ {
+ char *fp, *tfp;
+
+ fp = grub_util_path_concat (2, from, from_files[i]);
+ tfp = xasprintf ("%s/%s", to, from_files[i]);
add_tar_file (fp, tfp);
+ free (tfp);
free (fp);
+ free (from_files[i]);
}
+
grub_util_fd_closedir (d);
+ free (from_files);
free (tcn);
return;
}
--
2.43.0

View File

@ -0,0 +1,205 @@
From 990902e28c390217d25ea474e5ef163d79eadc7f Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 31 Mar 2023 15:19:58 +0800
Subject: [PATCH 2/2] prep_loadenv: Fix regex for Open Firmware device
specifier with encoded commas
The Open Firmware device specifier allows for comma-separated properties
of a component, but this conflicts with the way that grub separates
device and partition in its device specifier. To address this, grub
encodes commas in Open Firmware device strings with a leading backslash
as an established convention.
However, the regular expression used to extract the boot device
substring from the $cmdpath environment variable did not properly retain
commas with leading backslashes as part of the device. This could cause
the comma to be incorrectly interpreted as a partition delimiter and
result in a broken name for the boot disk.
To fix this issue, we have updated the regular expression to properly
handle the encoded comma in the Open Firmware device specifier, ensuring
that the correct boot device is identified and used.
v2:
Fix the issue of freeing an uninitialized pointer in early_prep_loadenv.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/commands/prep_loadenv.c | 108 ++++++++++++++++++++++--------
1 file changed, 79 insertions(+), 29 deletions(-)
--- a/grub-core/commands/prep_loadenv.c
+++ b/grub-core/commands/prep_loadenv.c
@@ -15,7 +15,7 @@
GRUB_MOD_LICENSE ("GPLv3+");
static char *
-match_substr (regmatch_t *match, const char *str)
+match_substr (const regmatch_t *match, const char *str)
{
if (match->rm_so != -1)
{
@@ -185,24 +185,18 @@
return err;
}
-static grub_err_t
-boot_disk_prep_partname (char **name)
+static regmatch_t *
+regex_match_str (const char *pattern, const char *str, grub_size_t *nmatch)
{
regex_t regex;
int ret;
grub_size_t s;
char *comperr;
- const char *cmdpath;
regmatch_t *matches = NULL;
grub_err_t err = GRUB_ERR_NONE;
- *name = NULL;
-
- cmdpath = grub_env_get ("cmdpath");
- if (!cmdpath)
- return GRUB_ERR_NONE;
-
- ret = regcomp (&regex, "\\(([^,]+)(,?.*)?\\)(.*)", REG_EXTENDED);
+ *nmatch = 0;
+ ret = regcomp (&regex, pattern, REG_EXTENDED);
if (ret)
goto fail;
@@ -210,22 +204,11 @@
if (! matches)
goto fail;
- ret = regexec (&regex, cmdpath, regex.re_nsub + 1, matches, 0);
- if (!ret)
+ ret = regexec (&regex, str, regex.re_nsub + 1, matches, 0);
+ if (ret == 0)
{
- char *devname = devname = match_substr (matches + 1, cmdpath);
- if (!devname)
- {
- err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "%s contains no disk name", cmdpath);
- goto out;
- }
-
- err = prep_partname (devname, name);
- out:
- grub_free (devname);
- regfree (&regex);
- grub_free (matches);
- return err;
+ *nmatch = regex.re_nsub + 1;
+ return matches;
}
fail:
@@ -235,13 +218,60 @@
if (!comperr)
{
regfree (&regex);
- return grub_errno;
+ return NULL;
}
regerror (ret, &regex, comperr, s);
err = grub_error (GRUB_ERR_TEST_FAILURE, "%s", comperr);
regfree (&regex);
grub_free (comperr);
- return err;
+ return NULL;
+}
+
+static grub_err_t
+boot_disk_prep_partname (const char *varname, char **name)
+{
+ const char *cmdpath;
+ regmatch_t *matches;
+ grub_size_t nmatch;
+ char *devname = NULL;
+
+ *name = NULL;
+
+ if (varname)
+ cmdpath = grub_env_get (varname);
+ else
+ cmdpath = grub_env_get ("cmdpath");
+ if (!cmdpath)
+ return GRUB_ERR_NONE;
+
+ matches = regex_match_str("\\((.*)\\)(.*)", cmdpath, &nmatch);
+ if (matches && nmatch >= 2)
+ devname = match_substr (matches + 1, cmdpath);
+ if (devname == NULL)
+ goto quit;
+ grub_free (matches);
+
+ matches = regex_match_str ("(.*[^\\])(,.*)", devname, &nmatch);
+ if (matches && nmatch >= 2)
+ {
+ char *n = match_substr (matches + 1, devname);
+ grub_free (devname);
+ devname = n;
+ }
+ else
+ grub_errno = GRUB_ERR_NONE;
+ if (devname)
+ {
+ grub_printf ("search prep from disk `%s'\n", devname);
+ prep_partname (devname, name);
+ }
+
+ quit:
+ grub_free (devname);
+ grub_free (matches);
+ if (grub_errno)
+ grub_print_error ();
+ return GRUB_ERR_NONE;
}
static grub_err_t
@@ -274,13 +304,31 @@
return GRUB_ERR_NONE;
}
+static grub_err_t
+grub_cmd_prep_partname (grub_command_t cmd __attribute__ ((unused)),
+ int argc,
+ char **argv)
+{
+ char *prep = NULL;
+ const char *varname = NULL;
+
+ if (argc > 0)
+ varname = argv[0];
+
+ boot_disk_prep_partname(varname, &prep);
+ if (prep)
+ grub_printf ("prep: %s\n", prep);
+
+ return GRUB_ERR_NONE;
+}
+
static void
early_prep_loadenv (void)
{
grub_err_t err;
- char *prep;
+ char *prep = NULL;
- err = boot_disk_prep_partname (&prep);
+ err = boot_disk_prep_partname (NULL, &prep);
if (err == GRUB_ERR_NONE && prep)
err = prep_read_envblk (prep);
if (err == GRUB_ERR_BAD_FILE_TYPE || err == GRUB_ERR_FILE_NOT_FOUND)
@@ -296,6 +344,10 @@
{
early_env_hook = early_prep_loadenv;
cmd_prep_load =
+ grub_register_command("prep_partname", grub_cmd_prep_partname,
+ "VARNAME",
+ N_("Get partition name of PReP."));
+ cmd_prep_load =
grub_register_command("prep_load_env", grub_cmd_prep_loadenv,
"DEVICE",
N_("Load variables from environment block file."));

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,427 @@
From 1d34522075949581ccb34a08dd73607566517824 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Tue, 7 Feb 2023 18:33:42 +0800
Subject: [PATCH 2/4] tpm2: Add more marshal/unmarshal functions
Add a few more marshal/unmarshal functions to support authorized policy.
* Marshal:
grub_tpm2_mu_TPMU_SENSITIVE_COMPOSITE_Marshal()
grub_tpm2_mu_TPMT_SENSITIVE_Marshal()
grub_tpm2_mu_TPM2B_SENSITIVE_Marshal()
grub_tpm2_mu_TPMS_SIGNATURE_RSA_Marshal()
grub_tpm2_mu_TPMS_SIGNATURE_ECC_Marshal()
grub_tpm2_mu_TPMU_HA_Marshal()
grub_tpm2_mu_TPMT_HA_Marshal()
grub_tpm2_mu_TPMU_SIGNATURE_Marshal()
grub_tpm2_mu_TPMT_SIGNATURE_Marshal()
grub_tpm2_mu_TPMT_TK_VERIFIED_Marshal()
* Unmarshal:
grub_tpm2_mu_TPMT_TK_HASHCHECK_Unmarshal()
grub_tpm2_mu_TPMT_TK_VERIFIED_Unmarshal()
grub_tpm2_mu_TPMS_SIGNATURE_RSA_Unmarshal()
grub_tpm2_mu_TPMS_SIGNATURE_ECC_Unmarshal()
grub_tpm2_mu_TPMU_HA_Unmarshal()
grub_tpm2_mu_TPMT_HA_Unmarshal()
grub_tpm2_mu_TPMU_SIGNATURE_Unmarshal()
grub_tpm2_mu_TPMT_SIGNATURE_Unmarshal()
Signed-off-by: Gary Lin <glin@suse.com>
---
grub-core/tpm2/mu.c | 262 +++++++++++++++++++++++++++++++++++++++++
include/grub/tpm2/mu.h | 75 ++++++++++++
2 files changed, 337 insertions(+)
diff --git a/grub-core/tpm2/mu.c b/grub-core/tpm2/mu.c
index 1617f37cd..3a9a3c1be 100644
--- a/grub-core/tpm2/mu.c
+++ b/grub-core/tpm2/mu.c
@@ -383,6 +383,49 @@ grub_tpm2_mu_TPMS_SENSITIVE_CREATE_Marshal (grub_tpm2_buffer_t buffer,
grub_tpm2_mu_TPM2B_Marshal (buffer, p->data.size, p->data.buffer);
}
+void
+grub_tpm2_mu_TPMU_SENSITIVE_COMPOSITE_Marshal (grub_tpm2_buffer_t buffer,
+ const TPMI_ALG_PUBLIC type,
+ const TPMU_SENSITIVE_COMPOSITE *p)
+{
+ switch(type)
+ {
+ case TPM_ALG_RSA:
+ grub_tpm2_mu_TPM2B_Marshal (buffer, p->rsa.size, p->rsa.buffer);
+ break;
+ case TPM_ALG_ECC:
+ grub_tpm2_mu_TPM2B_Marshal (buffer, p->ecc.size, p->ecc.buffer);
+ break;
+ case TPM_ALG_KEYEDHASH:
+ grub_tpm2_mu_TPM2B_Marshal (buffer, p->bits.size, p->bits.buffer);
+ break;
+ case TPM_ALG_SYMCIPHER:
+ grub_tpm2_mu_TPM2B_Marshal (buffer, p->sym.size, p->sym.buffer);
+ break;
+ default:
+ buffer->error = 1;
+ }
+}
+
+void
+grub_tpm2_mu_TPMT_SENSITIVE_Marshal (grub_tpm2_buffer_t buffer,
+ const TPMT_SENSITIVE *p)
+{
+ grub_tpm2_buffer_pack_u16 (buffer, p->sensitiveType);
+ grub_tpm2_mu_TPM2B_Marshal (buffer, p->authValue.size, p->authValue.buffer);
+ grub_tpm2_mu_TPM2B_Marshal (buffer, p->seedValue.size, p->seedValue.buffer);
+ grub_tpm2_mu_TPMU_SENSITIVE_COMPOSITE_Marshal (buffer, p->sensitiveType,
+ &p->sensitive);
+}
+
+void
+grub_tpm2_mu_TPM2B_SENSITIVE_Marshal (grub_tpm2_buffer_t buffer,
+ const TPM2B_SENSITIVE *p)
+{
+ grub_tpm2_buffer_pack_u16 (buffer, p->size);
+ grub_tpm2_mu_TPMT_SENSITIVE_Marshal (buffer, &p->sensitiveArea);
+}
+
void
grub_tpm2_mu_TPM2B_SENSITIVE_CREATE_Marshal (grub_tpm2_buffer_t buffer,
const TPM2B_SENSITIVE_CREATE *sensitiveCreate)
@@ -405,6 +448,113 @@ grub_tpm2_mu_TPM2B_SENSITIVE_CREATE_Marshal (grub_tpm2_buffer_t buffer,
grub_tpm2_buffer_pack_u16 (buffer, 0);
}
+void
+grub_tpm2_mu_TPMS_SIGNATURE_RSA_Marshal (grub_tpm2_buffer_t buffer,
+ const TPMS_SIGNATURE_RSA *p)
+{
+ grub_tpm2_buffer_pack_u16 (buffer, p->hash);
+ grub_tpm2_mu_TPM2B_Marshal (buffer, p->sig.size, p->sig.buffer);
+}
+
+void
+grub_tpm2_mu_TPMS_SIGNATURE_ECC_Marshal (grub_tpm2_buffer_t buffer,
+ const TPMS_SIGNATURE_ECC *p)
+{
+ grub_tpm2_buffer_pack_u16 (buffer, p->hash);
+ grub_tpm2_mu_TPM2B_Marshal (buffer, p->signatureR.size, p->signatureR.buffer);
+ grub_tpm2_mu_TPM2B_Marshal (buffer, p->signatureS.size, p->signatureS.buffer);
+}
+
+void
+grub_tpm2_mu_TPMU_HA_Marshal (grub_tpm2_buffer_t buffer,
+ const TPMI_ALG_HASH hashAlg,
+ const TPMU_HA *p)
+{
+ switch (hashAlg)
+ {
+ case TPM_ALG_SHA1:
+ for (grub_uint16_t i = 0; i < TPM_SHA1_DIGEST_SIZE; i++)
+ grub_tpm2_buffer_pack_u8 (buffer, p->sha1[i]);
+ break;
+ case TPM_ALG_SHA256:
+ for (grub_uint16_t i = 0; i < TPM_SHA256_DIGEST_SIZE; i++)
+ grub_tpm2_buffer_pack_u8 (buffer, p->sha256[i]);
+ break;
+ case TPM_ALG_SHA384:
+ for (grub_uint16_t i = 0; i < TPM_SHA384_DIGEST_SIZE; i++)
+ grub_tpm2_buffer_pack_u8 (buffer, p->sha384[i]);
+ break;
+ case TPM_ALG_SHA512:
+ for (grub_uint16_t i = 0; i < TPM_SHA512_DIGEST_SIZE; i++)
+ grub_tpm2_buffer_pack_u8 (buffer, p->sha512[i]);
+ break;
+ default:
+ buffer->error = 1;
+ break;
+ }
+}
+
+void
+grub_tpm2_mu_TPMT_HA_Marshal (grub_tpm2_buffer_t buffer,
+ const TPMT_HA *p)
+{
+ grub_tpm2_buffer_pack_u16 (buffer, p->hashAlg);
+ grub_tpm2_mu_TPMU_HA_Marshal (buffer, p->hashAlg, &p->digest);
+}
+
+void
+grub_tpm2_mu_TPMU_SIGNATURE_Marshal (grub_tpm2_buffer_t buffer,
+ const TPMI_ALG_SIG_SCHEME sigAlg,
+ const TPMU_SIGNATURE *p)
+{
+ switch (sigAlg)
+ {
+ case TPM_ALG_RSASSA:
+ grub_tpm2_mu_TPMS_SIGNATURE_RSA_Marshal (buffer, (TPMS_SIGNATURE_RSA *)&p->rsassa);
+ break;
+ case TPM_ALG_RSAPSS:
+ grub_tpm2_mu_TPMS_SIGNATURE_RSA_Marshal (buffer, (TPMS_SIGNATURE_RSA *)&p->rsapss);
+ break;
+ case TPM_ALG_ECDSA:
+ grub_tpm2_mu_TPMS_SIGNATURE_ECC_Marshal (buffer, (TPMS_SIGNATURE_ECC *)&p->ecdsa);
+ break;
+ case TPM_ALG_ECDAA:
+ grub_tpm2_mu_TPMS_SIGNATURE_ECC_Marshal (buffer, (TPMS_SIGNATURE_ECC *)&p->ecdaa);
+ break;
+ case TPM_ALG_SM2:
+ grub_tpm2_mu_TPMS_SIGNATURE_ECC_Marshal (buffer, (TPMS_SIGNATURE_ECC *)&p->sm2);
+ break;
+ case TPM_ALG_ECSCHNORR:
+ grub_tpm2_mu_TPMS_SIGNATURE_ECC_Marshal (buffer, (TPMS_SIGNATURE_ECC *)&p->ecschnorr);
+ break;
+ case TPM_ALG_HMAC:
+ grub_tpm2_mu_TPMT_HA_Marshal (buffer, &p->hmac);
+ break;
+ case TPM_ALG_NULL:
+ break;
+ default:
+ buffer->error = 1;
+ break;
+ }
+}
+
+void
+grub_tpm2_mu_TPMT_SIGNATURE_Marshal (grub_tpm2_buffer_t buffer,
+ const TPMT_SIGNATURE *p)
+{
+ grub_tpm2_buffer_pack_u16 (buffer, p->sigAlg);
+ grub_tpm2_mu_TPMU_SIGNATURE_Marshal (buffer, p->sigAlg, &p->signature);
+}
+
+void
+grub_tpm2_mu_TPMT_TK_VERIFIED_Marshal (grub_tpm2_buffer_t buffer,
+ const TPMT_TK_VERIFIED *p)
+{
+ grub_tpm2_buffer_pack_u16 (buffer, p->tag);
+ grub_tpm2_buffer_pack_u32 (buffer, p->hierarchy);
+ grub_tpm2_mu_TPM2B_Marshal (buffer, p->digest.size, p->digest.buffer);
+}
+
void
grub_tpm2_mu_TPM2B_Unmarshal (grub_tpm2_buffer_t buffer,
TPM2B* p)
@@ -775,6 +925,24 @@ grub_tpm2_mu_TPMT_TK_CREATION_Unmarshal (grub_tpm2_buffer_t buffer,
grub_tpm2_mu_TPM2B_Unmarshal (buffer, (TPM2B*) &p->digest);
}
+void
+grub_tpm2_mu_TPMT_TK_HASHCHECK_Unmarshal (grub_tpm2_buffer_t buffer,
+ TPMT_TK_HASHCHECK *p)
+{
+ grub_tpm2_buffer_unpack_u16 (buffer, &p->tag);
+ grub_tpm2_buffer_unpack_u32 (buffer, &p->hierarchy);
+ grub_tpm2_mu_TPM2B_Unmarshal (buffer, (TPM2B*) &p->digest);
+}
+
+void
+grub_tpm2_mu_TPMT_TK_VERIFIED_Unmarshal (grub_tpm2_buffer_t buffer,
+ TPMT_TK_VERIFIED *p)
+{
+ grub_tpm2_buffer_unpack_u16 (buffer, &p->tag);
+ grub_tpm2_buffer_unpack_u32 (buffer, &p->hierarchy);
+ grub_tpm2_mu_TPM2B_Unmarshal (buffer, (TPM2B*) &p->digest);
+}
+
void
grub_tpm2_mu_TPMS_PCR_SELECTION_Unmarshal (grub_tpm2_buffer_t buf,
TPMS_PCR_SELECTION* pcrSelection)
@@ -805,3 +973,97 @@ grub_tpm2_mu_TPML_DIGEST_Unmarshal (grub_tpm2_buffer_t buf,
for (grub_uint32_t i = 0; i < digest->count; i++)
grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (buf, &digest->digests[i]);
}
+
+void
+grub_tpm2_mu_TPMS_SIGNATURE_RSA_Unmarshal (grub_tpm2_buffer_t buffer,
+ TPMS_SIGNATURE_RSA *rsa)
+{
+ grub_tpm2_buffer_unpack_u16 (buffer, &rsa->hash);
+ grub_tpm2_mu_TPM2B_Unmarshal (buffer, (TPM2B*)&rsa->sig);
+}
+
+void
+grub_tpm2_mu_TPMS_SIGNATURE_ECC_Unmarshal (grub_tpm2_buffer_t buffer,
+ TPMS_SIGNATURE_ECC *ecc)
+{
+ grub_tpm2_buffer_unpack_u16 (buffer, &ecc->hash);
+ grub_tpm2_mu_TPM2B_Unmarshal (buffer, (TPM2B*)&ecc->signatureR);
+ grub_tpm2_mu_TPM2B_Unmarshal (buffer, (TPM2B*)&ecc->signatureS);
+}
+
+void
+grub_tpm2_mu_TPMU_HA_Unmarshal (grub_tpm2_buffer_t buffer,
+ TPMI_ALG_HASH hashAlg,
+ TPMU_HA *p)
+{
+ switch (hashAlg)
+ {
+ case TPM_ALG_SHA1:
+ grub_tpm2_buffer_unpack (buffer, &p->sha1, TPM_SHA1_DIGEST_SIZE);
+ break;
+ case TPM_ALG_SHA256:
+ grub_tpm2_buffer_unpack (buffer, &p->sha256, TPM_SHA256_DIGEST_SIZE);
+ break;
+ case TPM_ALG_SHA384:
+ grub_tpm2_buffer_unpack (buffer, &p->sha384, TPM_SHA384_DIGEST_SIZE);
+ break;
+ case TPM_ALG_SHA512:
+ grub_tpm2_buffer_unpack (buffer, &p->sha512, TPM_SHA512_DIGEST_SIZE);
+ break;
+ default:
+ buffer->error = 1;
+ break;
+ }
+}
+
+void
+grub_tpm2_mu_TPMT_HA_Unmarshal (grub_tpm2_buffer_t buffer,
+ TPMT_HA *p)
+{
+ grub_tpm2_buffer_unpack_u16 (buffer, &p->hashAlg);
+ grub_tpm2_mu_TPMU_HA_Unmarshal (buffer, p->hashAlg, &p->digest);
+}
+
+void
+grub_tpm2_mu_TPMU_SIGNATURE_Unmarshal (grub_tpm2_buffer_t buffer,
+ TPMI_ALG_SIG_SCHEME sigAlg,
+ TPMU_SIGNATURE *p)
+{
+ switch (sigAlg)
+ {
+ case TPM_ALG_RSASSA:
+ grub_tpm2_mu_TPMS_SIGNATURE_RSA_Unmarshal (buffer, (TPMS_SIGNATURE_RSA *)&p->rsassa);
+ break;
+ case TPM_ALG_RSAPSS:
+ grub_tpm2_mu_TPMS_SIGNATURE_RSA_Unmarshal (buffer, (TPMS_SIGNATURE_RSA *)&p->rsapss);
+ break;
+ case TPM_ALG_ECDSA:
+ grub_tpm2_mu_TPMS_SIGNATURE_ECC_Unmarshal (buffer, (TPMS_SIGNATURE_ECC *)&p->ecdsa);
+ break;
+ case TPM_ALG_ECDAA:
+ grub_tpm2_mu_TPMS_SIGNATURE_ECC_Unmarshal (buffer, (TPMS_SIGNATURE_ECC *)&p->ecdaa);
+ break;
+ case TPM_ALG_SM2:
+ grub_tpm2_mu_TPMS_SIGNATURE_ECC_Unmarshal (buffer, (TPMS_SIGNATURE_ECC *)&p->sm2);
+ break;
+ case TPM_ALG_ECSCHNORR:
+ grub_tpm2_mu_TPMS_SIGNATURE_ECC_Unmarshal (buffer, (TPMS_SIGNATURE_ECC *)&p->ecschnorr);
+ break;
+ case TPM_ALG_HMAC:
+ grub_tpm2_mu_TPMT_HA_Unmarshal (buffer, &p->hmac);
+ break;
+ case TPM_ALG_NULL:
+ break;
+ default:
+ buffer->error = 1;
+ break;
+ }
+}
+
+void
+grub_tpm2_mu_TPMT_SIGNATURE_Unmarshal (grub_tpm2_buffer_t buffer,
+ TPMT_SIGNATURE *p)
+{
+ grub_tpm2_buffer_unpack_u16 (buffer, &p->sigAlg);
+ grub_tpm2_mu_TPMU_SIGNATURE_Unmarshal (buffer, p->sigAlg, &p->signature);
+}
diff --git a/include/grub/tpm2/mu.h b/include/grub/tpm2/mu.h
index c545976db..afb842ab5 100644
--- a/include/grub/tpm2/mu.h
+++ b/include/grub/tpm2/mu.h
@@ -147,6 +147,47 @@ grub_tpm2_mu_TPM2B_SENSITIVE_CREATE_Marshal (grub_tpm2_buffer_t buf,
const TPM2B_SENSITIVE_CREATE *sensitiveCreate);
void
+grub_tpm2_mu_TPMU_SENSITIVE_COMPOSITE_Marshal (grub_tpm2_buffer_t buf,
+ const TPMI_ALG_PUBLIC type,
+ const TPMU_SENSITIVE_COMPOSITE *p);
+void
+grub_tpm2_mu_TPMT_SENSITIVE_Marshal (grub_tpm2_buffer_t buf,
+ const TPMT_SENSITIVE *p);
+
+void
+grub_tpm2_mu_TPM2B_SENSITIVE_Marshal (grub_tpm2_buffer_t buf,
+ const TPM2B_SENSITIVE *p);
+
+void
+grub_tpm2_mu_TPMS_SIGNATURE_RSA_Marshal (grub_tpm2_buffer_t buf,
+ const TPMS_SIGNATURE_RSA *p);
+
+void
+grub_tpm2_mu_TPMS_SIGNATURE_ECC_Marshal (grub_tpm2_buffer_t buf,
+ const TPMS_SIGNATURE_ECC *p);
+
+void
+grub_tpm2_mu_TPMU_HA_Marshal (grub_tpm2_buffer_t buf,
+ const TPMI_ALG_HASH hashAlg,
+ const TPMU_HA *p);
+
+void
+grub_tpm2_mu_TPMT_HA_Marshal (grub_tpm2_buffer_t buf,
+ const TPMT_HA *p);
+
+void
+grub_tpm2_mu_TPMU_SIGNATURE_Marshal (grub_tpm2_buffer_t buf,
+ const TPMI_ALG_SIG_SCHEME sigAlg,
+ const TPMU_SIGNATURE *p);
+
+void
+grub_tpm2_mu_TPMT_SIGNATURE_Marshal (grub_tpm2_buffer_t buf,
+ const TPMT_SIGNATURE *p);
+
+void
+grub_tpm2_mu_TPMT_TK_VERIFIED_Marshal (grub_tpm2_buffer_t buf,
+ const TPMT_TK_VERIFIED *p);
+void
grub_tpm2_mu_TPM2B_Unmarshal (grub_tpm2_buffer_t buf,
TPM2B* p);
@@ -277,6 +318,14 @@ void
grub_tpm2_mu_TPMT_TK_CREATION_Unmarshal (grub_tpm2_buffer_t buf,
TPMT_TK_CREATION *p);
+void
+grub_tpm2_mu_TPMT_TK_HASHCHECK_Unmarshal (grub_tpm2_buffer_t buf,
+ TPMT_TK_HASHCHECK *p);
+
+void
+grub_tpm2_mu_TPMT_TK_VERIFIED_Unmarshal (grub_tpm2_buffer_t buf,
+ TPMT_TK_VERIFIED *p);
+
void
grub_tpm2_mu_TPMS_PCR_SELECTION_Unmarshal (grub_tpm2_buffer_t buf,
TPMS_PCR_SELECTION* pcrSelection);
@@ -289,4 +338,30 @@ void
grub_tpm2_mu_TPML_DIGEST_Unmarshal (grub_tpm2_buffer_t buf,
TPML_DIGEST* digest);
+void
+grub_tpm2_mu_TPMS_SIGNATURE_RSA_Unmarshal (grub_tpm2_buffer_t buf,
+ TPMS_SIGNATURE_RSA *p);
+
+void
+grub_tpm2_mu_TPMS_SIGNATURE_ECC_Unmarshal (grub_tpm2_buffer_t buf,
+ TPMS_SIGNATURE_ECC *p);
+
+void
+grub_tpm2_mu_TPMU_HA_Unmarshal (grub_tpm2_buffer_t buf,
+ TPMI_ALG_HASH hashAlg,
+ TPMU_HA *p);
+
+void
+grub_tpm2_mu_TPMT_HA_Unmarshal (grub_tpm2_buffer_t buf,
+ TPMT_HA *p);
+
+void
+grub_tpm2_mu_TPMU_SIGNATURE_Unmarshal (grub_tpm2_buffer_t buf,
+ TPMI_ALG_SIG_SCHEME sigAlg,
+ TPMU_SIGNATURE *p);
+
+void
+grub_tpm2_mu_TPMT_SIGNATURE_Unmarshal (grub_tpm2_buffer_t buf,
+ TPMT_SIGNATURE *p);
+
#endif /* ! GRUB_TPM2_MU_HEADER */
--
2.35.3

View File

@ -0,0 +1,279 @@
From 25069a23257ba9c6db644bbe6114dafb879063e5 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 8 Jul 2019 12:32:37 +0200
Subject: [PATCH 03/11] Handle multi-arch (64-on-32) boot in linuxefi loader.
Allow booting 64-bit kernels on 32-bit EFI on x86.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/loader/efi/linux.c | 11 ++-
grub-core/loader/i386/efi/linux.c | 127 +++++++++++++++++++-----------
include/grub/i386/linux.h | 7 +-
3 files changed, 97 insertions(+), 48 deletions(-)
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -44,14 +44,10 @@
static grub_err_t
grub_linuxefi_boot (void)
{
- int offset = 0;
-
-#ifdef __x86_64__
- offset = 512;
-#endif
asm volatile ("cli");
- return grub_efi_linux_boot ((char *)kernel_mem, handover_offset + offset,
+ return grub_efi_linux_boot ((char *)kernel_mem,
+ handover_offset,
params);
}
@@ -147,14 +143,20 @@
return grub_errno;
}
+#define MIN(a, b) \
+ ({ typeof (a) _a = (a); \
+ typeof (b) _b = (b); \
+ _a < _b ? _a : _b; })
+
static grub_err_t
grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_file_t file = 0;
- struct linux_i386_kernel_header lh;
- grub_ssize_t len, start, filelen;
+ struct linux_i386_kernel_header *lh = NULL;
+ grub_ssize_t start, filelen;
void *kernel = NULL;
+ int setup_header_end_offset;
grub_err_t err;
grub_dl_ref (my_mod);
@@ -185,45 +187,79 @@
goto fail;
}
- params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384));
-
+ params = grub_efi_allocate_pages_max (0x3fffffff,
+ BYTES_TO_PAGES(sizeof(*params)));
if (! params)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
goto fail;
}
- grub_memset (params, 0, 16384);
+ grub_dprintf ("linux", "params = %p\n", params);
- grub_memcpy (&lh, kernel, sizeof (lh));
+ grub_memset (params, 0, sizeof(*params));
- if (lh.boot_flag != grub_cpu_to_le16 (0xaa55))
+ setup_header_end_offset = *((grub_uint8_t *)kernel + 0x201);
+ grub_dprintf ("linux", "copying %lu bytes from %p to %p\n",
+ MIN((grub_size_t)0x202+setup_header_end_offset,
+ sizeof (*params)) - 0x1f1,
+ (grub_uint8_t *)kernel + 0x1f1,
+ (grub_uint8_t *)params + 0x1f1);
+ grub_memcpy ((grub_uint8_t *)params + 0x1f1,
+ (grub_uint8_t *)kernel + 0x1f1,
+ MIN((grub_size_t)0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1);
+ lh = (struct linux_i386_kernel_header *)params;
+ grub_dprintf ("linux", "lh is at %p\n", lh);
+ grub_dprintf ("linux", "checking lh->boot_flag\n");
+ if (lh->boot_flag != grub_cpu_to_le16 (0xaa55))
{
grub_error (GRUB_ERR_BAD_OS, N_("invalid magic number"));
goto fail;
}
- if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
+ grub_dprintf ("linux", "checking lh->setup_sects\n");
+ if (lh->setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
{
grub_error (GRUB_ERR_BAD_OS, N_("too many setup sectors"));
goto fail;
}
- if (lh.version < grub_cpu_to_le16 (0x020b))
+ grub_dprintf ("linux", "checking lh->version\n");
+ if (lh->version < grub_cpu_to_le16 (0x020b))
{
grub_error (GRUB_ERR_BAD_OS, N_("kernel too old"));
goto fail;
}
- if (!lh.handover_offset)
+ grub_dprintf ("linux", "checking lh->handover_offset\n");
+ if (!lh->handover_offset)
{
grub_error (GRUB_ERR_BAD_OS, N_("kernel doesn't support EFI handover"));
goto fail;
}
- linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff,
- BYTES_TO_PAGES(lh.cmdline_size + 1));
+#if defined(__x86_64__) || defined(__aarch64__)
+ grub_dprintf ("linux", "checking lh->xloadflags\n");
+ if (!(lh->xloadflags & LINUX_XLF_KERNEL_64))
+ {
+ grub_error (GRUB_ERR_BAD_OS, N_("kernel doesn't support 64-bit CPUs"));
+ goto fail;
+ }
+#endif
+#if defined(__i386__)
+ if ((lh->xloadflags & LINUX_XLF_KERNEL_64) &&
+ !(lh->xloadflags & LINUX_XLF_EFI_HANDOVER_32))
+ {
+ grub_error (GRUB_ERR_BAD_OS,
+ N_("kernel doesn't support 32-bit handover"));
+ goto fail;
+ }
+#endif
+
+ grub_dprintf ("linux", "setting up cmdline\n");
+ linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff,
+ BYTES_TO_PAGES(lh->cmdline_size + 1));
if (!linux_cmdline)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline"));
@@ -233,27 +269,26 @@
grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
err = grub_create_loader_cmdline (argc, argv,
linux_cmdline + sizeof (LINUX_IMAGE) - 1,
- lh.cmdline_size - (sizeof (LINUX_IMAGE) - 1),
+ lh->cmdline_size - (sizeof (LINUX_IMAGE) - 1),
GRUB_VERIFY_KERNEL_CMDLINE);
if (err)
goto fail;
- lh.cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline;
+ grub_dprintf ("linux", "cmdline:%s\n", linux_cmdline);
+ grub_dprintf ("linux", "setting lh->cmd_line_ptr\n");
+ lh->cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline;
- handover_offset = lh.handover_offset;
+ grub_dprintf ("linux", "computing handover offset\n");
+ handover_offset = lh->handover_offset;
- start = (lh.setup_sects + 1) * 512;
- len = grub_file_size(file) - start;
+ start = (lh->setup_sects + 1) * 512;
- kernel_mem = grub_efi_allocate_fixed (lh.pref_address,
- BYTES_TO_PAGES(lh.init_size));
+ kernel_mem = grub_efi_allocate_pages_max(lh->pref_address,
+ BYTES_TO_PAGES(lh->init_size));
if (!kernel_mem)
- {
- grub_errno = GRUB_ERR_NONE;
- kernel_mem = grub_efi_allocate_pages_max(0x3fffffff,
- BYTES_TO_PAGES(lh.init_size));
- }
+ kernel_mem = grub_efi_allocate_pages_max(0x3fffffff,
+ BYTES_TO_PAGES(lh->init_size));
if (!kernel_mem)
{
@@ -261,21 +296,23 @@
goto fail;
}
- grub_memcpy (kernel_mem, (char *)kernel + start, len);
+ grub_dprintf ("linux", "kernel_mem = %lx\n", (unsigned long) kernel_mem);
+
grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
loaded=1;
+ grub_dprintf ("linux", "setting lh->code32_start to %p\n", kernel_mem);
+ lh->code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem;
- lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem;
- /* Grub linuxefi erroneously initialize linux's boot_params with non-zero values. (bsc#1025563)
+ grub_memcpy (kernel_mem, (char *)kernel + start, filelen - start);
- From https://www.kernel.org/doc/Documentation/x86/boot.txt:
- The memory for struct boot_params could be allocated anywhere (even above 4G)
- and initialized to all zero.
- Then, the setup header at offset 0x01f1 of kernel image on should be
- loaded into struct boot_params and examined. */
- grub_memcpy (&params->setup_sects, &lh.setup_sects, sizeof (lh) - 0x01f1);
+ grub_dprintf ("linux", "setting lh->type_of_loader\n");
+ lh->type_of_loader = 0x6;
- params->type_of_loader = 0x21;
+ grub_dprintf ("linux", "setting lh->ext_loader_{type,ver}\n");
+ params->ext_loader_type = 0;
+ params->ext_loader_ver = 2;
+ grub_dprintf("linux", "kernel_mem: %p handover_offset: %08x\n",
+ kernel_mem, handover_offset);
fail:
@@ -291,8 +328,10 @@
loaded = 0;
}
- if (linux_cmdline && !loaded)
- grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)linux_cmdline, BYTES_TO_PAGES(lh.cmdline_size + 1));
+ if (linux_cmdline && lh && !loaded)
+ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)
+ linux_cmdline,
+ BYTES_TO_PAGES(lh->cmdline_size + 1));
if (kernel_mem && !loaded)
grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)kernel_mem, BYTES_TO_PAGES(kernel_size));
--- a/include/grub/i386/linux.h
+++ b/include/grub/i386/linux.h
@@ -138,7 +138,12 @@
grub_uint32_t kernel_alignment;
grub_uint8_t relocatable;
grub_uint8_t min_alignment;
- grub_uint8_t pad[2];
+#define LINUX_XLF_KERNEL_64 (1<<0)
+#define LINUX_XLF_CAN_BE_LOADED_ABOVE_4G (1<<1)
+#define LINUX_XLF_EFI_HANDOVER_32 (1<<2)
+#define LINUX_XLF_EFI_HANDOVER_64 (1<<3)
+#define LINUX_XLF_EFI_KEXEC (1<<4)
+ grub_uint16_t xloadflags;
grub_uint32_t cmdline_size;
grub_uint32_t hardware_subarch;
grub_uint64_t hardware_subarch_data;
--- a/grub-core/loader/efi/linux_boot.c
+++ b/grub-core/loader/efi/linux_boot.c
@@ -30,11 +30,16 @@
typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *);
grub_err_t
-grub_efi_linux_boot (void *kernel_addr, grub_off_t offset,
+grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset,
void *kernel_params)
{
grub_efi_loaded_image_t *loaded_image = NULL;
handover_func hf;
+ int offset = 0;
+
+#ifdef __x86_64__
+ offset = 512;
+#endif
/*
* Since the EFI loader is not calling the LoadImage() and StartImage()
@@ -48,8 +53,8 @@
grub_dprintf ("linux", "Loaded Image base address could not be set\n");
grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p params: %p\n",
- kernel_addr, (void *)(grub_efi_uintn_t)offset, kernel_params);
- hf = (handover_func)((char *)kernel_addr + offset);
+ kernel_addr, (void *)(grub_efi_uintn_t)handover_offset, kernel_params);
+ hf = (handover_func)((char *)kernel_addr + handover_offset + offset);
hf (grub_efi_image_handle, grub_efi_system_table, kernel_params);
return GRUB_ERR_BUG;

View File

@ -0,0 +1,57 @@
From 3526c4e467ee01a3cfd2f4d627433d078a1ab780 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 27 Aug 2018 13:14:06 -0400
Subject: [PATCH 3/9] Make grub_error() more verbose
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/kern/efi/mm.c | 17 ++++++++++++++---
grub-core/kern/err.c | 13 +++++++++++--
include/grub/err.h | 5 ++++-
3 files changed, 29 insertions(+), 6 deletions(-)
--- a/grub-core/kern/err.c
+++ b/grub-core/kern/err.c
@@ -33,15 +33,24 @@
static int grub_error_stack_pos;
static int grub_error_stack_assert;
+#ifdef grub_error
+#undef grub_error
+#endif
+
grub_err_t
-grub_error (grub_err_t n, const char *fmt, ...)
+grub_error (grub_err_t n, const char *file, const int line, const char *fmt, ...)
{
va_list ap;
+ int m;
grub_errno = n;
+ m = grub_snprintf (grub_errmsg, sizeof (grub_errmsg), "%s:%d:", file, line);
+ if (m < 0)
+ m = 0;
+
va_start (ap, fmt);
- grub_vsnprintf (grub_errmsg, sizeof (grub_errmsg), _(fmt), ap);
+ grub_vsnprintf (grub_errmsg + m, sizeof (grub_errmsg) - m, _(fmt), ap);
va_end (ap);
return n;
--- a/include/grub/err.h
+++ b/include/grub/err.h
@@ -86,8 +86,11 @@
extern grub_err_t EXPORT_VAR(grub_errno);
extern char EXPORT_VAR(grub_errmsg)[GRUB_MAX_ERRMSG];
-grub_err_t EXPORT_FUNC(grub_error) (grub_err_t n, const char *fmt, ...)
- __attribute__ ((format (GNU_PRINTF, 2, 3)));
+grub_err_t EXPORT_FUNC(grub_error) (grub_err_t n, const char *file, const int line, const char *fmt, ...)
+ __attribute__ ((format (GNU_PRINTF, 4, 5)));
+
+#define grub_error(n, fmt, ...) grub_error (n, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
+
void EXPORT_FUNC(grub_fatal) (const char *fmt, ...) __attribute__ ((noreturn));
void EXPORT_FUNC(grub_error_push) (void);
int EXPORT_FUNC(grub_error_pop) (void);

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,36 @@
From 64494ffc442a5de05b237ad48d27c70d22849a44 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Thu, 3 Aug 2023 15:52:52 +0800
Subject: [PATCH 3/4] cryptodisk: wipe out the cached keys from protectors
An attacker may insert a malicious disk with the same crypto UUID and
trick grub2 to mount the fake root. Even though the key from the key
protector fails to unlock the fake root, it's not wiped out cleanly so
the attacker could dump the memory to retrieve the secret key. To defend
such attack, wipe out the cached key when we don't need it.
Signed-off-by: Gary Lin <glin@suse.com>
---
grub-core/disk/cryptodisk.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index cf37a0934..f42437f4e 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -1348,7 +1348,11 @@ grub_cryptodisk_clear_key_cache (struct grub_cryptomount_args *cargs)
return;
for (i = 0; cargs->protectors[i]; i++)
- grub_free (cargs->key_cache[i].key);
+ {
+ if (cargs->key_cache[i].key)
+ grub_memset (cargs->key_cache[i].key, 0, cargs->key_cache[i].key_len);
+ grub_free (cargs->key_cache[i].key);
+ }
grub_free (cargs->key_cache);
}
--
2.35.3

View File

@ -0,0 +1,73 @@
From 7e5f031a6a6a3decc2360a7b0c71abbe598e7354 Mon Sep 17 00:00:00 2001
From: Maxim Suhanov <dfirblog@gmail.com>
Date: Mon, 28 Aug 2023 16:33:17 +0300
Subject: [PATCH 3/6] fs/ntfs: Fix an OOB read when parsing directory entries
from resident and non-resident index attributes
This fix introduces checks to ensure that index entries are never read
beyond the corresponding directory index.
The lack of this check is a minor issue, likely not exploitable in any way.
Reported-by: Maxim Suhanov <dfirblog@gmail.com>
Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/ntfs.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
index a68e173d8..2d78b96e1 100644
--- a/grub-core/fs/ntfs.c
+++ b/grub-core/fs/ntfs.c
@@ -599,7 +599,7 @@ get_utf8 (grub_uint8_t *in, grub_size_t len)
}
static int
-list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos,
+list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos, grub_uint8_t *end_pos,
grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
{
grub_uint8_t *np;
@@ -610,6 +610,9 @@ list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos,
grub_uint8_t namespace;
char *ustr;
+ if ((pos >= end_pos) || (end_pos - pos < 0x52))
+ break;
+
if (pos[0xC] & 2) /* end signature */
break;
@@ -617,6 +620,9 @@ list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos,
ns = *(np++);
namespace = *(np++);
+ if (2 * ns > end_pos - pos - 0x52)
+ break;
+
/*
* Ignore files in DOS namespace, as they will reappear as Win32
* names.
@@ -806,7 +812,9 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
}
cur_pos += 0x10; /* Skip index root */
- ret = list_file (mft, cur_pos + u16at (cur_pos, 0), hook, hook_data);
+ ret = list_file (mft, cur_pos + u16at (cur_pos, 0),
+ at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR),
+ hook, hook_data);
if (ret)
goto done;
@@ -893,6 +901,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
(const grub_uint8_t *) "INDX")))
goto done;
ret = list_file (mft, &indx[0x18 + u16at (indx, 0x18)],
+ indx + (mft->data->idx_size << GRUB_NTFS_BLK_SHR),
hook, hook_data);
if (ret)
goto done;
--
2.42.0

View File

@ -0,0 +1,115 @@
From e7b1a524d5f86dcfddfbb069577e3b148dbb19cd Mon Sep 17 00:00:00 2001
From: Anthony Iliopoulos via Grub-devel <grub-devel@gnu.org>
Date: Thu, 26 Oct 2023 11:53:39 +0200
Subject: [PATCH 3/3] fs/xfs: add large extent counters incompat feature
support
XFS introduced 64-bit extent counters for inodes via a series of
upstream commits, and the feature was marked as stable in v6.5 via
commit 61d7e8274cd8 ("xfs: drop EXPERIMENTAL tag for large extent
counts").
Further, xfsprogs release v6.5.0 switched this feature on by default in
mkfs.xfs via commit e5b18d7d1d96 ("mkfs: enable large extent counts by
default").
Filesystems formatted with large extent count support (nrext64=1) are
thus currently not recognizable by grub, since this is an incompat
feature. Add the required support so that those filesystems and inodes
with large extent counters can be read by grub.
Signed-off-by: Anthony Iliopoulos <ailiop@suse.com>
---
grub-core/fs/xfs.c | 30 +++++++++++++++++++++++++-----
1 file changed, 25 insertions(+), 5 deletions(-)
diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
index 18edfcff4..bc2224dbb 100644
--- a/grub-core/fs/xfs.c
+++ b/grub-core/fs/xfs.c
@@ -79,6 +79,8 @@ GRUB_MOD_LICENSE ("GPLv3+");
/* Inode flags2 flags */
#define XFS_DIFLAG2_BIGTIME_BIT 3
#define XFS_DIFLAG2_BIGTIME (1 << XFS_DIFLAG2_BIGTIME_BIT)
+#define XFS_DIFLAG2_NREXT64_BIT 4
+#define XFS_DIFLAG2_NREXT64 (1 << XFS_DIFLAG2_NREXT64_BIT)
/* incompat feature flags */
#define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */
@@ -86,6 +88,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
#define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */
#define XFS_SB_FEAT_INCOMPAT_BIGTIME (1 << 3) /* large timestamps */
#define XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR (1 << 4) /* needs xfs_repair */
+#define XFS_SB_FEAT_INCOMPAT_NREXT64 (1 << 5) /* large extent counters */
/*
* Directory entries with ftype are explicitly handled by GRUB code.
@@ -101,7 +104,8 @@ GRUB_MOD_LICENSE ("GPLv3+");
XFS_SB_FEAT_INCOMPAT_SPINODES | \
XFS_SB_FEAT_INCOMPAT_META_UUID | \
XFS_SB_FEAT_INCOMPAT_BIGTIME | \
- XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR)
+ XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR | \
+ XFS_SB_FEAT_INCOMPAT_NREXT64)
struct grub_xfs_sblock
{
@@ -203,7 +207,8 @@ struct grub_xfs_inode
grub_uint16_t mode;
grub_uint8_t version;
grub_uint8_t format;
- grub_uint8_t unused2[26];
+ grub_uint8_t unused2[18];
+ grub_uint64_t nextents_big;
grub_uint64_t atime;
grub_uint64_t mtime;
grub_uint64_t ctime;
@@ -545,11 +550,26 @@ get_fsb (const void *keys, int idx)
return grub_be_to_cpu64 (grub_get_unaligned64 (p));
}
+static int
+grub_xfs_inode_has_large_extent_counts (const struct grub_xfs_inode *inode)
+{
+ return inode->version >= 3 &&
+ (inode->flags2 & grub_cpu_to_be64_compile_time (XFS_DIFLAG2_NREXT64));
+}
+
+static grub_uint64_t
+grub_xfs_get_inode_nextents (struct grub_xfs_inode *inode)
+{
+ return (grub_xfs_inode_has_large_extent_counts (inode)) ?
+ grub_be_to_cpu64 (inode->nextents_big) :
+ grub_be_to_cpu32 (inode->nextents);
+}
+
static grub_disk_addr_t
grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{
struct grub_xfs_btree_node *leaf = 0;
- int ex, nrec;
+ grub_uint64_t ex, nrec;
struct grub_xfs_extent *exts;
grub_uint64_t ret = 0;
@@ -574,7 +594,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
/ (2 * sizeof (grub_uint64_t));
do
{
- int i;
+ grub_uint64_t i;
for (i = 0; i < nrec; i++)
{
@@ -621,7 +641,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
grub_addr_t exts_end = 0;
grub_addr_t data_end = 0;
- nrec = grub_be_to_cpu32 (node->inode.nextents);
+ nrec = grub_xfs_get_inode_nextents (&node->inode);
exts = (struct grub_xfs_extent *) grub_xfs_inode_data(&node->inode);
if (grub_mul (sizeof (struct grub_xfs_extent), nrec, &exts_end) ||
--
2.42.1

View File

@ -0,0 +1,137 @@
From c31fc5aa0ded9ce1e774d0a3526cfee19be1b77f Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 7 Feb 2022 20:49:01 +0800
Subject: [PATCH 3/5] grub-install: support prep environment block
The grub-install can be instructed to create environment block at end of
PReP paritition with probed device identities and properties in
variables to facilitate root device discovery. So far these variables
are defined for this purpose:
ENV_FS_UUID - The filesystem uuid for the grub root device
ENV_CRYPTO_UUID - The crytodisk uuid for the grub root device separated
by space
ENV_GRUB_DIR - The path to grub prefix directory
ENV_HINT - The recommended hint string for searching root device
The size of environment block is defined in GRUB_ENVBLK_PREP_SIZE which
is 4096 bytes and can be extended in the future.
v2: Improve detection of ENV_CRYPTO_UUID by traversing all members of
the logical disk and utilize a space as a separator when multiple UUIDs
are found (bsc#1216075).
Signed-off-by: Michael Chang <mchang@suse.com>
---
include/grub/lib/envblk.h | 3 +++
util/grub-install.c | 38 ++++++++++++++++++++++++++++++++++++++
2 files changed, 41 insertions(+)
--- a/include/grub/lib/envblk.h
+++ b/include/grub/lib/envblk.h
@@ -24,6 +24,9 @@
#ifndef ASM_FILE
+#include <grub/disk.h>
+#define GRUB_ENVBLK_PREP_SIZE (GRUB_DISK_SECTOR_SIZE << 3)
+
struct grub_envblk
{
char *buf;
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -43,6 +43,7 @@
#include <grub/util/ofpath.h>
#include <grub/hfsplus.h>
#include <grub/time.h>
+#include <grub/lib/envblk.h>
#include <string.h>
@@ -609,6 +610,41 @@
}
}
+static char *
+cryptodisk_uuids (grub_disk_t disk, int in_recurse)
+{
+ grub_disk_memberlist_t list = NULL, tmp;
+ static char *ret;
+
+ if (!in_recurse)
+ ret = NULL;
+
+ if (disk->dev->disk_memberlist)
+ list = disk->dev->disk_memberlist (disk);
+
+ while (list)
+ {
+ ret = cryptodisk_uuids (list->disk, 1);
+ tmp = list->next;
+ free (list);
+ list = tmp;
+ }
+
+ if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
+ {
+ if (!ret)
+ ret = grub_strdup (grub_util_cryptodisk_get_uuid (disk));
+ else
+ {
+ char *s = grub_xasprintf ("%s %s", grub_util_cryptodisk_get_uuid (disk), ret);
+ grub_free (ret);
+ ret = s;
+ }
+ }
+
+ return ret;
+}
+
static int
is_same_disk (const char *a, const char *b)
{
@@ -2138,6 +2174,43 @@
if (write_to_disk (ins_dev, imgfile))
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)))
+ {
+ char *uuid = NULL;
+ grub_envblk_t envblk = NULL;
+ char *buf;
+ char *cryptouuid = NULL;
+
+ if (grub_dev->disk)
+ cryptouuid = cryptodisk_uuids (grub_dev->disk, 0);
+
+ if (grub_fs->fs_uuid && grub_fs->fs_uuid (grub_dev, &uuid))
+ {
+ grub_print_error ();
+ grub_errno = 0;
+ uuid = NULL;
+ }
+ buf = grub_envblk_buf (GRUB_ENVBLK_PREP_SIZE);
+ envblk = grub_envblk_open (buf, GRUB_ENVBLK_PREP_SIZE);
+ if (uuid)
+ grub_envblk_set (envblk, "ENV_FS_UUID", uuid);
+ if (cryptouuid)
+ grub_envblk_set (envblk, "ENV_CRYPTO_UUID", cryptouuid);
+ if (relative_grubdir)
+ grub_envblk_set (envblk, "ENV_GRUB_DIR", relative_grubdir);
+ if (have_abstractions)
+ grub_envblk_set (envblk, "ENV_HINT", grub_dev->disk->name);
+ if (use_relative_path_on_btrfs)
+ grub_envblk_set (envblk, "btrfs_relative_path", "1");
+ if (envblk)
+ {
+ fprintf (stderr, _("Write environment block to PReP.\n"));
+ if (grub_disk_write_tail (ins_dev->disk, envblk->size, envblk->buf))
+ grub_util_error ("%s", _("failed to write environment block to the PReP partition"));
+ }
+ grub_envblk_close (envblk);
+ }
grub_device_close (ins_dev);
if (update_nvram)
grub_install_register_ieee1275 (1, grub_util_get_os_disk (install_device),

View File

@ -0,0 +1,62 @@
From 1729400ab816804a28ebf50cb1310607b2c4b75e Mon Sep 17 00:00:00 2001
From: Diego Domingos <diegodo@br.ibm.com>
Date: Fri, 25 Feb 2022 12:49:51 -0500
Subject: [PATCH 3/4] ieee1275: change the logic of ieee1275_get_devargs()
Usually grub will parse the PFW arguments by searching for the first occurence of the character ':'.
However, we can have this char more than once on NQN.
This patch changes the logic to find the last occurence of this char so we can get the proper values
for NVMeoFC
---
grub-core/kern/ieee1275/openfw.c | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c
index f819bd106..655a71310 100644
--- a/grub-core/kern/ieee1275/openfw.c
+++ b/grub-core/kern/ieee1275/openfw.c
@@ -354,6 +354,13 @@ static char *
grub_ieee1275_get_devargs (const char *path)
{
char *colon = grub_strchr (path, ':');
+ char *colon_check = colon;
+
+ /* Find the last occurence of colon */
+ while(colon_check){
+ colon = colon_check;
+ colon_check = grub_strchr (colon+1, ':');
+ }
if (! colon)
return 0;
@@ -368,6 +375,18 @@ grub_ieee1275_get_devname (const char *path)
char *colon = grub_strchr (path, ':');
int pathlen = grub_strlen (path);
struct grub_ieee1275_devalias curalias;
+
+ /* Check some special cases */
+ if(grub_strstr(path, "nvme-of")){
+ char *namespace_split = grub_strstr(path,"/namespace@");
+ if(namespace_split){
+ colon = grub_strchr (namespace_split, ':');
+ } else {
+ colon = NULL;
+ }
+
+ }
+
if (colon)
pathlen = (int)(colon - path);
@@ -693,7 +712,7 @@ grub_ieee1275_get_boot_dev (void)
return NULL;
}
- bootpath = (char *) grub_malloc ((grub_size_t) bootpath_size + 64);
+ bootpath = (char *) grub_malloc ((grub_size_t) bootpath_size + 64 + 256);
if (! bootpath)
{
grub_print_error ();
--
2.35.3

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,543 @@
From a49c4dcbcb04078434f461ed3356c04042be461a Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Wed, 8 Feb 2023 10:30:55 +0800
Subject: [PATCH 3/4] tpm2: Implement more TPM2 commands
This commit implements a few more TPM2 commands as the preparation for
the authorized policy support.
* TPM2_LoadExternal
This command is added to load the external public key to verify the
signed policy digest
* TPM2_HashSequenceStart, TPM2_SequenceUpdate, TPM2_SequenceComplete,
and TPM2_Hash
With those commands, we can use the TPM as a coprocessor to calculate
the hash of a given binary blob.
* TPM2_VerifySignature
This command verifies the given signature with the given public key
and returns the validation ticket to authorize the policy.
* TPM2_PolicyAuthorize
This command approves the given policy digest so that we can unseal
the key with the newly authorized policy.
Signed-off-by: Gary Lin <glin@suse.com>
---
grub-core/tpm2/tpm2.c | 424 +++++++++++++++++++++++++
include/grub/tpm2/internal/functions.h | 57 ++++
2 files changed, 481 insertions(+)
diff --git a/grub-core/tpm2/tpm2.c b/grub-core/tpm2/tpm2.c
index d67699a24..159353b08 100644
--- a/grub-core/tpm2/tpm2.c
+++ b/grub-core/tpm2/tpm2.c
@@ -427,6 +427,73 @@ TPM2_Load (const TPMI_DH_OBJECT parent_handle,
return TPM_RC_SUCCESS;
}
+TPM_RC
+TPM2_LoadExternal (const TPMS_AUTH_COMMAND *authCommand,
+ const TPM2B_SENSITIVE *inPrivate,
+ const TPM2B_PUBLIC *inPublic,
+ const TPMI_RH_HIERARCHY hierarchy,
+ TPM_HANDLE *objectHandle,
+ TPM2B_NAME *name,
+ TPMS_AUTH_RESPONSE *authResponse)
+{
+ TPM_RC rc;
+ struct grub_tpm2_buffer in;
+ struct grub_tpm2_buffer out;
+ TPM_HANDLE objectHandleTmp;
+ TPM2B_NAME nameTmp;
+ TPMS_AUTH_RESPONSE authResponseTmp;
+ TPMI_ST_COMMAND_TAG tag = authCommand ? TPM_ST_SESSIONS : TPM_ST_NO_SESSIONS;
+ TPM_RC responseCode;
+ grub_uint32_t param_size;
+
+ if (!inPublic)
+ return TPM_RC_VALUE;
+
+ if (!objectHandle)
+ objectHandle = &objectHandleTmp;
+ if (!name)
+ name = &nameTmp;
+ if (!authResponse)
+ authResponse = &authResponseTmp;
+
+ grub_memset (objectHandle, 0, sizeof (*objectHandle));
+ grub_memset (name, 0, sizeof (*name));
+ grub_memset (authResponse, 0, sizeof (*authResponse));
+
+ /* Marshal */
+ grub_tpm2_buffer_init (&in);
+ if (authCommand)
+ grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
+ if (inPrivate)
+ grub_tpm2_mu_TPM2B_SENSITIVE_Marshal (&in, inPrivate);
+ else
+ grub_tpm2_buffer_pack_u16 (&in, 0);
+ grub_tpm2_mu_TPM2B_PUBLIC_Marshal (&in, inPublic);
+ grub_tpm2_buffer_pack_u32 (&in, hierarchy);
+ if (in.error)
+ return TPM_RC_FAILURE;
+
+ /* Submit */
+ grub_tpm2_buffer_init (&out);
+ rc = grub_tpm2_submit_command (tag, TPM_CC_LoadExternal, &responseCode, &in, &out);
+ if (rc != TPM_RC_SUCCESS)
+ return rc;
+ if (responseCode != TPM_RC_SUCCESS)
+ return responseCode;
+
+ /* Unmarshal*/
+ grub_tpm2_buffer_unpack_u32 (&out, objectHandle);
+ if (tag == TPM_ST_SESSIONS)
+ grub_tpm2_buffer_unpack_u32 (&out, &param_size);
+ grub_tpm2_mu_TPM2B_Unmarshal (&out, (TPM2B*)name);
+ if (tag == TPM_ST_SESSIONS)
+ grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal (&out, authResponse);
+ if (out.error)
+ return TPM_RC_FAILURE;
+
+ return TPM_RC_SUCCESS;
+}
+
TPM_RC
TPM2_Unseal (const TPMI_DH_OBJECT itemHandle,
const TPMS_AUTH_COMMAND *authCommand,
@@ -759,3 +826,360 @@ TPM2_EvictControl (const TPMI_RH_PROVISION auth,
return TPM_RC_SUCCESS;
}
+
+TPM_RC
+TPM2_HashSequenceStart (const TPMS_AUTH_COMMAND *authCommand,
+ const TPM2B_AUTH *auth,
+ const TPMI_ALG_HASH hashAlg,
+ TPMI_DH_OBJECT *sequenceHandle,
+ TPMS_AUTH_RESPONSE *authResponse)
+{
+ struct grub_tpm2_buffer in;
+ struct grub_tpm2_buffer out;
+ TPMI_DH_OBJECT sequenceHandleTmp;
+ TPMS_AUTH_RESPONSE authResponseTmp;
+ TPMI_ST_COMMAND_TAG tag = authCommand ? TPM_ST_SESSIONS : TPM_ST_NO_SESSIONS;
+ TPM_RC responseCode;
+ TPM_RC rc;
+ grub_uint32_t parameterSize;
+
+ if (!auth)
+ return TPM_RC_VALUE;
+
+ if (!sequenceHandle)
+ sequenceHandle = &sequenceHandleTmp;
+ if (!authResponse)
+ authResponse = &authResponseTmp;
+
+ grub_memset (sequenceHandle, 0, sizeof (*sequenceHandle));
+ grub_memset (authResponse, 0, sizeof (*authResponse));
+
+ /* Marshal */
+ grub_tpm2_buffer_init (&in);
+ if (authCommand)
+ grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
+ grub_tpm2_mu_TPM2B_Marshal (&in, auth->size, auth->buffer);
+ grub_tpm2_buffer_pack_u16 (&in, hashAlg);
+ if (in.error)
+ return TPM_RC_FAILURE;
+
+ /* Submit */
+ grub_tpm2_buffer_init (&out);
+ rc = grub_tpm2_submit_command (tag, TPM_CC_HashSequenceStart, &responseCode, &in,
+ &out);
+ if (rc != TPM_RC_SUCCESS)
+ return rc;
+ if (responseCode != TPM_RC_SUCCESS)
+ return responseCode;
+
+ /* Unmarshal */
+ grub_tpm2_buffer_unpack_u32 (&out, sequenceHandle);
+ if (tag == TPM_ST_SESSIONS)
+ {
+ grub_tpm2_buffer_unpack_u32 (&out, &parameterSize);
+ grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal(&out, authResponse);
+ }
+ if (out.error)
+ return TPM_RC_FAILURE;
+
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC
+TPM2_SequenceUpdate (const TPMI_DH_OBJECT sequenceHandle,
+ const TPMS_AUTH_COMMAND *authCommand,
+ const TPM2B_MAX_BUFFER *buffer,
+ TPMS_AUTH_RESPONSE *authResponse)
+{
+ struct grub_tpm2_buffer in;
+ struct grub_tpm2_buffer out;
+ TPMS_AUTH_RESPONSE authResponseTmp;
+ TPM_RC responseCode;
+ TPM_RC rc;
+ grub_uint32_t parameterSize;
+
+ if (!authCommand)
+ return TPM_RC_VALUE;
+
+ if (!authResponse)
+ authResponse = &authResponseTmp;
+
+ grub_memset (authResponse, 0, sizeof (*authResponse));
+
+ /* Marshal */
+ grub_tpm2_buffer_init (&in);
+ grub_tpm2_buffer_pack_u32 (&in, sequenceHandle);
+ grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
+ if (buffer)
+ grub_tpm2_mu_TPM2B_Marshal (&in, buffer->size, buffer->buffer);
+ else
+ grub_tpm2_buffer_pack_u16 (&in, 0);
+ if (in.error)
+ return TPM_RC_FAILURE;
+
+ /* Submit */
+ grub_tpm2_buffer_init (&out);
+ rc = grub_tpm2_submit_command (TPM_ST_SESSIONS, TPM_CC_SequenceUpdate,
+ &responseCode, &in, &out);
+ if (rc != TPM_RC_SUCCESS)
+ return rc;
+ if (responseCode != TPM_RC_SUCCESS)
+ return responseCode;
+
+ /* Unmarshal */
+ grub_tpm2_buffer_unpack_u32 (&out, &parameterSize);
+ grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal(&out, authResponse);
+ if (out.error)
+ return TPM_RC_FAILURE;
+
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC
+TPM2_SequenceComplete (const TPMI_DH_OBJECT sequenceHandle,
+ const TPMS_AUTH_COMMAND *authCommand,
+ const TPM2B_MAX_BUFFER *buffer,
+ const TPMI_RH_HIERARCHY hierarchy,
+ TPM2B_DIGEST *result,
+ TPMT_TK_HASHCHECK *validation,
+ TPMS_AUTH_RESPONSE *authResponse)
+{
+ struct grub_tpm2_buffer in;
+ struct grub_tpm2_buffer out;
+ TPM2B_DIGEST resultTmp;
+ TPMT_TK_HASHCHECK validationTmp;
+ TPMS_AUTH_RESPONSE authResponseTmp;
+ TPM_RC responseCode;
+ TPM_RC rc;
+ grub_uint32_t parameterSize;
+
+ if (!authCommand)
+ return TPM_RC_VALUE;
+
+ if (!result)
+ result = &resultTmp;
+ if (!validation)
+ validation = &validationTmp;
+ if (!authResponse)
+ authResponse = &authResponseTmp;
+
+ grub_memset (result, 0, sizeof (*result));
+ grub_memset (validation, 0, sizeof (*validation));
+ grub_memset (authResponse, 0, sizeof (*authResponse));
+
+ /* Marshal */
+ grub_tpm2_buffer_init (&in);
+ grub_tpm2_buffer_pack_u32 (&in, sequenceHandle);
+ grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
+ if (buffer)
+ grub_tpm2_mu_TPM2B_Marshal (&in, buffer->size, buffer->buffer);
+ else
+ grub_tpm2_buffer_pack_u16 (&in, 0);
+ grub_tpm2_buffer_pack_u32 (&in, hierarchy);
+
+ if (in.error)
+ return TPM_RC_FAILURE;
+
+ /* Submit */
+ grub_tpm2_buffer_init (&out);
+ rc = grub_tpm2_submit_command (TPM_ST_SESSIONS, TPM_CC_SequenceComplete,
+ &responseCode, &in, &out);
+ if (rc != TPM_RC_SUCCESS)
+ return rc;
+ if (responseCode != TPM_RC_SUCCESS)
+ return responseCode;
+
+ /* Unmarshal */
+ grub_tpm2_buffer_unpack_u32 (&out, &parameterSize);
+ grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (&out, result);
+ grub_tpm2_mu_TPMT_TK_HASHCHECK_Unmarshal (&out, validation);
+ grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal(&out, authResponse);
+ if (out.error)
+ return TPM_RC_FAILURE;
+
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC
+TPM2_Hash (const TPMS_AUTH_COMMAND *authCommand,
+ const TPM2B_MAX_BUFFER *data,
+ const TPMI_ALG_HASH hashAlg,
+ const TPMI_RH_HIERARCHY hierarchy,
+ TPM2B_DIGEST *outHash,
+ TPMT_TK_HASHCHECK *validation,
+ TPMS_AUTH_RESPONSE *authResponse)
+{
+ TPM_RC rc;
+ struct grub_tpm2_buffer in;
+ struct grub_tpm2_buffer out;
+ TPMS_AUTH_RESPONSE authResponseTmp;
+ TPM2B_DIGEST outHashTmp;
+ TPMT_TK_HASHCHECK validationTmp;
+ TPMI_ST_COMMAND_TAG tag = authCommand ? TPM_ST_SESSIONS : TPM_ST_NO_SESSIONS;
+ TPM_RC responseCode;
+ grub_uint32_t param_size;
+
+ if (hashAlg == TPM_ALG_NULL)
+ return TPM_RC_VALUE;
+
+ if (!outHash)
+ outHash = &outHashTmp;
+ if (!validation)
+ validation = &validationTmp;
+ if (!authResponse)
+ authResponse = &authResponseTmp;
+
+ grub_memset (outHash, 0, sizeof (*outHash));
+ grub_memset (validation, 0, sizeof (*validation));
+ grub_memset (authResponse, 0, sizeof (*authResponse));
+
+ /* Marshal */
+ grub_tpm2_buffer_init (&in);
+ if (authCommand)
+ grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
+ if (data)
+ grub_tpm2_mu_TPM2B_Marshal (&in, data->size, data->buffer);
+ else
+ grub_tpm2_buffer_pack_u16 (&in, 0);
+ grub_tpm2_buffer_pack_u16 (&in, hashAlg);
+ grub_tpm2_buffer_pack_u32 (&in, hierarchy);
+ if (in.error)
+ return TPM_RC_FAILURE;
+
+ /* Submit */
+ grub_tpm2_buffer_init (&out);
+ rc = grub_tpm2_submit_command (tag, TPM_CC_Hash, &responseCode, &in, &out);
+ if (rc != TPM_RC_SUCCESS)
+ return rc;
+ if (responseCode != TPM_RC_SUCCESS)
+ return responseCode;
+
+ /* Unmarshal*/
+ if (tag == TPM_ST_SESSIONS)
+ grub_tpm2_buffer_unpack_u32 (&out, &param_size);
+ grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (&out, outHash);
+ grub_tpm2_mu_TPMT_TK_HASHCHECK_Unmarshal (&out, validation);
+ if (tag == TPM_ST_SESSIONS)
+ grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal (&out, authResponse);
+ if (out.error)
+ return TPM_RC_FAILURE;
+
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC
+TPM2_VerifySignature (const TPMI_DH_OBJECT keyHandle,
+ const TPMS_AUTH_COMMAND *authCommand,
+ const TPM2B_DIGEST *digest,
+ const TPMT_SIGNATURE *signature,
+ TPMT_TK_VERIFIED *validation,
+ TPMS_AUTH_RESPONSE *authResponse)
+{
+ TPM_RC rc;
+ struct grub_tpm2_buffer in;
+ struct grub_tpm2_buffer out;
+ TPMS_AUTH_RESPONSE authResponseTmp;
+ TPMI_ST_COMMAND_TAG tag = authCommand ? TPM_ST_SESSIONS : TPM_ST_NO_SESSIONS;
+ TPMT_TK_VERIFIED validationTmp;
+ TPM_RC responseCode;
+ grub_uint32_t param_size;
+
+ if (!digest || !signature)
+ return TPM_RC_VALUE;
+
+ if (!validation)
+ validation = &validationTmp;
+ if (!authResponse)
+ authResponse = &authResponseTmp;
+
+ grub_memset (validation, 0, sizeof (*validation));
+ grub_memset (authResponse, 0, sizeof (*authResponse));
+
+ /* Marshal */
+ grub_tpm2_buffer_init (&in);
+ if (authCommand)
+ grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
+ grub_tpm2_buffer_pack_u32 (&in, keyHandle);
+ grub_tpm2_mu_TPM2B_Marshal (&in, digest->size, digest->buffer);
+ grub_tpm2_mu_TPMT_SIGNATURE_Marshal (&in, signature);
+ if (in.error)
+ return TPM_RC_FAILURE;
+
+ /* Submit */
+ grub_tpm2_buffer_init (&out);
+ rc = grub_tpm2_submit_command (tag, TPM_CC_VerifySignature, &responseCode, &in, &out);
+ if (rc != TPM_RC_SUCCESS)
+ return rc;
+ if (responseCode != TPM_RC_SUCCESS)
+ return responseCode;
+
+ /* Unmarshal*/
+ if (tag == TPM_ST_SESSIONS)
+ grub_tpm2_buffer_unpack_u32 (&out, &param_size);
+ grub_tpm2_mu_TPMT_TK_VERIFIED_Unmarshal (&out, validation);
+ if (tag == TPM_ST_SESSIONS)
+ grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal (&out, authResponse);
+ if (out.error)
+ return TPM_RC_FAILURE;
+
+ return TPM_RC_SUCCESS;
+}
+
+TPM_RC
+TPM2_PolicyAuthorize (const TPMI_SH_POLICY policySession,
+ const TPMS_AUTH_COMMAND *authCommand,
+ const TPM2B_DIGEST *approvedPolicy,
+ const TPM2B_NONCE *policyRef,
+ const TPM2B_NAME *keySign,
+ const TPMT_TK_VERIFIED *checkTicket,
+ TPMS_AUTH_RESPONSE *authResponse)
+{
+ TPM_RC rc;
+ struct grub_tpm2_buffer in;
+ struct grub_tpm2_buffer out;
+ TPMS_AUTH_RESPONSE authResponseTmp;
+ TPMI_ST_COMMAND_TAG tag = authCommand ? TPM_ST_SESSIONS : TPM_ST_NO_SESSIONS;
+ TPM_RC responseCode;
+ grub_uint32_t param_size;
+
+ if (!approvedPolicy || !keySign || !checkTicket)
+ return TPM_RC_VALUE;
+
+ if (!authResponse)
+ authResponse = &authResponseTmp;
+
+ grub_memset (authResponse, 0, sizeof (*authResponse));
+
+ /* Marshal */
+ grub_tpm2_buffer_init (&in);
+ grub_tpm2_buffer_pack_u32 (&in, policySession);
+ if (authCommand)
+ grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand);
+ grub_tpm2_mu_TPM2B_Marshal (&in, approvedPolicy->size, approvedPolicy->buffer);
+ if (policyRef)
+ grub_tpm2_mu_TPM2B_Marshal (&in, policyRef->size, policyRef->buffer);
+ else
+ grub_tpm2_buffer_pack_u16 (&in, 0);
+ grub_tpm2_mu_TPM2B_Marshal (&in, keySign->size, keySign->name);
+ grub_tpm2_mu_TPMT_TK_VERIFIED_Marshal (&in, checkTicket);
+ if (in.error)
+ return TPM_RC_FAILURE;
+
+ /* Submit */
+ grub_tpm2_buffer_init (&out);
+ rc = grub_tpm2_submit_command (tag, TPM_CC_PolicyAuthorize, &responseCode, &in, &out);
+ if (rc != TPM_RC_SUCCESS)
+ return rc;
+ if (responseCode != TPM_RC_SUCCESS)
+ return responseCode;
+
+ /* Unmarshal*/
+ if (tag == TPM_ST_SESSIONS)
+ grub_tpm2_buffer_unpack_u32 (&out, &param_size);
+ if (tag == TPM_ST_SESSIONS)
+ grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal (&out, authResponse);
+ if (out.error)
+ return TPM_RC_FAILURE;
+
+ return TPM_RC_SUCCESS;
+}
diff --git a/include/grub/tpm2/internal/functions.h b/include/grub/tpm2/internal/functions.h
index 9380f26a2..67b78fab8 100644
--- a/include/grub/tpm2/internal/functions.h
+++ b/include/grub/tpm2/internal/functions.h
@@ -70,6 +70,15 @@ TPM2_Load (const TPMI_DH_OBJECT parent_handle,
TPM2B_NAME *name,
TPMS_AUTH_RESPONSE *authResponse);
+TPM_RC
+TPM2_LoadExternal (const TPMS_AUTH_COMMAND *authCommand,
+ const TPM2B_SENSITIVE *inPrivate,
+ const TPM2B_PUBLIC *inPublic,
+ const TPMI_RH_HIERARCHY hierarchy,
+ TPM_HANDLE *objectHandle,
+ TPM2B_NAME *name,
+ TPMS_AUTH_RESPONSE *authResponse);
+
TPM_RC
TPM2_Unseal (const TPMI_DH_OBJECT item_handle,
const TPMS_AUTH_COMMAND *authCommand,
@@ -114,4 +123,52 @@ TPM2_EvictControl (const TPMI_RH_PROVISION auth,
const TPMI_DH_PERSISTENT persistentHandle,
TPMS_AUTH_RESPONSE *authResponse);
+TPM_RC
+TPM2_HashSequenceStart (const TPMS_AUTH_COMMAND *authCommand,
+ const TPM2B_AUTH *auth,
+ const TPMI_ALG_HASH hashAlg,
+ TPMI_DH_OBJECT *sequenceHandle,
+ TPMS_AUTH_RESPONSE *authResponse);
+
+TPM_RC
+TPM2_SequenceUpdate (const TPMI_DH_OBJECT sequenceHandle,
+ const TPMS_AUTH_COMMAND *authCommand,
+ const TPM2B_MAX_BUFFER *buffer,
+ TPMS_AUTH_RESPONSE *authResponse);
+
+TPM_RC
+TPM2_SequenceComplete (const TPMI_DH_OBJECT sequenceHandle,
+ const TPMS_AUTH_COMMAND *authCommand,
+ const TPM2B_MAX_BUFFER *buffer,
+ const TPMI_RH_HIERARCHY hierarchy,
+ TPM2B_DIGEST *result,
+ TPMT_TK_HASHCHECK *validation,
+ TPMS_AUTH_RESPONSE *authResponse);
+
+TPM_RC
+TPM2_Hash (const TPMS_AUTH_COMMAND *authCommand,
+ const TPM2B_MAX_BUFFER *data,
+ const TPMI_ALG_HASH hashAlg,
+ const TPMI_RH_HIERARCHY hierarchy,
+ TPM2B_DIGEST *outHash,
+ TPMT_TK_HASHCHECK *validation,
+ TPMS_AUTH_RESPONSE *authResponse);
+
+TPM_RC
+TPM2_VerifySignature (const TPMI_DH_OBJECT keyHandle,
+ const TPMS_AUTH_COMMAND *authCommand,
+ const TPM2B_DIGEST *digest,
+ const TPMT_SIGNATURE *signature,
+ TPMT_TK_VERIFIED *validation,
+ TPMS_AUTH_RESPONSE *authResponse);
+
+TPM_RC
+TPM2_PolicyAuthorize (const TPMI_SH_POLICY policySession,
+ const TPMS_AUTH_COMMAND *authCommand,
+ const TPM2B_DIGEST *approvedPolicy,
+ const TPM2B_NONCE *policyRef,
+ const TPM2B_NAME *keySign,
+ const TPMT_TK_VERIFIED *checkTicket,
+ TPMS_AUTH_RESPONSE *authResponse);
+
#endif /* ! GRUB_TPM2_INTERNAL_FUNCTIONS_HEADER */
--
2.35.3

View File

@ -0,0 +1,299 @@
From cf6b16f113b1b5e6efce79b569be1de3e504de8f Mon Sep 17 00:00:00 2001
From: Rashmica Gupta <rashmica.g@gmail.com>
Date: Thu, 11 Jun 2020 11:26:23 +1000
Subject: [PATCH 04/23] Add suport for signing grub with an appended signature
Add infrastructure to allow firmware to verify the integrity of grub
by use of a Linux-kernel-module-style appended signature. We initially
target powerpc-ieee1275, but the code should be extensible to other
platforms.
Usually these signatures are appended to a file without modifying the
ELF file itself. (This is what the 'sign-file' tool does, for example.)
The verifier loads the signed file from the file system and looks at the
end of the file for the appended signature. However, on powerpc-ieee1275
platforms, the bootloader is often stored directly in the PReP partition
as raw bytes without a file-system. This makes determining the location
of an appended signature more difficult.
To address this, we add a new ELF note.
The name field of shall be the string "Appended-Signature", zero-padded
to 4 byte alignment. The type field shall be 0x41536967 (the ASCII values
for the string "ASig"). It must be the final section in the ELF binary.
The description shall contain the appended signature structure as defined
by the Linux kernel. The description will also be padded to be a multiple
of 4 bytes. The padding shall be added before the appended signature
structure (not at the end) so that the final bytes of a signed ELF file
are the appended signature magic.
A subsequent patch documents how to create a grub core.img validly signed
under this scheme.
Signed-off-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Rashmica Gupta <rashmica.g@gmail.com>
---
You can experiment with this code with a patched version of SLOF
that verifies these signatures. You can find one at:
https://github.com/daxtens/SLOF
I will be proposing this for inclusion in a future Power Architecture
Platform Reference (PAPR).
---
include/grub/util/install.h | 8 ++++++--
include/grub/util/mkimage.h | 4 ++--
util/grub-install-common.c | 15 +++++++++++---
util/grub-mkimage.c | 11 +++++++++++
util/grub-mkimagexx.c | 39 ++++++++++++++++++++++++++++++++++++-
util/mkimage.c | 13 +++++++------
6 files changed, 76 insertions(+), 14 deletions(-)
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -67,6 +67,9 @@
N_("SBAT metadata"), 0 }, \
{ "disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, \
N_("disable shim_lock verifier"), 0 }, \
+ { "appended-signature-size", GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE,\
+ "SIZE", 0, N_("Add a note segment reserving SIZE bytes for an appended signature"), \
+ 1}, \
{ "verbose", 'v', 0, 0, \
N_("print verbose messages."), 1 }
@@ -130,7 +133,8 @@
GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS,
GRUB_INSTALL_OPTIONS_DTB,
GRUB_INSTALL_OPTIONS_SBAT,
- GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK
+ GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK,
+ GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE
};
extern char *grub_install_source_directory;
@@ -190,7 +194,7 @@
size_t npubkeys,
char *config_path,
const struct grub_install_image_target_desc *image_target,
- int note,
+ int note, size_t appsig_size,
grub_compression_t comp, const char *dtb_file,
const char *sbat_path, const int disable_shim_lock);
--- a/include/grub/util/mkimage.h
+++ b/include/grub/util/mkimage.h
@@ -51,12 +51,12 @@
const struct grub_install_image_target_desc *image_target);
void
grub_mkimage_generate_elf32 (const struct grub_install_image_target_desc *image_target,
- int note, char **core_img, size_t *core_size,
+ int note, size_t appsig_size, char **core_img, size_t *core_size,
Elf32_Addr target_addr,
struct grub_mkimage_layout *layout);
void
grub_mkimage_generate_elf64 (const struct grub_install_image_target_desc *image_target,
- int note, char **core_img, size_t *core_size,
+ int note, size_t appsig_size, char **core_img, size_t *core_size,
Elf64_Addr target_addr,
struct grub_mkimage_layout *layout);
--- a/util/grub-install-common.c
+++ b/util/grub-install-common.c
@@ -466,10 +466,12 @@
static char *sbat;
static int disable_shim_lock;
static grub_compression_t compression;
+static size_t appsig_size;
int
grub_install_parse (int key, char *arg)
{
+ const char *end;
switch (key)
{
case GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS:
@@ -567,6 +569,12 @@
grub_util_error (_("Unrecognized compression `%s'"), arg);
case GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE:
return 1;
+ case GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE:
+ grub_errno = 0;
+ appsig_size = grub_strtol(arg, &end, 10);
+ if (grub_errno)
+ return 0;
+ return 1;
default:
return 0;
}
@@ -666,10 +674,11 @@
" --output '%s' "
" --dtb '%s' "
"--sbat '%s' "
- "--format '%s' --compression '%s' %s %s %s\n",
+ "--format '%s' --compression '%s' "
+ "--appended-signature-size %zu %s %s %s\n",
dir, prefix,
outname, dtb ? : "", sbat ? : "", mkimage_target,
- compnames[compression], note ? "--note" : "",
+ compnames[compression], appsig_size, note ? "--note" : "",
disable_shim_lock ? "--disable-shim-lock" : "", s);
free (s);
@@ -680,7 +689,7 @@
grub_install_generate_image (dir, prefix, fp, outname,
modules.entries, memdisk_path,
pubkeys, npubkeys, config_path, tgt,
- note, compression, dtb, sbat,
+ note, appsig_size, compression, dtb, sbat,
disable_shim_lock);
while (dc--)
grub_install_pop_module ();
--- a/util/grub-mkimage.c
+++ b/util/grub-mkimage.c
@@ -84,6 +84,7 @@
{"sbat", 's', N_("FILE"), 0, N_("SBAT metadata"), 0},
{"disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, N_("disable shim_lock verifier"), 0},
{"verbose", 'v', 0, 0, N_("print verbose messages."), 0},
+ {"appended-signature-size", 'S', N_("SIZE"), 0, N_("Add a note segment reserving SIZE bytes for an appended signature"), 0},
{ 0, 0, 0, 0, 0, 0 }
};
@@ -128,6 +129,7 @@
char *sbat;
int note;
int disable_shim_lock;
+ size_t appsig_size;
const struct grub_install_image_target_desc *image_target;
grub_compression_t comp;
};
@@ -138,6 +140,7 @@
/* Get the input argument from argp_parse, which we
know is a pointer to our arguments structure. */
struct arguments *arguments = state->input;
+ const char* end;
switch (key)
{
@@ -170,6 +173,13 @@
arguments->note = 1;
break;
+ case 'S':
+ grub_errno = 0;
+ arguments->appsig_size = grub_strtol(arg, &end, 10);
+ if (grub_errno)
+ return 0;
+ break;
+
case 'm':
if (arguments->memdisk)
free (arguments->memdisk);
@@ -324,6 +334,7 @@
arguments.memdisk, arguments.pubkeys,
arguments.npubkeys, arguments.config,
arguments.image_target, arguments.note,
+ arguments.appsig_size,
arguments.comp, arguments.dtb,
arguments.sbat, arguments.disable_shim_lock);
--- a/util/grub-mkimagexx.c
+++ b/util/grub-mkimagexx.c
@@ -85,6 +85,15 @@
struct grub_ieee1275_note_desc descriptor;
};
+#define GRUB_APPENDED_SIGNATURE_NOTE_NAME "Appended-Signature"
+#define GRUB_APPENDED_SIGNATURE_NOTE_TYPE 0x41536967 /* "ASig" */
+
+struct grub_appended_signature_note
+{
+ Elf32_Nhdr header;
+ char name[ALIGN_UP(sizeof (GRUB_APPENDED_SIGNATURE_NOTE_NAME), 4)];
+};
+
#define GRUB_XEN_NOTE_NAME "Xen"
struct fixup_block_list
@@ -208,7 +217,7 @@
void
SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc *image_target,
- int note, char **core_img, size_t *core_size,
+ int note, size_t appsig_size, char **core_img, size_t *core_size,
Elf_Addr target_addr,
struct grub_mkimage_layout *layout)
{
@@ -222,6 +231,12 @@
int shnum = 4;
int string_size = sizeof (".text") + sizeof ("mods") + 1;
+ if (appsig_size)
+ {
+ phnum++;
+ footer_size += ALIGN_UP(sizeof (struct grub_appended_signature_note) + appsig_size, 4);
+ }
+
if (image_target->id != IMAGE_LOONGSON_ELF)
phnum += 2;
@@ -485,6 +500,28 @@
phdr->p_offset = grub_host_to_target32 (header_size + program_size);
}
+ if (appsig_size) {
+ int note_size = ALIGN_UP(sizeof (struct grub_appended_signature_note) + appsig_size, 4);
+ struct grub_appended_signature_note *note_ptr = (struct grub_appended_signature_note *)
+ (elf_img + program_size + header_size + (note ? sizeof (struct grub_ieee1275_note) : 0));
+
+ note_ptr->header.n_namesz = grub_host_to_target32 (sizeof (GRUB_APPENDED_SIGNATURE_NOTE_NAME));
+ /* needs to sit at the end, so we round this up and sign some zero padding */
+ note_ptr->header.n_descsz = grub_host_to_target32 (ALIGN_UP(appsig_size, 4));
+ note_ptr->header.n_type = grub_host_to_target32 (GRUB_APPENDED_SIGNATURE_NOTE_TYPE);
+ strcpy (note_ptr->name, GRUB_APPENDED_SIGNATURE_NOTE_NAME);
+
+ phdr++;
+ phdr->p_type = grub_host_to_target32 (PT_NOTE);
+ phdr->p_flags = grub_host_to_target32 (PF_R);
+ phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
+ phdr->p_vaddr = 0;
+ phdr->p_paddr = 0;
+ phdr->p_filesz = grub_host_to_target32 (note_size);
+ phdr->p_memsz = 0;
+ phdr->p_offset = grub_host_to_target32 (header_size + program_size + (note ? sizeof (struct grub_ieee1275_note) : 0));
+ }
+
{
char *str_start = (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr)
+ shnum * sizeof (*shdr));
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -885,8 +885,9 @@
char *memdisk_path, char **pubkey_paths,
size_t npubkeys, char *config_path,
const struct grub_install_image_target_desc *image_target,
- int note, grub_compression_t comp, const char *dtb_path,
- const char *sbat_path, int disable_shim_lock)
+ int note, size_t appsig_size, grub_compression_t comp,
+ const char *dtb_path, const char *sbat_path,
+ int disable_shim_lock)
{
char *kernel_img, *core_img;
size_t total_module_size, core_size;
@@ -1810,11 +1811,11 @@
else
target_addr = image_target->link_addr;
if (image_target->voidp_sizeof == 4)
- grub_mkimage_generate_elf32 (image_target, note, &core_img, &core_size,
- target_addr, &layout);
+ grub_mkimage_generate_elf32 (image_target, note, appsig_size, &core_img,
+ &core_size, target_addr, &layout);
else
- grub_mkimage_generate_elf64 (image_target, note, &core_img, &core_size,
- target_addr, &layout);
+ grub_mkimage_generate_elf64 (image_target, note, appsig_size, &core_img,
+ &core_size, target_addr, &layout);
}
break;
}

View File

@ -0,0 +1,272 @@
From 3cf4fdf8d17423dea4e5913ab14fb6305f3c2571 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 18 Feb 2022 21:43:38 +0800
Subject: [PATCH 4/5] Introduce prep_load_env command
This command will accept grub disk device and perform load_env for
environment block located at end of PReP partition which belongs to that
input disk device. All variables read from that environment block are
exported to grub as environment variables.
Please note there's no support for whitelist variables and also
--skip-sig option compared to ordinary load_env command.
v2:
To avoid disrupting the boot process with errors, it's important to log
any errors that may occur and always return GRUB_ERR_NONE.
v3:
Making the new module powerpc_ieee1275 specific.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/Makefile.core.def | 5 +
grub-core/commands/prep_loadenv.c | 227 ++++++++++++++++++++++++++++++
2 files changed, 232 insertions(+)
create mode 100644 grub-core/commands/prep_loadenv.c
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2673,3 +2673,9 @@
common = lib/libtasn1_wrap/tests/Test_strings.c;
common = lib/libtasn1_wrap/wrap_tests.c;
};
+
+module = {
+ name = prep_loadenv;
+ common = commands/prep_loadenv.c;
+ enable = powerpc_ieee1275;
+};
--- /dev/null
+++ b/grub-core/commands/prep_loadenv.c
@@ -0,0 +1,230 @@
+#include <grub/dl.h>
+#include <grub/mm.h>
+#include <grub/file.h>
+#include <grub/disk.h>
+#include <grub/misc.h>
+#include <grub/err.h>
+#include <grub/env.h>
+#include <grub/partition.h>
+#include <grub/lib/envblk.h>
+#include <grub/extcmd.h>
+#include <grub/i18n.h>
+#include <grub/gpt_partition.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static char *
+match_substr (regmatch_t *match, const char *str)
+{
+ if (match->rm_so != -1)
+ {
+ char *substr;
+ regoff_t sz = match->rm_eo - match->rm_so;
+
+ if (!sz)
+ return NULL;
+ substr = grub_malloc (1 + sz);
+ if (!substr)
+ {
+ grub_print_error ();
+ return NULL;
+ }
+ grub_memcpy (substr, str + match->rm_so, sz);
+ substr[sz] = '\0';
+ return substr;
+ }
+
+ return NULL;
+}
+
+static int
+is_prep_partition (grub_device_t dev)
+{
+ if (!dev->disk)
+ return 0;
+ if (!dev->disk->partition)
+ return 0;
+ if (grub_strcmp (dev->disk->partition->partmap->name, "msdos") == 0)
+ return (dev->disk->partition->msdostype == 0x41);
+
+ if (grub_strcmp (dev->disk->partition->partmap->name, "gpt") == 0)
+ {
+ struct grub_gpt_partentry gptdata;
+ grub_partition_t p = dev->disk->partition;
+ int ret = 0;
+ dev->disk->partition = dev->disk->partition->parent;
+
+ if (grub_disk_read (dev->disk, p->offset, p->index,
+ sizeof (gptdata), &gptdata) == 0)
+ {
+ const grub_guid_t template = {
+ grub_cpu_to_le32_compile_time (0x9e1a2d38),
+ grub_cpu_to_le16_compile_time (0xc612),
+ grub_cpu_to_le16_compile_time (0x4316),
+ { 0xaa, 0x26, 0x8b, 0x49, 0x52, 0x1e, 0x5a, 0x8b }
+ };
+
+ ret = grub_memcmp (&template, &gptdata.type,
+ sizeof (template)) == 0;
+ }
+ dev->disk->partition = p;
+ return ret;
+ }
+
+ return 0;
+}
+
+static int
+part_hook (grub_disk_t disk, const grub_partition_t partition, void *data)
+{
+ char **ret = data;
+ char *partition_name, *devname;
+ grub_device_t dev;
+
+ partition_name = grub_partition_get_name (partition);
+ if (! partition_name)
+ return 2;
+
+ devname = grub_xasprintf ("%s,%s", disk->name, partition_name);
+ grub_free (partition_name);
+ if (!devname)
+ return 2;
+
+ dev = grub_device_open (devname);
+ if (!dev)
+ {
+ grub_free (devname);
+ return 2;
+ }
+ if (is_prep_partition (dev))
+ {
+ *ret = devname;
+ return 1;
+ }
+ grub_free (devname);
+ grub_device_close (dev);
+ return 0;
+}
+
+static int
+set_var (const char *name, const char *value,
+ void *hook_data __attribute__ ((unused)))
+{
+ grub_env_set (name, value);
+ grub_env_export (name);
+ return 0;
+}
+
+static grub_err_t
+prep_read_envblk (const char *devname)
+{
+ char *buf = NULL;
+ grub_device_t dev = NULL;
+ grub_envblk_t envblk = NULL;
+
+ dev = grub_device_open (devname);
+ if (!dev)
+ return grub_errno;
+
+ if (!dev->disk || !dev->disk->partition)
+ {
+ grub_error (GRUB_ERR_BAD_DEVICE, "disk device required");
+ goto fail;
+ }
+
+ buf = grub_malloc (GRUB_ENVBLK_PREP_SIZE);
+ if (!buf)
+ goto fail;
+
+ if (grub_disk_read (dev->disk, dev->disk->partition->len - (GRUB_ENVBLK_PREP_SIZE >> GRUB_DISK_SECTOR_BITS), 0, GRUB_ENVBLK_PREP_SIZE, buf))
+ goto fail;
+
+ envblk = grub_envblk_open (buf, GRUB_ENVBLK_PREP_SIZE);
+ if (!envblk)
+ {
+ grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid environment block");
+ goto fail;
+ }
+ grub_envblk_iterate (envblk, NULL, set_var);
+
+ fail:
+ if (envblk)
+ grub_envblk_close (envblk);
+ else
+ grub_free (buf);
+ if (dev)
+ grub_device_close (dev);
+ return grub_errno;
+}
+
+static grub_err_t
+prep_partname (const char *devname, char **prep)
+{
+ grub_device_t dev = NULL;
+ grub_err_t err;
+ int ret;
+
+ dev = grub_device_open (devname);
+ if (!dev)
+ return grub_errno;
+
+ ret = grub_partition_iterate (dev->disk, part_hook, prep);
+ if (ret == 1 && *prep)
+ {
+ err = GRUB_ERR_NONE;
+ goto out;
+ }
+ else if (ret == 0 && grub_errno == GRUB_ERR_NONE)
+ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "no prep partition");
+ else
+ err = grub_errno;
+
+ out:
+ grub_device_close (dev);
+ return err;
+}
+
+static grub_err_t
+grub_cmd_prep_loadenv (grub_command_t cmd __attribute__ ((unused)),
+ int argc,
+ char **argv)
+{
+ char *devname, *prep = NULL;
+ grub_err_t err;
+
+ if (argc < 1)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
+
+ devname = grub_file_get_device_name(argv[0]);
+ if (!devname)
+ return grub_errno;
+
+ err = prep_partname (devname, &prep);
+ if (prep == NULL || err != GRUB_ERR_NONE)
+ goto out;
+
+ err = prep_read_envblk (prep);
+
+ out:
+ grub_free (devname);
+ grub_free (prep);
+
+ if (err)
+ grub_print_error ();
+ return GRUB_ERR_NONE;
+}
+
+static grub_command_t cmd_prep_load;
+
+GRUB_MOD_INIT(prep_loadenv)
+{
+ cmd_prep_load =
+ grub_register_command("prep_load_env", grub_cmd_prep_loadenv,
+ "DEVICE",
+ N_("Load variables from environment block file."));
+}
+
+GRUB_MOD_FINI(prep_loadenv)
+{
+ grub_unregister_command (cmd_prep_load);
+}

View File

@ -0,0 +1,91 @@
From 6547d22fc9e20720d1a896be82b2d50d842f86b0 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 20 Nov 2023 09:25:53 +0800
Subject: [PATCH 4/4] Key revocation on out of bound file access
After successful disk unlocking, grub now takes on the responsibility of
safeguarding passwords or TPM keys exclusively within authenticated
cryptodisk files. Any attempt to access boot-related files outside this
trust realm triggers immediate key revocation, preventing potential
compromise by out of bound access.
This patch strengthens security measures by restricting grub's access to
system boot files, except for essential internal processes like memdisk
and procfs, ensuring key protection against potential breaches due to
inadvertent customizations in grub.cfg.
Signed-Off-by Michael Chang <mchang@suse.com>
---
grub-core/commands/crypttab.c | 36 +++++++++++++++++++++++++++++++++++
include/grub/file.h | 1 +
2 files changed, 37 insertions(+)
diff --git a/grub-core/commands/crypttab.c b/grub-core/commands/crypttab.c
index d3acc4b59..e09296c57 100644
--- a/grub-core/commands/crypttab.c
+++ b/grub-core/commands/crypttab.c
@@ -121,6 +121,41 @@ grub_cryptokey_tpmkey_discard (void)
grub_cryptokey_discard();
}
+static grub_file_t
+grub_distrust_open (grub_file_t io,
+ enum grub_file_type type __attribute__ ((unused)))
+{
+ grub_disk_t disk = io->device->disk;
+
+ if (io->device->disk &&
+ (io->device->disk->dev->id == GRUB_DISK_DEVICE_MEMDISK_ID
+ || io->device->disk->dev->id == GRUB_DISK_DEVICE_PROCFS_ID))
+ return io;
+
+ /* Ensure second stage files is in a protected location or grub won't hand
+ * over the key and discards it */
+ switch (type & GRUB_FILE_TYPE_MASK)
+ {
+ case GRUB_FILE_TYPE_ACPI_TABLE:
+ case GRUB_FILE_TYPE_CONFIG:
+ case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE:
+ case GRUB_FILE_TYPE_FONT:
+ case GRUB_FILE_TYPE_GRUB_MODULE:
+ case GRUB_FILE_TYPE_GRUB_MODULE_LIST:
+ case GRUB_FILE_TYPE_LINUX_KERNEL:
+ case GRUB_FILE_TYPE_LINUX_INITRD:
+ case GRUB_FILE_TYPE_LOADENV:
+ case GRUB_FILE_TYPE_THEME:
+ if (!disk || !grub_disk_is_crypto (disk))
+ grub_cryptokey_discard ();
+ break;
+ default:
+ break;
+ }
+
+ return io;
+}
+
static grub_err_t
grub_cmd_crypttab_entry (grub_command_t cmd __attribute__ ((unused)),
int argc, char **argv)
@@ -153,6 +188,7 @@ GRUB_MOD_INIT(crypttab)
{
cmd = grub_register_command ("crypttab_entry", grub_cmd_crypttab_entry,
N_("VOLUME-NAME ENCRYPTED-DEVICE KEY-FILE") , N_("No description"));
+ grub_file_filter_register (GRUB_FILE_FILTER_DISTRUST, grub_distrust_open);
grub_dl_set_persistent (mod);
}
diff --git a/include/grub/file.h b/include/grub/file.h
index fcfd32ce2..daf23a9c9 100644
--- a/include/grub/file.h
+++ b/include/grub/file.h
@@ -185,6 +185,7 @@ extern grub_disk_read_hook_t EXPORT_VAR(grub_file_progress_hook);
/* Filters with lower ID are executed first. */
typedef enum grub_file_filter_id
{
+ GRUB_FILE_FILTER_DISTRUST,
GRUB_FILE_FILTER_NOCAT,
GRUB_FILE_FILTER_VERIFY,
GRUB_FILE_FILTER_GZIO,
--
2.42.1

View File

@ -0,0 +1,183 @@
From 384763d7990f769839ca74d6756fbd85580873d4 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 11 Jul 2019 17:17:02 +0200
Subject: [PATCH 04/11] Try to pick better locations for kernel and initrd
- Don't limit allocations on 64-bit platforms to < 0x[37f]fffffff if
we're using the "large" code model ; use __UINTPTR_MAX__.
- Get the comparison right to check the address we've allocated.
- Fix the allocation for the command line as well.
*But*, when we did this some systems started failing badly; coudln't
parse partition tables, etc. What's going on here is the disk controller
is silently failing DMAs to addresses above 4GB, so we're trying to parse
uninitialized (or HW zeroed) ram when looking for the partition table,
etc.
So to limit this, we make grub_malloc() pick addresses below 4GB on
x86_64, but the direct EFI page allocation functions can get addresses
above that.
Additionally, we now try to locate kernel+initrd+cmdline+etc below
0x7fffffff, and if they're too big to fit any memory window there, then
we try a higher address.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/kern/efi/mm.c | 8 ++++----
grub-core/loader/i386/efi/linux.c | 25 +++++++++++++++++--------
include/grub/arm/efi/memory.h | 1 +
include/grub/arm64/efi/memory.h | 1 +
include/grub/i386/efi/memory.h | 1 +
include/grub/ia64/efi/memory.h | 1 +
include/grub/x86_64/efi/memory.h | 4 +++-
7 files changed, 28 insertions(+), 13 deletions(-)
--- a/grub-core/kern/efi/mm.c
+++ b/grub-core/kern/efi/mm.c
@@ -121,7 +121,7 @@
grub_efi_boot_services_t *b;
grub_efi_physical_address_t address = max;
- if (max > 0xffffffff)
+ if (max > GRUB_EFI_MAX_USABLE_ADDRESS)
return 0;
b = grub_efi_system_table->boot_services;
@@ -481,7 +481,7 @@
{
if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY
#if 1
- && desc->physical_start <= GRUB_EFI_MAX_USABLE_ADDRESS
+ && desc->physical_start <= GRUB_EFI_MAX_ALLOCATION_ADDRESS
#endif
&& desc->physical_start + PAGES_TO_BYTES (desc->num_pages) > 0x100000
&& desc->num_pages != 0)
@@ -499,9 +499,9 @@
#if 1
if (BYTES_TO_PAGES (filtered_desc->physical_start)
+ filtered_desc->num_pages
- > BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_USABLE_ADDRESS))
+ > BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_ALLOCATION_ADDRESS))
filtered_desc->num_pages
- = (BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_USABLE_ADDRESS)
+ = (BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_ALLOCATION_ADDRESS)
- BYTES_TO_PAGES (filtered_desc->physical_start));
#endif
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -27,6 +27,7 @@
#include <grub/lib/cmdline.h>
#include <grub/efi/efi.h>
#include <grub/efi/linux.h>
+#include <grub/cpu/efi/memory.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -102,8 +103,9 @@
size += ALIGN_UP (grub_file_size (files[i]), 4);
}
- initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size));
-
+ initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS, BYTES_TO_PAGES(size));
+ if (!initrd_mem)
+ initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS, BYTES_TO_PAGES(size));
if (!initrd_mem)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd"));
@@ -187,8 +189,11 @@
goto fail;
}
- params = grub_efi_allocate_pages_max (0x3fffffff,
+ params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS,
BYTES_TO_PAGES(sizeof(*params)));
+ if (!params)
+ params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS,
+ BYTES_TO_PAGES(sizeof(*params)));
if (! params)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
@@ -258,8 +263,11 @@
#endif
grub_dprintf ("linux", "setting up cmdline\n");
- linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff,
- BYTES_TO_PAGES(lh->cmdline_size + 1));
+ linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS,
+ BYTES_TO_PAGES(lh->cmdline_size + 1));
+ if (!linux_cmdline)
+ linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS,
+ BYTES_TO_PAGES(lh->cmdline_size + 1));
if (!linux_cmdline)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline"));
@@ -285,11 +293,12 @@
kernel_mem = grub_efi_allocate_pages_max(lh->pref_address,
BYTES_TO_PAGES(lh->init_size));
-
if (!kernel_mem)
- kernel_mem = grub_efi_allocate_pages_max(0x3fffffff,
+ kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS,
+ BYTES_TO_PAGES(lh->init_size));
+ if (!kernel_mem)
+ kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS,
BYTES_TO_PAGES(lh->init_size));
-
if (!kernel_mem)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel"));
--- a/include/grub/arm/efi/memory.h
+++ b/include/grub/arm/efi/memory.h
@@ -2,5 +2,6 @@
#include <grub/efi/memory.h>
#define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
#endif /* ! GRUB_MEMORY_CPU_HEADER */
--- a/include/grub/arm64/efi/memory.h
+++ b/include/grub/arm64/efi/memory.h
@@ -2,5 +2,6 @@
#include <grub/efi/memory.h>
#define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffffffffULL
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
#endif /* ! GRUB_MEMORY_CPU_HEADER */
--- a/include/grub/i386/efi/memory.h
+++ b/include/grub/i386/efi/memory.h
@@ -2,5 +2,6 @@
#include <grub/efi/memory.h>
#define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
#endif /* ! GRUB_MEMORY_CPU_HEADER */
--- a/include/grub/ia64/efi/memory.h
+++ b/include/grub/ia64/efi/memory.h
@@ -2,5 +2,6 @@
#include <grub/efi/memory.h>
#define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
#endif /* ! GRUB_MEMORY_CPU_HEADER */
--- a/include/grub/x86_64/efi/memory.h
+++ b/include/grub/x86_64/efi/memory.h
@@ -2,9 +2,11 @@
#include <grub/efi/memory.h>
#if defined (__code_model_large__)
-#define GRUB_EFI_MAX_USABLE_ADDRESS 0xffffffff
+#define GRUB_EFI_MAX_USABLE_ADDRESS __UINTPTR_MAX__
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS 0x7fffffff
#else
#define GRUB_EFI_MAX_USABLE_ADDRESS 0x7fffffff
+#define GRUB_EFI_MAX_ALLOCATION_ADDRESS GRUB_EFI_MAX_USABLE_ADDRESS
#endif
#endif /* ! GRUB_MEMORY_CPU_HEADER */

View File

@ -0,0 +1,301 @@
From 5d417346956bc3108183020a8a9f20ddda034b48 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 11 Jul 2019 14:38:57 +0200
Subject: [PATCH 4/9] arm/arm64 loader: Better memory allocation and error
messages.
On mustang, our memory map looks like:
Type Physical start - end #Pages Size Attributes
reserved 0000004000000000-00000040001fffff 00000200 2MiB UC WC WT WB
conv-mem 0000004000200000-0000004393ffffff 00393e00 14654MiB UC WC WT WB
ldr-code 0000004394000000-00000043f7ffffff 00064000 1600MiB UC WC WT WB
BS-data 00000043f8000000-00000043f801ffff 00000020 128KiB UC WC WT WB
conv-mem 00000043f8020000-00000043fa15bfff 0000213c 34032KiB UC WC WT WB
ldr-code 00000043fa15c000-00000043fa2a1fff 00000146 1304KiB UC WC WT WB
ldr-data 00000043fa2a2000-00000043fa3e8fff 00000147 1308KiB UC WC WT WB
conv-mem 00000043fa3e9000-00000043fa3e9fff 00000001 4KiB UC WC WT WB
ldr-data 00000043fa3ea000-00000043fa3eafff 00000001 4KiB UC WC WT WB
ldr-code 00000043fa3eb000-00000043fa4affff 000000c5 788KiB UC WC WT WB
BS-code 00000043fa4b0000-00000043fa59ffff 000000f0 960KiB UC WC WT WB
RT-code 00000043fa5a0000-00000043fa5affff 00000010 64KiB RT UC WC WT WB
RT-data 00000043fa5b0000-00000043fa5bffff 00000010 64KiB RT UC WC WT WB
RT-code 00000043fa5c0000-00000043fa5cffff 00000010 64KiB RT UC WC WT WB
ldr-data 00000043fa5d0000-00000043fa5d0fff 00000001 4KiB UC WC WT WB
BS-code 00000043fa5d1000-00000043fa5ddfff 0000000d 52KiB UC WC WT WB
reserved 00000043fa5de000-00000043fa60ffff 00000032 200KiB UC WC WT WB
ACPI-rec 00000043fa610000-00000043fa6affff 000000a0 640KiB UC WC WT WB
ACPI-nvs 00000043fa6b0000-00000043fa6bffff 00000010 64KiB UC WC WT WB
ACPI-rec 00000043fa6c0000-00000043fa70ffff 00000050 320KiB UC WC WT WB
RT-code 00000043fa710000-00000043fa72ffff 00000020 128KiB RT UC WC WT WB
RT-data 00000043fa730000-00000043fa78ffff 00000060 384KiB RT UC WC WT WB
RT-code 00000043fa790000-00000043fa79ffff 00000010 64KiB RT UC WC WT WB
RT-data 00000043fa7a0000-00000043fa99ffff 00000200 2MiB RT UC WC WT WB
RT-code 00000043fa9a0000-00000043fa9affff 00000010 64KiB RT UC WC WT WB
RT-data 00000043fa9b0000-00000043fa9cffff 00000020 128KiB RT UC WC WT WB
BS-code 00000043fa9d0000-00000043fa9d9fff 0000000a 40KiB UC WC WT WB
reserved 00000043fa9da000-00000043fa9dbfff 00000002 8KiB UC WC WT WB
conv-mem 00000043fa9dc000-00000043fc29dfff 000018c2 25352KiB UC WC WT WB
BS-data 00000043fc29e000-00000043fc78afff 000004ed 5044KiB UC WC WT WB
conv-mem 00000043fc78b000-00000043fca01fff 00000277 2524KiB UC WC WT WB
BS-data 00000043fca02000-00000043fcea3fff 000004a2 4744KiB UC WC WT WB
conv-mem 00000043fcea4000-00000043fcea4fff 00000001 4KiB UC WC WT WB
BS-data 00000043fcea5000-00000043fd192fff 000002ee 3000KiB UC WC WT WB
conv-mem 00000043fd193000-00000043fd2b0fff 0000011e 1144KiB UC WC WT WB
BS-data 00000043fd2b1000-00000043ff80ffff 0000255f 38268KiB UC WC WT WB
BS-code 00000043ff810000-00000043ff99ffff 00000190 1600KiB UC WC WT WB
RT-code 00000043ff9a0000-00000043ff9affff 00000010 64KiB RT UC WC WT WB
conv-mem 00000043ff9b0000-00000043ff9bffff 00000010 64KiB UC WC WT WB
RT-data 00000043ff9c0000-00000043ff9effff 00000030 192KiB RT UC WC WT WB
conv-mem 00000043ff9f0000-00000043ffa05fff 00000016 88KiB UC WC WT WB
BS-data 00000043ffa06000-00000043ffffffff 000005fa 6120KiB UC WC WT WB
MMIO 0000000010510000-0000000010510fff 00000001 4KiB RT
MMIO 0000000010548000-0000000010549fff 00000002 8KiB RT
MMIO 0000000017000000-0000000017001fff 00000002 8KiB RT
MMIO 000000001c025000-000000001c025fff 00000001 4KiB RT
This patch adds a requirement when we're trying to find the base of ram, that
the memory we choose is actually /allocatable/ conventional memory, not merely
write-combining. On this machine that means we wind up with an allocation
around 0x4392XXXXXX, which is a reasonable address.
This also changes grub_efi_allocate_pages_real() so that if 0 is allocated, it
tries to allocate again starting with the same max address it did the first
time, rather than interposing GRUB_EFI_MAX_USABLE_ADDRESS there, so that any
per-platform constraints on its given address are maintained.
Signed-off-by: Peter Jones <pjones@redhat.com>
squash! arm/arm64 loader: Better memory allocation and error messages.
Use PRIxGRUB_* conversion specifier in printf's format string to
correspond properly to the data type of arguments.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/kern/efi/mm.c | 33 ++++++++++---
grub-core/loader/arm64/efi/linux.c | 78 ++++++++++++++++++++++--------
2 files changed, 84 insertions(+), 27 deletions(-)
--- a/grub-core/kern/efi/mm.c
+++ b/grub-core/kern/efi/mm.c
@@ -153,6 +153,7 @@
{
grub_efi_status_t status;
grub_efi_boot_services_t *b;
+ grub_efi_physical_address_t ret = address;
/* Limit the memory access to less than 4GB for 32-bit platforms. */
if (address > GRUB_EFI_MAX_USABLE_ADDRESS)
@@ -169,19 +170,22 @@
}
b = grub_efi_system_table->boot_services;
- status = b->allocate_pages (alloctype, memtype, pages, &address);
+ status = b->allocate_pages (alloctype, memtype, pages, &ret);
if (status != GRUB_EFI_SUCCESS)
{
+ grub_dprintf ("efi",
+ "allocate_pages(%d, %d, 0x%0" PRIxGRUB_SIZE ", 0x%016" PRIxGRUB_UINT64_T ") = 0x%016" PRIxGRUB_SIZE "\n",
+ alloctype, memtype, pages, address, status);
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
return NULL;
}
- if (address == 0)
+ if (ret == 0)
{
/* Uggh, the address 0 was allocated... This is too annoying,
so reallocate another one. */
- address = GRUB_EFI_MAX_USABLE_ADDRESS;
- status = b->allocate_pages (alloctype, memtype, pages, &address);
+ ret = address;
+ status = b->allocate_pages (alloctype, memtype, pages, &ret);
grub_efi_free_pages (0, pages);
if (status != GRUB_EFI_SUCCESS)
{
@@ -190,9 +194,9 @@
}
}
- grub_efi_store_alloc (address, pages);
+ grub_efi_store_alloc (ret, pages);
- return (void *) ((grub_addr_t) address);
+ return (void *) ((grub_addr_t) ret);
}
void *
@@ -711,8 +715,21 @@
for (desc = memory_map, *base_addr = GRUB_EFI_MAX_USABLE_ADDRESS;
(grub_addr_t) desc < ((grub_addr_t) memory_map + memory_map_size);
desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
- if (desc->attribute & GRUB_EFI_MEMORY_WB)
- *base_addr = grub_min (*base_addr, desc->physical_start);
+ {
+ if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY &&
+ (desc->attribute & GRUB_EFI_MEMORY_WB))
+ {
+ *base_addr = grub_min (*base_addr, desc->physical_start);
+ grub_dprintf ("efi", "setting base_addr=0x%016" PRIxGRUB_ADDR "\n", *base_addr);
+ }
+ else
+ {
+ grub_dprintf ("efi", "ignoring address 0x%016" PRIxGRUB_UINT64_T "\n", desc->physical_start);
+ }
+ }
+
+ if (*base_addr == GRUB_EFI_MAX_USABLE_ADDRESS)
+ grub_dprintf ("efi", "base_addr 0x%016" PRIxGRUB_ADDR " is probably wrong.\n", *base_addr);
grub_free(memory_map);
--- a/grub-core/loader/arm64/efi/linux.c
+++ b/grub-core/loader/arm64/efi/linux.c
@@ -89,13 +89,15 @@
{
grub_efi_loaded_image_t *loaded_image = NULL;
int node, retval, len;
-
+ grub_err_t err = GRUB_ERR_NONE;
void *fdt;
fdt = grub_fdt_load (GRUB_EFI_LINUX_FDT_EXTRA_SPACE);
-
if (!fdt)
- goto failure;
+ {
+ err = grub_error(GRUB_ERR_BAD_OS, "failed to load FDT");
+ goto failure;
+ }
node = grub_fdt_find_subnode (fdt, 0, "chosen");
if (node < 0)
@@ -106,17 +108,26 @@
*/
retval = grub_fdt_set_prop32(fdt, 0, "#address-cells", 2);
if (retval)
- goto failure;
+ {
+ err = grub_error(retval, "Could not find #address-cells");
+ goto failure;
+ }
retval = grub_fdt_set_prop32(fdt, 0, "#size-cells", 2);
if (retval)
- goto failure;
+ {
+ err = grub_error(retval, "Could not find #size-cells");
+ goto failure;
+ }
node = grub_fdt_add_subnode (fdt, 0, "chosen");
}
if (node < 1)
- goto failure;
+ {
+ err = grub_error(grub_errno, "failed to load chosen fdt node.");
+ goto failure;
+ }
/* Set initrd info */
if (initrd_start && initrd_end > initrd_start)
@@ -127,15 +138,26 @@
retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-start",
initrd_start);
if (retval)
- goto failure;
+ {
+ err = grub_error(retval, "Failed to set linux,initrd-start property");
+ goto failure;
+ }
+
retval = grub_fdt_set_prop64 (fdt, node, "linux,initrd-end",
initrd_end);
if (retval)
- goto failure;
+ {
+ err = grub_error(retval, "Failed to set linux,initrd-end property");
+ goto failure;
+ }
}
- if (grub_fdt_install() != GRUB_ERR_NONE)
- goto failure;
+ retval = grub_fdt_install();
+ if (retval != GRUB_ERR_NONE)
+ {
+ err = grub_error(retval, "Failed to install fdt");
+ goto failure;
+ }
grub_dprintf ("linux", "Installed/updated FDT configuration table @ %p\n",
fdt);
@@ -143,14 +165,20 @@
/* Convert command line to UCS-2 */
loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
if (!loaded_image)
- goto failure;
+ {
+ err = grub_error(grub_errno, "Failed to install fdt");
+ goto failure;
+ }
loaded_image->load_options_size = len =
(grub_strlen (linux_args) + 1) * sizeof (grub_efi_char16_t);
loaded_image->load_options =
grub_efi_allocate_any_pages (GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
if (!loaded_image->load_options)
- return grub_error(GRUB_ERR_BAD_OS, "failed to create kernel parameters");
+ {
+ err = grub_error(GRUB_ERR_BAD_OS, "failed to create kernel parameters");
+ goto failure;
+ }
loaded_image->load_options_size =
2 * grub_utf8_to_utf16 (loaded_image->load_options, len,
@@ -160,7 +188,7 @@
failure:
grub_fdt_unload();
- return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT");
+ return err;
}
static void
@@ -246,16 +274,28 @@
static void *
allocate_initrd_mem (int initrd_pages)
{
- grub_addr_t max_addr;
+ grub_addr_t max_addr = 0;
+ grub_err_t err;
+ void *ret;
+
+ err = grub_efi_get_ram_base (&max_addr);
+ if (err != GRUB_ERR_NONE)
+ {
+ grub_error (err, "grub_efi_get_ram_base() failed");
+ return NULL;
+ }
- if (grub_efi_get_ram_base (&max_addr) != GRUB_ERR_NONE)
- return NULL;
+ grub_dprintf ("linux", "max_addr: 0x%016lx, INITRD_MAX_ADDRESS_OFFSET: 0x%016llx\n",
+ max_addr, INITRD_MAX_ADDRESS_OFFSET);
max_addr += INITRD_MAX_ADDRESS_OFFSET - 1;
+ grub_dprintf ("linux", "calling grub_efi_allocate_pages_real (0x%016lx, 0x%08x, EFI_ALLOCATE_MAX_ADDRESS, EFI_LOADER_DATA)", max_addr, initrd_pages);
- return grub_efi_allocate_pages_real (max_addr, initrd_pages,
- GRUB_EFI_ALLOCATE_MAX_ADDRESS,
- GRUB_EFI_LOADER_DATA);
+ ret = grub_efi_allocate_pages_real (max_addr, initrd_pages,
+ GRUB_EFI_ALLOCATE_MAX_ADDRESS,
+ GRUB_EFI_LOADER_DATA);
+ grub_dprintf ("linux", "got 0x%016llx\n", (unsigned long long)ret);
+ return ret;
}
static grub_err_t

View File

@ -0,0 +1,342 @@
From 9888bf40d960339a59dc18fb6e1df5f65b4668e3 Mon Sep 17 00:00:00 2001
From: Hernan Gatta <hegatta@linux.microsoft.com>
Date: Tue, 1 Feb 2022 05:02:56 -0800
Subject: [PATCH 13/14] cryptodisk: Support key protectors
Add a new parameter to cryptomount to support the key protectors framework: -k.
The parameter is used to automatically retrieve a key from specified key
protectors. The parameter may be repeated to specify any number of key
protectors. These are tried in order until one provides a usable key for any
given disk.
Signed-off-by: <Hernan Gatta hegatta@linux.microsoft.com>
---
Makefile.util.def | 1 +
grub-core/disk/cryptodisk.c | 166 +++++++++++++++++++++++++++++-------
include/grub/cryptodisk.h | 14 +++
3 files changed, 151 insertions(+), 30 deletions(-)
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -35,6 +35,7 @@
common = grub-core/kern/list.c;
common = grub-core/kern/misc.c;
common = grub-core/kern/partition.c;
+ common = grub-core/kern/protectors.c;
common = grub-core/lib/crypto.c;
common = grub-core/lib/json/json.c;
common = grub-core/disk/luks.c;
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -26,6 +26,7 @@
#include <grub/file.h>
#include <grub/procfs.h>
#include <grub/partition.h>
+#include <grub/protector.h>
#ifdef GRUB_UTIL
#include <grub/emu/hostdisk.h>
@@ -44,7 +45,8 @@
OPTION_KEYFILE,
OPTION_KEYFILE_OFFSET,
OPTION_KEYFILE_SIZE,
- OPTION_HEADER
+ OPTION_HEADER,
+ OPTION_PROTECTOR
};
static const struct grub_arg_option options[] =
@@ -58,6 +60,8 @@
{"keyfile-offset", 'O', 0, N_("Key file offset (bytes)"), 0, ARG_TYPE_INT},
{"keyfile-size", 'S', 0, N_("Key file data size (bytes)"), 0, ARG_TYPE_INT},
{"header", 'H', 0, N_("Read header from file"), 0, ARG_TYPE_STRING},
+ {"protector", 'P', GRUB_ARG_OPTION_REPEATABLE,
+ N_("Unlock volume(s) using key protector(s)."), 0, ARG_TYPE_STRING},
{0, 0, 0, 0, 0, 0}
};
@@ -1061,6 +1065,7 @@
grub_err_t ret = GRUB_ERR_NONE;
grub_cryptodisk_t dev;
grub_cryptodisk_dev_t cr;
+ int i;
struct cryptodisk_read_hook_ctx read_hook_data = {0};
int askpass = 0;
char *part = NULL;
@@ -1113,41 +1118,112 @@
goto error_no_close;
if (!dev)
continue;
+ break;
+ }
- if (!cargs->key_len)
- {
- /* Get the passphrase from the user, if no key data. */
- askpass = 1;
- part = grub_partition_get_name (source->partition);
- grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
- source->partition != NULL ? "," : "",
- part != NULL ? part : N_("UNKNOWN"),
- dev->uuid);
- grub_free (part);
-
- cargs->key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE);
- if (cargs->key_data == NULL)
- goto error_no_close;
+ if (dev == NULL)
+ {
+ grub_error (GRUB_ERR_BAD_MODULE,
+ "no cryptodisk module can handle this device");
+ goto error_no_close;
+ }
- if (!grub_password_get ((char *) cargs->key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE))
- {
- grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied");
- goto error;
- }
- cargs->key_len = grub_strlen ((char *) cargs->key_data);
- }
+ if (cargs->protectors)
+ {
+ for (i = 0; cargs->protectors[i]; i++)
+ {
+ if (cargs->key_cache[i].invalid)
+ continue;
- ret = cr->recover_key (source, dev, cargs);
- if (ret != GRUB_ERR_NONE)
- goto error;
+ if (cargs->key_cache[i].key == NULL)
+ {
+ ret = grub_key_protector_recover_key (cargs->protectors[i],
+ &cargs->key_cache[i].key,
+ &cargs->key_cache[i].key_len);
+ if (ret != GRUB_ERR_NONE)
+ {
+ if (grub_errno)
+ {
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+ }
+
+ grub_dprintf ("cryptodisk",
+ "failed to recover a key from key protector "
+ "%s, will not try it again for any other "
+ "disks, if any, during this invocation of "
+ "cryptomount\n",
+ cargs->protectors[i]);
+
+ cargs->key_cache[i].invalid = 1;
+ continue;
+ }
+ }
+
+ cargs->key_data = cargs->key_cache[i].key;
+ cargs->key_len = cargs->key_cache[i].key_len;
+
+ ret = cr->recover_key (source, dev, cargs);
+ if (ret != GRUB_ERR_NONE)
+ {
+ part = grub_partition_get_name (source->partition);
+ grub_dprintf ("cryptodisk",
+ "recovered a key from key protector %s but it "
+ "failed to unlock %s%s%s (%s)\n",
+ cargs->protectors[i], source->name,
+ source->partition != NULL ? "," : "",
+ part != NULL ? part : N_("UNKNOWN"), dev->uuid);
+ grub_free (part);
+ continue;
+ }
+ else
+ {
+ ret = grub_cryptodisk_insert (dev, name, source);
+ if (ret != GRUB_ERR_NONE)
+ goto error;
+ goto cleanup;
+ }
+ }
- ret = grub_cryptodisk_insert (dev, name, source);
- if (ret != GRUB_ERR_NONE)
+ part = grub_partition_get_name (source->partition);
+ grub_error (GRUB_ERR_ACCESS_DENIED,
+ N_("no key protector provided a usable key for %s%s%s (%s)"),
+ source->name, source->partition != NULL ? "," : "",
+ part != NULL ? part : N_("UNKNOWN"), dev->uuid);
+ grub_free (part);
goto error;
+ }
+
+ if (!cargs->key_len)
+ {
+ /* Get the passphrase from the user, if no key data. */
+ askpass = 1;
+ part = grub_partition_get_name (source->partition);
+ grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
+ source->partition != NULL ? "," : "",
+ part != NULL ? part : N_("UNKNOWN"), dev->uuid);
+ grub_free (part);
+
+ cargs->key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE);
+ if (cargs->key_data == NULL)
+ goto error;
+
+ if (!grub_password_get ((char *) cargs->key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE))
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied");
+ goto error;
+ }
+ cargs->key_len = grub_strlen ((char *) cargs->key_data);
+ }
+
+ ret = cr->recover_key (source, dev, cargs);
+ if (ret != GRUB_ERR_NONE)
+ goto error;
+
+ ret = grub_cryptodisk_insert (dev, name, source);
+ if (ret != GRUB_ERR_NONE)
+ goto error;
- goto cleanup;
- }
- grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk module can handle this device");
goto cleanup;
error:
@@ -1258,6 +1334,20 @@
return ret;
}
+static void
+grub_cryptodisk_clear_key_cache (struct grub_cryptomount_args *cargs)
+{
+ int i;
+
+ if (cargs->key_cache == NULL || cargs->protectors == NULL)
+ return;
+
+ for (i = 0; cargs->protectors[i]; i++)
+ grub_free (cargs->key_cache[i].key);
+
+ grub_free (cargs->key_cache);
+}
+
static grub_err_t
grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
{
@@ -1270,6 +1360,10 @@
if (grub_cryptodisk_list == NULL)
return grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk modules loaded");
+ if (state[OPTION_PASSWORD].set && state[OPTION_PROTECTOR].set) /* password and key protector */
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "a password and a key protector cannot both be set");
+
if (state[OPTION_PASSWORD].set) /* password */
{
cargs.key_data = (grub_uint8_t *) state[OPTION_PASSWORD].arg;
@@ -1362,6 +1456,15 @@
return grub_errno;
}
+ if (state[OPTION_PROTECTOR].set) /* key protector(s) */
+ {
+ cargs.key_cache = grub_zalloc (state[OPTION_PROTECTOR].set * sizeof (*cargs.key_cache));
+ if (cargs.key_cache == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY,
+ "no memory for key protector key cache");
+ cargs.protectors = state[OPTION_PROTECTOR].args;
+ }
+
if (state[OPTION_UUID].set) /* uuid */
{
int found_uuid;
@@ -1370,6 +1473,7 @@
dev = grub_cryptodisk_get_by_uuid (args[0]);
if (dev)
{
+ grub_cryptodisk_clear_key_cache (&cargs);
grub_dprintf ("cryptodisk",
"already mounted as crypto%lu\n", dev->id);
return GRUB_ERR_NONE;
@@ -1378,6 +1482,7 @@
cargs.check_boot = state[OPTION_BOOT].set;
cargs.search_uuid = args[0];
found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
+ grub_cryptodisk_clear_key_cache (&cargs);
if (found_uuid)
return GRUB_ERR_NONE;
@@ -1397,6 +1502,7 @@
{
cargs.check_boot = state[OPTION_BOOT].set;
grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
+ grub_cryptodisk_clear_key_cache (&cargs);
return GRUB_ERR_NONE;
}
else
@@ -1420,6 +1526,7 @@
disk = grub_disk_open (diskname);
if (!disk)
{
+ grub_cryptodisk_clear_key_cache (&cargs);
if (disklast)
*disklast = ')';
return grub_errno;
@@ -1430,12 +1537,14 @@
{
grub_dprintf ("cryptodisk", "already mounted as crypto%lu\n", dev->id);
grub_disk_close (disk);
+ grub_cryptodisk_clear_key_cache (&cargs);
if (disklast)
*disklast = ')';
return GRUB_ERR_NONE;
}
dev = grub_cryptodisk_scan_device_real (diskname, disk, &cargs);
+ grub_cryptodisk_clear_key_cache (&cargs);
grub_disk_close (disk);
if (disklast)
@@ -1576,6 +1685,7 @@
cmd = grub_register_extcmd ("cryptomount", grub_cmd_cryptomount, 0,
N_("[ [-p password] | [-k keyfile"
" [-O keyoffset] [-S keysize] ] ] [-H file]"
+ " [-P protector [-P protector ...]]"
" <SOURCE|-u UUID|-a|-b>"),
N_("Mount a crypto device."), options);
grub_procfs_register ("luks_script", &luks_script);
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -70,6 +70,18 @@
(*grub_cryptodisk_rekey_func_t) (struct grub_cryptodisk *dev,
grub_uint64_t zoneno);
+struct grub_cryptomount_cached_key
+{
+ grub_uint8_t *key;
+ grub_size_t key_len;
+
+ /*
+ * The key protector associated with this cache entry failed, so avoid it
+ * even if the cached entry (an instance of this structure) is empty.
+ */
+ int invalid;
+};
+
struct grub_cryptomount_args
{
/* scan: Flag to indicate that only bootable volumes should be decrypted */
@@ -81,6 +93,10 @@
/* recover_key: Length of key_data */
grub_size_t key_len;
grub_file_t hdr_file;
+ /* recover_key: Names of the key protectors to use (NULL-terminated) */
+ char **protectors;
+ /* recover_key: Key cache to avoid invoking the same key protector twice */
+ struct grub_cryptomount_cached_key *key_cache;
};
typedef struct grub_cryptomount_args *grub_cryptomount_args_t;

View File

@ -0,0 +1,89 @@
From b7e2fb6a680447b7bb7eb18bb7570afa8d2b7f09 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Thu, 10 Aug 2023 10:19:29 +0800
Subject: [PATCH 4/4] diskfilter: look up cryptodisk devices first
When using disk auto-unlocking with TPM 2.0, the typical grub.cfg may
look like this:
tpm2_key_protector_init --tpm2key=(hd0,gpt1)/boot/grub2/sealed.tpm
cryptomount -u <PART-UUID> -P tpm2
search --fs-uuid --set=root <FS-UUID>
Since the disk search order is based on the order of module loading, the
attacker could insert a malicious disk with the same FS-UUID root to
trick grub2 to boot into th malicious root and further dump memory to
steal the unsealed key.
To defend such attack, we can specify the hint provided by 'grub-probe'
to search the encrypted partition first:
search --fs-uuid --set=root --hint='cryptouuid/<PART-UUID>' <FS-UUID>
However, for LVM on a encrypted partition, the search hint provided by
'grub-probe' is:
--hint='lvmid/<VG-UUID>/<LV-UUID>'
It doesn't guarantee to look up the logical volume from the encrypted
partition, so the attacker may have the chance to fool grub2 to boot
into the malicious disk.
To mininize the attack surface, this commit tweaks the disk device search
in diskfilter to look up cryptodisk devices first and then others, so
that the auto-unlocked disk will be found first, not the attacker's disk.
Signed-off-by: Gary Lin <glin@suse.com>
---
grub-core/disk/diskfilter.c | 35 ++++++++++++++++++++++++++---------
1 file changed, 26 insertions(+), 9 deletions(-)
diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c
index 61a311efd..94832c8dd 100644
--- a/grub-core/disk/diskfilter.c
+++ b/grub-core/disk/diskfilter.c
@@ -226,15 +226,32 @@ scan_devices (const char *arname)
int need_rescan;
for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++)
- for (p = grub_disk_dev_list; p; p = p->next)
- if (p->id != GRUB_DISK_DEVICE_DISKFILTER_ID
- && p->disk_iterate)
- {
- if ((p->disk_iterate) (scan_disk_hook, NULL, pull))
- return;
- if (arname && is_lv_readable (find_lv (arname), 1))
- return;
- }
+ {
+ /* look up the crytodisk devices first */
+ for (p = grub_disk_dev_list; p; p = p->next)
+ if (p->id == GRUB_DISK_DEVICE_CRYPTODISK_ID
+ && p->disk_iterate)
+ {
+ if ((p->disk_iterate) (scan_disk_hook, NULL, pull))
+ return;
+ if (arname && is_lv_readable (find_lv (arname), 1))
+ return;
+ break;
+ }
+
+ /* check the devices other than crytodisk */
+ for (p = grub_disk_dev_list; p; p = p->next)
+ if (p->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
+ continue;
+ else if (p->id != GRUB_DISK_DEVICE_DISKFILTER_ID
+ && p->disk_iterate)
+ {
+ if ((p->disk_iterate) (scan_disk_hook, NULL, pull))
+ return;
+ if (arname && is_lv_readable (find_lv (arname), 1))
+ return;
+ }
+ }
scan_depth = 0;
need_rescan = 1;
--
2.35.3

View File

@ -0,0 +1,116 @@
From ca482c7c1efe5faf792bf0912a116ea8e0642e24 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Wed, 15 Apr 2015 14:48:30 +0800
Subject: [PATCH 4/8] efinet: UEFI IPv6 PXE support
When grub2 image is booted from UEFI IPv6 PXE, the DHCPv6 Reply packet is
cached in firmware buffer which can be obtained by PXE Base Code protocol. The
network interface can be setup through the parameters in that obtained packet.
Signed-off-by: Michael Chang <mchang@suse.com>
Signed-off-by: Ken Lin <ken.lin@hpe.com>
---
grub-core/net/drivers/efi/efinet.c | 24 +++++++++++++----
include/grub/efi/api.h | 55 +++++++++++++++++++++++++++++++++++++-
2 files changed, 73 insertions(+), 6 deletions(-)
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -400,6 +400,18 @@
continue;
pxe_mode = pxe->mode;
+ if (pxe_mode->using_ipv6)
+ {
+ grub_net_configure_by_dhcpv6_reply (card->name, card, 0,
+ (struct grub_net_dhcp6_packet *)
+ &pxe_mode->dhcp_ack,
+ sizeof (pxe_mode->dhcp_ack),
+ 1, device, path);
+ if (grub_errno)
+ grub_print_error ();
+ }
+ else
+ {
inter = grub_net_configure_by_dhcp_ack (card->name, card, 0,
(struct grub_net_bootp_packet *)
&pxe_mode->dhcp_ack,
@@ -428,6 +440,7 @@
vlan_dp = (grub_efi_device_path_t *) ((grub_efi_uint8_t *) vlan_dp + vlan_dp_len);
}
}
+ }
return;
}
}
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -1523,14 +1523,67 @@
typedef grub_uint8_t grub_efi_pxe_packet_t[1472];
+typedef struct {
+ grub_uint8_t addr[4];
+} grub_efi_pxe_ipv4_address_t;
+
+typedef struct {
+ grub_uint8_t addr[16];
+} grub_efi_pxe_ipv6_address_t;
+
+typedef struct {
+ grub_uint8_t addr[32];
+} grub_efi_pxe_mac_address_t;
+
+typedef union {
+ grub_uint32_t addr[4];
+ grub_efi_pxe_ipv4_address_t v4;
+ grub_efi_pxe_ipv6_address_t v6;
+} grub_efi_pxe_ip_address_t;
+
+#define GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT 8
+typedef struct {
+ grub_uint8_t filters;
+ grub_uint8_t ip_cnt;
+ grub_uint16_t reserved;
+ grub_efi_pxe_ip_address_t ip_list[GRUB_EFI_PXE_BASE_CODE_MAX_IPCNT];
+} grub_efi_pxe_ip_filter_t;
+
+typedef struct {
+ grub_efi_pxe_ip_address_t ip_addr;
+ grub_efi_pxe_mac_address_t mac_addr;
+} grub_efi_pxe_arp_entry_t;
+
+typedef struct {
+ grub_efi_pxe_ip_address_t ip_addr;
+ grub_efi_pxe_ip_address_t subnet_mask;
+ grub_efi_pxe_ip_address_t gw_addr;
+} grub_efi_pxe_route_entry_t;
+
+
+#define GRUB_EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES 8
+#define GRUB_EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES 8
+
typedef struct grub_efi_pxe_mode
{
- grub_uint8_t unused[52];
+ grub_uint8_t started;
+ grub_uint8_t ipv6_available;
+ grub_uint8_t ipv6_supported;
+ grub_uint8_t using_ipv6;
+ grub_uint8_t unused[16];
+ grub_efi_pxe_ip_address_t station_ip;
+ grub_efi_pxe_ip_address_t subnet_mask;
grub_efi_pxe_packet_t dhcp_discover;
grub_efi_pxe_packet_t dhcp_ack;
grub_efi_pxe_packet_t proxy_offer;
grub_efi_pxe_packet_t pxe_discover;
grub_efi_pxe_packet_t pxe_reply;
+ grub_efi_pxe_packet_t pxe_bis_reply;
+ grub_efi_pxe_ip_filter_t ip_filter;
+ grub_uint32_t arp_cache_entries;
+ grub_efi_pxe_arp_entry_t arp_cache[GRUB_EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES];
+ grub_uint32_t route_table_entries;
+ grub_efi_pxe_route_entry_t route_table[GRUB_EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES];
} grub_efi_pxe_mode_t;
typedef struct grub_efi_pxe

View File

@ -0,0 +1,51 @@
From 7a5a116739fa6d8a625da7d6b9272c9a2462f967 Mon Sep 17 00:00:00 2001
From: Maxim Suhanov <dfirblog@gmail.com>
Date: Mon, 28 Aug 2023 16:33:44 +0300
Subject: [PATCH 4/6] fs/ntfs: Fix an OOB read when parsing bitmaps for index
attributes
This fix introduces checks to ensure that bitmaps for directory indices
are never read beyond their actual sizes.
The lack of this check is a minor issue, likely not exploitable in any way.
Reported-by: Maxim Suhanov <dfirblog@gmail.com>
Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/ntfs.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
index 2d78b96e1..bb70c89fb 100644
--- a/grub-core/fs/ntfs.c
+++ b/grub-core/fs/ntfs.c
@@ -843,6 +843,25 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
if (is_resident)
{
+ if (bitmap_len > (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
+ {
+ grub_error (GRUB_ERR_BAD_FS, "resident bitmap too large");
+ goto done;
+ }
+
+ if (cur_pos >= at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
+ {
+ grub_error (GRUB_ERR_BAD_FS, "resident bitmap out of range");
+ goto done;
+ }
+
+ if (u16at (cur_pos, 0x14) + u32at (cur_pos, 0x10) >
+ (grub_addr_t) at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR) - (grub_addr_t) cur_pos)
+ {
+ grub_error (GRUB_ERR_BAD_FS, "resident bitmap out of range");
+ goto done;
+ }
+
grub_memcpy (bmp, cur_pos + u16at (cur_pos, 0x14),
bitmap_len);
}
--
2.42.0

View File

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

View File

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

View File

@ -0,0 +1,59 @@
From f7b9580133cf346d77f345d175fa5cb8a591be16 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <dja@axtens.net>
Date: Sat, 15 Aug 2020 02:00:57 +1000
Subject: [PATCH 05/23] docs/grub: Document signing grub under UEFI
Before adding information about how grub is signed with an appended
signature scheme, it's worth adding some information about how it
can currently be signed for UEFI.
Signed-off-by: Daniel Axtens <dja@axtens.net>
---
docs/grub.texi | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -6345,6 +6345,7 @@
* Secure Boot Advanced Targeting:: Embedded information for generation number based revocation
* Measured Boot:: Measuring boot components
* Lockdown:: Lockdown when booting on a secure setup
+* Signing GRUB itself:: Ensuring the integrity of the GRUB core image
@end menu
@node Authentication and authorisation
@@ -6423,7 +6424,7 @@
GRUB's @file{core.img} can optionally provide enforcement that all files
subsequently read from disk are covered by a valid digital signature.
-This document does @strong{not} cover how to ensure that your
+This section does @strong{not} cover how to ensure that your
platform's firmware (e.g., Coreboot) validates @file{core.img}.
If environment variable @code{check_signatures}
@@ -6586,6 +6587,25 @@
The @samp{lockdown} variable is set to @samp{y} when the GRUB is locked down.
Otherwise it does not exit.
+@node Signing GRUB itself
+@section Signing GRUB itself
+
+To ensure a complete secure-boot chain, there must be a way for the code that
+loads GRUB to verify the integrity of the core image.
+
+This is ultimately platform-specific and individual platforms can define their
+own mechanisms. However, there are general-purpose mechanisms that can be used
+with GRUB.
+
+@section Signing GRUB for UEFI secure boot
+
+On UEFI platforms, @file{core.img} is a PE binary. Therefore, it can be signed
+with a tool such as @command{pesign} or @command{sbsign}. Refer to the
+suggestions in @pxref{UEFI secure boot and shim} to ensure that the final
+image works under UEFI secure boot and can maintain the secure-boot chain. It
+will also be necessary to enrol the public key used into a relevant firmware
+key database.
+
@node Platform limitations
@chapter Platform limitations

View File

@ -0,0 +1,164 @@
From 496b6b20cbce3fc27228d1d8290089fb7107b8de Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 18 Feb 2022 21:51:16 +0800
Subject: [PATCH 5/5] export environment at start up
If the prep_loadenv module is built into the core image, it will read
the environment block automatically during start up and export all
variables. The will ease integration with those without early scripts to
running the command.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/Makefile.core.def | 2 +
grub-core/commands/prep_loadenv.c | 77 +++++++++++++++++++++++++++++++
grub-core/kern/env.c | 2 +
grub-core/kern/main.c | 3 ++
include/grub/env.h | 1 +
5 files changed, 85 insertions(+)
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2678,4 +2678,6 @@
name = prep_loadenv;
common = commands/prep_loadenv.c;
enable = powerpc_ieee1275;
+ cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)';
+ cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)';
};
--- a/grub-core/commands/prep_loadenv.c
+++ b/grub-core/commands/prep_loadenv.c
@@ -10,6 +10,7 @@
#include <grub/extcmd.h>
#include <grub/i18n.h>
#include <grub/gpt_partition.h>
+#include <regex.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -185,6 +186,65 @@
}
static grub_err_t
+boot_disk_prep_partname (char **name)
+{
+ regex_t regex;
+ int ret;
+ grub_size_t s;
+ char *comperr;
+ const char *cmdpath;
+ regmatch_t *matches = NULL;
+ grub_err_t err = GRUB_ERR_NONE;
+
+ *name = NULL;
+
+ cmdpath = grub_env_get ("cmdpath");
+ if (!cmdpath)
+ return GRUB_ERR_NONE;
+
+ ret = regcomp (&regex, "\\(([^,]+)(,?.*)?\\)(.*)", REG_EXTENDED);
+ if (ret)
+ goto fail;
+
+ matches = grub_calloc (regex.re_nsub + 1, sizeof (*matches));
+ if (! matches)
+ goto fail;
+
+ ret = regexec (&regex, cmdpath, regex.re_nsub + 1, matches, 0);
+ if (!ret)
+ {
+ char *devname = devname = match_substr (matches + 1, cmdpath);
+ if (!devname)
+ {
+ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "%s contains no disk name", cmdpath);
+ goto out;
+ }
+
+ err = prep_partname (devname, name);
+ out:
+ grub_free (devname);
+ regfree (&regex);
+ grub_free (matches);
+ return err;
+ }
+
+ fail:
+ grub_free (matches);
+ s = regerror (ret, &regex, 0, 0);
+ comperr = grub_malloc (s);
+ if (!comperr)
+ {
+ regfree (&regex);
+ return grub_errno;
+ }
+ regerror (ret, &regex, comperr, s);
+ err = grub_error (GRUB_ERR_TEST_FAILURE, "%s", comperr);
+ regfree (&regex);
+ grub_free (comperr);
+ return err;
+}
+
+static grub_err_t
grub_cmd_prep_loadenv (grub_command_t cmd __attribute__ ((unused)),
int argc,
char **argv)
@@ -214,10 +274,27 @@
return GRUB_ERR_NONE;
}
+static void
+early_prep_loadenv (void)
+{
+ grub_err_t err;
+ char *prep;
+
+ err = boot_disk_prep_partname (&prep);
+ if (err == GRUB_ERR_NONE && prep)
+ err = prep_read_envblk (prep);
+ if (err == GRUB_ERR_BAD_FILE_TYPE || err == GRUB_ERR_FILE_NOT_FOUND)
+ grub_error_pop ();
+ if (err != GRUB_ERR_NONE)
+ grub_print_error ();
+ grub_free (prep);
+}
+
static grub_command_t cmd_prep_load;
GRUB_MOD_INIT(prep_loadenv)
{
+ early_env_hook = early_prep_loadenv;
cmd_prep_load =
grub_register_command("prep_load_env", grub_cmd_prep_loadenv,
"DEVICE",
--- a/grub-core/kern/env.c
+++ b/grub-core/kern/env.c
@@ -28,6 +28,8 @@
/* The current context. */
struct grub_env_context *grub_current_context = &initial_context;
+void (*early_env_hook) (void) = NULL;
+
/* Return the hash representation of the string S. */
static unsigned int
grub_env_hashval (const char *s)
--- a/grub-core/kern/main.c
+++ b/grub-core/kern/main.c
@@ -309,6 +309,9 @@
grub_boot_time ("Before execution of embedded config.");
+ if (early_env_hook != NULL)
+ early_env_hook ();
+
if (load_config)
grub_parser_execute (load_config);
--- a/include/grub/env.h
+++ b/include/grub/env.h
@@ -69,5 +69,6 @@
grub_err_t
grub_env_extractor_close (int source);
+extern void (*EXPORT_VAR (early_env_hook)) (void);
#endif /* ! GRUB_ENV_HEADER */

View File

@ -0,0 +1,61 @@
From 1fe82c41e070385e273d7bb1cfb482627a3c28e8 Mon Sep 17 00:00:00 2001
From: Maxim Suhanov <dfirblog@gmail.com>
Date: Mon, 28 Aug 2023 16:38:19 +0300
Subject: [PATCH 5/6] fs/ntfs: Fix an OOB read when parsing a volume label
This fix introduces checks to ensure that an NTFS volume label is always
read from the corresponding file record segment.
The current NTFS code allows the volume label string to be read from an
arbitrary, attacker-chosen memory location. However, the bytes read are
always treated as UTF-16LE. So, the final string displayed is mostly
unreadable and it can't be easily converted back to raw bytes.
The lack of this check is a minor issue, likely not causing a significant
data leak.
Reported-by: Maxim Suhanov <dfirblog@gmail.com>
Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/ntfs.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
index bb70c89fb..ff5e3740f 100644
--- a/grub-core/fs/ntfs.c
+++ b/grub-core/fs/ntfs.c
@@ -1213,13 +1213,29 @@ grub_ntfs_label (grub_device_t device, char **label)
init_attr (&mft->attr, mft);
pa = find_attr (&mft->attr, GRUB_NTFS_AT_VOLUME_NAME);
+
+ if (pa >= mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR))
+ {
+ grub_error (GRUB_ERR_BAD_FS, "can\'t parse volume label");
+ goto fail;
+ }
+
+ if (mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR) - pa < 0x16)
+ {
+ grub_error (GRUB_ERR_BAD_FS, "can\'t parse volume label");
+ goto fail;
+ }
+
if ((pa) && (pa[8] == 0) && (u32at (pa, 0x10)))
{
int len;
len = u32at (pa, 0x10) / 2;
pa += u16at (pa, 0x14);
- *label = get_utf8 (pa, len);
+ if (mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR) - pa >= 2 * len)
+ *label = get_utf8 (pa, len);
+ else
+ grub_error (GRUB_ERR_BAD_FS, "can\'t parse volume label");
}
fail:
--
2.42.0

View File

@ -0,0 +1,48 @@
From 2c997c8c058b41d3a59a81f2bf654288b7cdf8f2 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Tue, 5 May 2015 14:19:24 +0800
Subject: [PATCH 5/8] grub.texi: Add net_bootp6 doument
Update grub documentation for net_bootp6 command.
Signed-off-by: Michael Chang <mchang@suse.com>
Signed-off-by: Ken Lin <ken.lin@hpe.com>
---
docs/grub.texi | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -5894,6 +5894,7 @@
* net_add_dns:: Add a DNS server
* net_add_route:: Add routing entry
* net_bootp:: Perform a bootp/DHCP autoconfiguration
+* net_bootp6:: Perform a DHCPv6 autoconfiguration
* net_del_addr:: Remove IP address from interface
* net_del_dns:: Remove a DNS server
* net_del_route:: Remove a route entry
@@ -5951,6 +5952,24 @@
@end deffn
+
+@node net_bootp6
+@subsection net_bootp6
+
+@deffn Command net_bootp6 [@var{card}]
+Perform configuration of @var{card} using DHCPv6 protocol. If no card name is
+specified, try to configure all existing cards. If configuration was
+successful, interface with name @var{card}@samp{:dhcp6} and configured address
+is added to @var{card}.
+
+@table @samp
+@item 1 (Domain Name Server)
+Adds all servers from option value to the list of servers used during name
+resolution.
+@end table
+
+@end deffn
+
@node net_del_addr
@subsection net_del_addr

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,105 @@
From a33acb675fe0d0464637175e4f06176e4c329025 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Fri, 12 Jul 2019 09:53:32 +0200
Subject: [PATCH 05/11] x86-efi: Use bounce buffers for reading to addresses >
4GB
Lots of machines apparently can't DMA correctly above 4GB during UEFI,
so use bounce buffers for the initramfs read.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/loader/i386/efi/linux.c | 52 ++++++++++++++++++++++++++-----
1 file changed, 45 insertions(+), 7 deletions(-)
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
index f3abbd025..d6bed4fb4 100644
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -35,11 +35,16 @@ static grub_dl_t my_mod;
static int loaded;
static void *kernel_mem;
static grub_uint64_t kernel_size;
-static grub_uint8_t *initrd_mem;
+static void *initrd_mem;
static grub_uint32_t handover_offset;
struct linux_kernel_params *params;
static char *linux_cmdline;
+#define MIN(a, b) \
+ ({ typeof (a) _a = (a); \
+ typeof (b) _b = (b); \
+ _a < _b ? _a : _b; })
+
#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12)
static grub_err_t
@@ -68,6 +73,44 @@ grub_linuxefi_unload (void)
return GRUB_ERR_NONE;
}
+#define BOUNCE_BUFFER_MAX 0x10000000ull
+
+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;
+}
+
static grub_err_t
grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
@@ -120,7 +163,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
for (i = 0; i < nfiles; i++)
{
grub_ssize_t cursize = grub_file_size (files[i]);
- if (grub_file_read (files[i], ptr, cursize) != cursize)
+ if (read (files[i], ptr, cursize) != cursize)
{
if (!grub_errno)
grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
@@ -145,11 +188,6 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
return grub_errno;
}
-#define MIN(a, b) \
- ({ typeof (a) _a = (a); \
- typeof (b) _b = (b); \
- _a < _b ? _a : _b; })
-
static grub_err_t
grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
--
2.31.1

View File

@ -0,0 +1,98 @@
From 8191aae462f8b755972a0a801f4adbdd6ecaa66c Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 14 Jul 2016 18:45:14 +0800
Subject: [PATCH 6/8] bootp: Add processing DHCPACK packet from HTTP Boot
The vendor class identifier with the string "HTTPClient" is used to denote the
packet as responding to HTTP boot request. In DHCP4 config, the filename for
HTTP boot is the URL of the boot file while for PXE boot it is the path to the
boot file. As a consequence, the next-server becomes obseleted because the HTTP
URL already contains the server address for the boot file. For DHCP6 config,
there's no difference definition in existing config as dhcp6.bootfile-url can
be used to specify URL for both HTTP and PXE boot file.
This patch adds processing for "HTTPClient" vendor class identifier in DHCPACK
packet by treating it as HTTP format, not as the PXE format.
Signed-off-by: Michael Chang <mchang@suse.com>
Signed-off-by: Ken Lin <ken.lin@hpe.com>
---
grub-core/net/bootp.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++--
include/grub/net.h | 1 +
2 files changed, 66 insertions(+), 2 deletions(-)
--- a/grub-core/net/bootp.c
+++ b/grub-core/net/bootp.c
@@ -352,6 +352,53 @@
if (!inter)
return 0;
+ /* FIXME: Introduce new http flag for better synergy with existing tftp code base */
+ if (size > OFFSET_OF (vendor, bp))
+ {
+ char *cidvar;
+ const char *cid;
+
+ opt = find_dhcp_option (bp, size, GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER, &opt_len);
+ if (opt && opt_len)
+ grub_env_set_net_property (name, "vendor_class_identifier", (const char *) opt, opt_len);
+ cidvar = grub_xasprintf ("net_%s_%s", name, "vendor_class_identifier");
+ cid = grub_env_get (cidvar);
+ grub_free (cidvar);
+
+ if (cid && grub_strcmp (cid, "HTTPClient") == 0)
+ {
+ char *proto, *ip, *pa;
+
+ /* FIXME: Provide better URL function that returns in place pointers
+ * so that we don't have to free them.
+ */
+ if (!dissect_url (bp->boot_file, &proto, &ip, &pa))
+ return inter;
+
+ if (is_def)
+ {
+ grub_net_default_server = grub_strdup (ip);
+ grub_env_set ("net_default_interface", name);
+ grub_env_export ("net_default_interface");
+ }
+ if (device && !*device)
+ {
+ *device = grub_xasprintf ("%s,%s", proto, ip);
+ grub_print_error ();
+ }
+
+ boot_file = pa;
+ boot_file_len = grub_strlen (pa);
+
+ /* FIXME: Don't use malloc buffer here */
+ grub_free (proto);
+ grub_free (ip);
+
+ /* FIXME: NEED TO FREE boot_file */
+ goto boot_file;
+ }
+ }
+
opt = find_dhcp_option (bp, size, GRUB_NET_DHCP_OVERLOAD, &opt_len);
if (opt && opt_len == 1)
overload = *opt;
@@ -428,6 +475,8 @@
}
}
+boot_file:
+
if (boot_file)
{
grub_env_set_net_property (name, "boot_file", boot_file, boot_file_len);
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -530,6 +530,7 @@
GRUB_NET_DHCP_MESSAGE_TYPE = 53,
GRUB_NET_DHCP_SERVER_IDENTIFIER = 54,
GRUB_NET_DHCP_PARAMETER_REQUEST_LIST = 55,
+ GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER = 60,
GRUB_NET_BOOTP_CLIENT_ID = 61,
GRUB_NET_DHCP_TFTP_SERVER_NAME = 66,
GRUB_NET_DHCP_BOOTFILE_NAME = 67,

View File

@ -0,0 +1,66 @@
From ac539a315495792cd75fe8ab1c474f26e0a78852 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <dja@axtens.net>
Date: Sat, 15 Aug 2020 02:19:36 +1000
Subject: [PATCH 06/23] docs/grub: Document signing grub with an appended
signature
Signing grub for firmware that verifies an appended signature is a
bit fiddly. I don't want people to have to figure it out from scratch
so document it here.
Signed-off-by: Daniel Axtens <dja@axtens.net>
---
docs/grub.texi | 42 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -6606,6 +6606,48 @@
will also be necessary to enrol the public key used into a relevant firmware
key database.
+@section Signing GRUB with an appended signature
+
+The @file{core.img} itself can be signed with a Linux kernel module-style
+appended signature.
+
+To support IEEE1275 platforms where the boot image is often loaded directly
+from a disk partition rather than from a file system, the @file{core.img}
+can specify the size and location of the appended signature with an ELF
+note added by @command{grub-install}.
+
+An image can be signed this way using the @command{sign-file} command from
+the Linux kernel:
+
+@example
+@group
+# grub.key is your private key and certificate.der is your public key
+
+# Determine the size of the appended signature. It depends on the signing
+# certificate and the hash algorithm
+touch empty
+sign-file SHA256 grub.key certificate.der empty empty.sig
+SIG_SIZE=`stat -c '%s' empty.sig`
+rm empty empty.sig
+
+# Build a grub image with $SIG_SIZE reserved for the signature
+grub-install --appended-signature-size $SIG_SIZE --modules="..." ...
+
+# Replace the reserved size with a signature:
+# cut off the last $SIG_SIZE bytes with truncate's minus modifier
+truncate -s -$SIG_SIZE /boot/grub/powerpc-ieee1275/core.elf core.elf.unsigned
+# sign the trimmed file with an appended signature, restoring the correct size
+sign-file SHA256 grub.key certificate.der core.elf.unsigned core.elf.signed
+
+# Don't forget to install the signed image as required
+# (e.g. on powerpc-ieee1275, to the PReP partition)
+@end group
+@end example
+
+As with UEFI secure boot, it is necessary to build in the required modules,
+or sign them separately.
+
+
@node Platform limitations
@chapter Platform limitations

View File

@ -0,0 +1,59 @@
From 3741c6807923ae97b0d87e61c59c8de8af544484 Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Thu, 23 Apr 2020 15:06:46 +0200
Subject: [PATCH 6/9] efi: Set image base address before jumping to the PE/COFF
entry point
Upstream GRUB uses the EFI LoadImage() and StartImage() to boot the Linux
kernel. But our custom EFI loader that supports Secure Boot instead uses
the EFI handover protocol (for x86) or jumping directly to the PE/COFF
entry point (for aarch64).
This is done to allow the bootloader to verify the images using the shim
lock protocol to avoid booting untrusted binaries.
Since the bootloader loads the kernel from the boot media instead of using
LoadImage(), it is responsible to set the Loaded Image base address before
booting the kernel.
Otherwise the kernel EFI stub will complain that it was not set correctly
and print the following warning message:
EFI stub: ERROR: FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value
Resolves: rhbz#1825411
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---
grub-core/loader/arm64/efi/linux.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
Index: grub-2.06~rc1/grub-core/loader/arm64/efi/linux.c
===================================================================
--- grub-2.06~rc1.orig/grub-core/loader/arm64/efi/linux.c
+++ grub-2.06~rc1/grub-core/loader/arm64/efi/linux.c
@@ -58,9 +58,24 @@ static grub_err_t
grub_efi_linux_boot (void *kernel_address, grub_off_t offset,
void *kernel_params)
{
+ grub_efi_loaded_image_t *loaded_image = NULL;
handover_func hf;
+ /*
+ * Since the EFI loader is not calling the LoadImage() and StartImage()
+ * services for loading the kernel and booting respectively, it has to
+ * set the Loaded Image base address.
+ */
+ loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
+ if (loaded_image)
+ loaded_image->image_base = kernel_addr;
+ else
+ grub_dprintf ("linux", "Loaded Image base address could not be set\n");
+
+ grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p params: %p\n",
+ kernel_address, (void *)(grub_efi_uintn_t)offset, kernel_params);
hf = (handover_func)((char *)kernel_address + offset);
+ grub_dprintf ("linux", "handover_func() = %p\n", hf);
hf (grub_efi_image_handle, grub_efi_system_table, kernel_params);
return GRUB_ERR_BUG;

View File

@ -0,0 +1,159 @@
From e58b870ff926415e23fc386af41ff81b2f588763 Mon Sep 17 00:00:00 2001
From: Maxim Suhanov <dfirblog@gmail.com>
Date: Mon, 28 Aug 2023 16:40:07 +0300
Subject: [PATCH 6/6] fs/ntfs: Make code more readable
Move some calls used to access NTFS attribute header fields into
functions with human-readable names.
Suggested-by: Daniel Kiper <daniel.kiper@oracle.com>
Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/ntfs.c | 48 +++++++++++++++++++++++++++++++--------------
1 file changed, 33 insertions(+), 15 deletions(-)
diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
index ff5e3740f..de435aa14 100644
--- a/grub-core/fs/ntfs.c
+++ b/grub-core/fs/ntfs.c
@@ -52,6 +52,24 @@ u64at (void *ptr, grub_size_t ofs)
return grub_le_to_cpu64 (grub_get_unaligned64 ((char *) ptr + ofs));
}
+static grub_uint16_t
+first_attr_off (void *mft_buf_ptr)
+{
+ return u16at (mft_buf_ptr, 0x14);
+}
+
+static grub_uint16_t
+res_attr_data_off (void *res_attr_ptr)
+{
+ return u16at (res_attr_ptr, 0x14);
+}
+
+static grub_uint32_t
+res_attr_data_len (void *res_attr_ptr)
+{
+ return u32at (res_attr_ptr, 0x10);
+}
+
grub_ntfscomp_func_t grub_ntfscomp_func;
static grub_err_t
@@ -106,7 +124,7 @@ init_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft)
{
at->mft = mft;
at->flags = (mft == &mft->data->mmft) ? GRUB_NTFS_AF_MMFT : 0;
- at->attr_nxt = mft->buf + u16at (mft->buf, 0x14);
+ at->attr_nxt = mft->buf + first_attr_off (mft->buf);
at->attr_end = at->emft_buf = at->edat_buf = at->sbuf = NULL;
}
@@ -154,7 +172,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
return NULL;
}
- new_pos = &at->emft_buf[u16at (at->emft_buf, 0x14)];
+ new_pos = &at->emft_buf[first_attr_off (at->emft_buf)];
while (*new_pos != 0xFF)
{
if ((*new_pos == *at->attr_cur)
@@ -213,7 +231,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
}
else
{
- at->attr_nxt = at->attr_end + u16at (pa, 0x14);
+ at->attr_nxt = at->attr_end + res_attr_data_off (pa);
at->attr_end = at->attr_end + u32at (pa, 4);
pa_end = at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
}
@@ -399,20 +417,20 @@ read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, grub_uint8_t *dest,
if (pa[8] == 0)
{
- if (ofs + len > u32at (pa, 0x10))
+ if (ofs + len > res_attr_data_len (pa))
return grub_error (GRUB_ERR_BAD_FS, "read out of range");
- if (u32at (pa, 0x10) > (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
+ if (res_attr_data_len (pa) > (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
return grub_error (GRUB_ERR_BAD_FS, "resident attribute too large");
if (pa >= at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
return grub_error (GRUB_ERR_BAD_FS, "resident attribute out of range");
- if (u16at (pa, 0x14) + u32at (pa, 0x10) >
+ if (res_attr_data_off (pa) + res_attr_data_len (pa) >
(grub_addr_t) at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR) - (grub_addr_t) pa)
return grub_error (GRUB_ERR_BAD_FS, "resident attribute out of range");
- grub_memcpy (dest, pa + u16at (pa, 0x14) + ofs, len);
+ grub_memcpy (dest, pa + res_attr_data_off (pa) + ofs, len);
return 0;
}
@@ -556,7 +574,7 @@ init_file (struct grub_ntfs_file *mft, grub_uint64_t mftno)
(unsigned long long) mftno);
if (!pa[8])
- mft->size = u32at (pa, 0x10);
+ mft->size = res_attr_data_len (pa);
else
mft->size = u64at (pa, 0x30);
@@ -805,7 +823,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
(u32at (cur_pos, 0x18) != 0x490024) ||
(u32at (cur_pos, 0x1C) != 0x300033))
continue;
- cur_pos += u16at (cur_pos, 0x14);
+ cur_pos += res_attr_data_off (cur_pos);
if (*cur_pos != 0x30) /* Not filename index */
continue;
break;
@@ -834,7 +852,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
{
int is_resident = (cur_pos[8] == 0);
- bitmap_len = ((is_resident) ? u32at (cur_pos, 0x10) :
+ bitmap_len = ((is_resident) ? res_attr_data_len (cur_pos) :
u32at (cur_pos, 0x28));
bmp = grub_malloc (bitmap_len);
@@ -855,14 +873,14 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
goto done;
}
- if (u16at (cur_pos, 0x14) + u32at (cur_pos, 0x10) >
+ if (res_attr_data_off (cur_pos) + res_attr_data_len (cur_pos) >
(grub_addr_t) at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR) - (grub_addr_t) cur_pos)
{
grub_error (GRUB_ERR_BAD_FS, "resident bitmap out of range");
goto done;
}
- grub_memcpy (bmp, cur_pos + u16at (cur_pos, 0x14),
+ grub_memcpy (bmp, cur_pos + res_attr_data_off (cur_pos),
bitmap_len);
}
else
@@ -1226,12 +1244,12 @@ grub_ntfs_label (grub_device_t device, char **label)
goto fail;
}
- if ((pa) && (pa[8] == 0) && (u32at (pa, 0x10)))
+ if ((pa) && (pa[8] == 0) && (res_attr_data_len (pa)))
{
int len;
- len = u32at (pa, 0x10) / 2;
- pa += u16at (pa, 0x14);
+ len = res_attr_data_len (pa) / 2;
+ pa += res_attr_data_off (pa);
if (mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR) - pa >= 2 * len)
*label = get_utf8 (pa, len);
else
--
2.42.0

View File

@ -0,0 +1,133 @@
From 24b5c0a3788c5c02b72ea61312f5cf8c39429db1 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 13 Sep 2018 14:42:34 -0400
Subject: [PATCH 06/11] x86-efi: Re-arrange grub_cmd_linux() a little bit.
This just helps the next patch be easier to read.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/loader/i386/efi/linux.c | 73 +++++++++++++++++--------------
1 file changed, 40 insertions(+), 33 deletions(-)
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
index d6bed4fb4..096a52eb5 100644
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -227,32 +227,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
- params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS,
- BYTES_TO_PAGES(sizeof(*params)));
- if (!params)
- params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS,
- BYTES_TO_PAGES(sizeof(*params)));
- if (! params)
- {
- grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
- goto fail;
- }
-
- grub_dprintf ("linux", "params = %p\n", params);
-
- grub_memset (params, 0, sizeof(*params));
+ lh = (struct linux_i386_kernel_header *)kernel;
+ grub_dprintf ("linux", "original lh is at %p\n", kernel);
- setup_header_end_offset = *((grub_uint8_t *)kernel + 0x201);
- grub_dprintf ("linux", "copying %lu bytes from %p to %p\n",
- MIN((grub_size_t)0x202+setup_header_end_offset,
- sizeof (*params)) - 0x1f1,
- (grub_uint8_t *)kernel + 0x1f1,
- (grub_uint8_t *)params + 0x1f1);
- grub_memcpy ((grub_uint8_t *)params + 0x1f1,
- (grub_uint8_t *)kernel + 0x1f1,
- MIN((grub_size_t)0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1);
- lh = (struct linux_i386_kernel_header *)params;
- grub_dprintf ("linux", "lh is at %p\n", lh);
grub_dprintf ("linux", "checking lh->boot_flag\n");
if (lh->boot_flag != grub_cpu_to_le16 (0xaa55))
{
@@ -300,6 +277,34 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
}
#endif
+ params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS,
+ BYTES_TO_PAGES(sizeof(*params)));
+ if (!params)
+ params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS,
+ BYTES_TO_PAGES(sizeof(*params)));
+ if (! params)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
+ goto fail;
+ }
+
+ grub_dprintf ("linux", "params = %p\n", params);
+
+ grub_memset (params, 0, sizeof(*params));
+
+ setup_header_end_offset = *((grub_uint8_t *)kernel + 0x201);
+ grub_dprintf ("linux", "copying %" PRIuGRUB_SIZE " bytes from %p to %p\n",
+ MIN((grub_size_t)0x202+setup_header_end_offset,
+ sizeof (*params)) - 0x1f1,
+ (grub_uint8_t *)kernel + 0x1f1,
+ (grub_uint8_t *)params + 0x1f1);
+ grub_memcpy ((grub_uint8_t *)params + 0x1f1,
+ (grub_uint8_t *)kernel + 0x1f1,
+ MIN((grub_size_t)0x202+setup_header_end_offset,sizeof (*params)) - 0x1f1);
+
+ lh = (struct linux_i386_kernel_header *)params;
+ grub_dprintf ("linux", "new lh is at %p\n", lh);
+
grub_dprintf ("linux", "setting up cmdline\n");
linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS,
BYTES_TO_PAGES(lh->cmdline_size + 1));
@@ -324,8 +329,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_dprintf ("linux", "setting lh->cmd_line_ptr\n");
lh->cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline;
- grub_dprintf ("linux", "computing handover offset\n");
handover_offset = lh->handover_offset;
+ grub_dprintf("linux", "handover_offset: %08x\n", handover_offset);
start = (lh->setup_sects + 1) * 512;
@@ -342,24 +347,26 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel"));
goto fail;
}
-
- grub_dprintf ("linux", "kernel_mem = %lx\n", (unsigned long) kernel_mem);
+ grub_dprintf("linux", "kernel_mem = %p\n", kernel_mem);
grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
- loaded=1;
+
+ loaded = 1;
+
grub_dprintf ("linux", "setting lh->code32_start to %p\n", kernel_mem);
lh->code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem;
grub_memcpy (kernel_mem, (char *)kernel + start, filelen - start);
- grub_dprintf ("linux", "setting lh->type_of_loader\n");
lh->type_of_loader = 0x6;
+ grub_dprintf ("linux", "setting lh->type_of_loader = 0x%02x\n",
+ lh->type_of_loader);
- grub_dprintf ("linux", "setting lh->ext_loader_{type,ver}\n");
params->ext_loader_type = 0;
params->ext_loader_ver = 2;
- grub_dprintf("linux", "kernel_mem: %p handover_offset: %08x\n",
- kernel_mem, handover_offset);
+ grub_dprintf ("linux",
+ "setting lh->ext_loader_{type,ver} = {0x%02x,0x%02x}\n",
+ params->ext_loader_type, params->ext_loader_ver);
fail:
--
2.31.1

View File

@ -0,0 +1,43 @@
From 4773f90bdefb72dde55fb5961f7f37b467307016 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <dja@axtens.net>
Date: Thu, 30 Jul 2020 00:13:21 +1000
Subject: [PATCH 07/23] dl: provide a fake grub_dl_set_persistent for the emu
target
Trying to start grub-emu with a module that calls grub_dl_set_persistent
will crash because grub-emu fakes modules and passes NULL to the module
init function.
Provide an empty function for the emu case.
Fixes: ee7808e2197c (dl: Add support for persistent modules)
Signed-off-by: Daniel Axtens <dja@axtens.net>
---
include/grub/dl.h | 11 +++++++++++
1 file changed, 11 insertions(+)
--- a/include/grub/dl.h
+++ b/include/grub/dl.h
@@ -242,11 +242,22 @@
return 0;
}
+#ifdef GRUB_MACHINE_EMU
+/*
+ * Under grub-emu, modules are faked and NULL is passed to GRUB_MOD_INIT.
+ * So we fake this out to avoid a NULL deref.
+ */
+static inline void
+grub_dl_set_persistent (grub_dl_t mod __attribute__((unused)))
+{
+}
+#else
static inline void
grub_dl_set_persistent (grub_dl_t mod)
{
mod->persistent = 1;
}
+#endif
static inline int
grub_dl_is_persistent (grub_dl_t mod)

View File

@ -0,0 +1,387 @@
From 369df8e3006000a4acacc674f5882d8729781811 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Sun, 10 Jul 2016 23:46:31 +0800
Subject: [PATCH 7/8] efinet: Setting network from UEFI device path
The PXE Base Code protocol used to obtain cached PXE DHCPACK packet is no
longer provided for HTTP Boot. Instead, we have to get the HTTP boot
information from the device path nodes defined in following UEFI Specification
sections.
9.3.5.12 IPv4 Device Path
9.3.5.13 IPv6 Device Path
9.3.5.23 Uniform Resource Identifiers (URI) Device Path
This patch basically does:
include/grub/efi/api.h:
Add new structure of Uniform Resource Identifiers (URI) Device Path
grub-core/net/drivers/efi/efinet.c:
Check if PXE Base Code is available, if not it will try to obtain the netboot
information from the device path where the image booted from. The DHCPACK
packet is recoverd from the information in device patch and feed into the same
DHCP packet processing functions to ensure the network interface is setting up
the same way it used to be.
Signed-off-by: Michael Chang <mchang@suse.com>
Signed-off-by: Ken Lin <ken.lin@hpe.com>
---
grub-core/net/drivers/efi/efinet.c | 268 +++++++++++++++++++++++++++++++++++--
include/grub/efi/api.h | 11 ++
2 files changed, 270 insertions(+), 9 deletions(-)
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -23,6 +23,7 @@
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
#include <grub/i18n.h>
+#include <grub/net/netbuff.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -341,6 +342,221 @@
grub_free (handles);
}
+static struct grub_net_buff *
+grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *use_ipv6)
+{
+ grub_efi_uint16_t uri_len;
+ grub_efi_device_path_t *ldp, *ddp;
+ grub_efi_uri_device_path_t *uri_dp;
+ struct grub_net_buff *nb;
+ grub_err_t err;
+
+ ddp = grub_efi_duplicate_device_path (dp);
+ ldp = grub_efi_find_last_device_path (ddp);
+
+ if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
+ || GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)
+ {
+ grub_free (ddp);
+ return NULL;
+ }
+
+ uri_len = GRUB_EFI_DEVICE_PATH_LENGTH (ldp) > 4 ? GRUB_EFI_DEVICE_PATH_LENGTH (ldp) - 4 : 0;
+
+ if (!uri_len)
+ {
+ grub_free (ddp);
+ return NULL;
+ }
+
+ uri_dp = (grub_efi_uri_device_path_t *) ldp;
+
+ ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+ ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+ ldp->length = sizeof (*ldp);
+
+ ldp = grub_efi_find_last_device_path (ddp);
+
+ if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
+ || (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
+ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE))
+ {
+ grub_free (ddp);
+ return NULL;
+ }
+
+ nb = grub_netbuff_alloc (512);
+ if (!nb)
+ return NULL;
+
+ if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE)
+ {
+ grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) ldp;
+ struct grub_net_bootp_packet *bp;
+ grub_uint8_t *ptr;
+
+ bp = (struct grub_net_bootp_packet *) nb->tail;
+ err = grub_netbuff_put (nb, sizeof (*bp) + 4);
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+
+ if (sizeof(bp->boot_file) < uri_len)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ grub_memcpy (bp->boot_file, uri_dp->uri, uri_len);
+ grub_memcpy (&bp->your_ip, ipv4->local_ip_address, sizeof (bp->your_ip));
+ grub_memcpy (&bp->server_ip, ipv4->remote_ip_address, sizeof (bp->server_ip));
+
+ bp->vendor[0] = GRUB_NET_BOOTP_RFC1048_MAGIC_0;
+ bp->vendor[1] = GRUB_NET_BOOTP_RFC1048_MAGIC_1;
+ bp->vendor[2] = GRUB_NET_BOOTP_RFC1048_MAGIC_2;
+ bp->vendor[3] = GRUB_NET_BOOTP_RFC1048_MAGIC_3;
+
+ ptr = nb->tail;
+ err = grub_netbuff_put (nb, sizeof (ipv4->subnet_mask) + 2);
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ *ptr++ = GRUB_NET_BOOTP_NETMASK;
+ *ptr++ = sizeof (ipv4->subnet_mask);
+ grub_memcpy (ptr, ipv4->subnet_mask, sizeof (ipv4->subnet_mask));
+
+ ptr = nb->tail;
+ err = grub_netbuff_put (nb, sizeof (ipv4->gateway_ip_address) + 2);
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ *ptr++ = GRUB_NET_BOOTP_ROUTER;
+ *ptr++ = sizeof (ipv4->gateway_ip_address);
+ grub_memcpy (ptr, ipv4->gateway_ip_address, sizeof (ipv4->gateway_ip_address));
+
+ ptr = nb->tail;
+ err = grub_netbuff_put (nb, sizeof ("HTTPClient") + 1);
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ *ptr++ = GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER;
+ *ptr++ = sizeof ("HTTPClient") - 1;
+ grub_memcpy (ptr, "HTTPClient", sizeof ("HTTPClient") - 1);
+
+ ptr = nb->tail;
+ err = grub_netbuff_put (nb, 1);
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ *ptr = GRUB_NET_BOOTP_END;
+ *use_ipv6 = 0;
+
+ ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+ ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+ ldp->length = sizeof (*ldp);
+ ldp = grub_efi_find_last_device_path (ddp);
+
+ if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE)
+ {
+ grub_efi_mac_address_device_path_t *mac = (grub_efi_mac_address_device_path_t *) ldp;
+ bp->hw_type = mac->if_type;
+ bp->hw_len = sizeof (bp->mac_addr);
+ grub_memcpy (bp->mac_addr, mac->mac_address, bp->hw_len);
+ }
+ }
+ else
+ {
+ grub_efi_ipv6_device_path_t *ipv6 = (grub_efi_ipv6_device_path_t *) ldp;
+
+ struct grub_net_dhcp6_packet *d6p;
+ struct grub_net_dhcp6_option *opt;
+ struct grub_net_dhcp6_option_iana *iana;
+ struct grub_net_dhcp6_option_iaaddr *iaaddr;
+
+ d6p = (struct grub_net_dhcp6_packet *)nb->tail;
+ err = grub_netbuff_put (nb, sizeof(*d6p));
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ d6p->message_type = GRUB_NET_DHCP6_REPLY;
+
+ opt = (struct grub_net_dhcp6_option *)nb->tail;
+ err = grub_netbuff_put (nb, sizeof(*opt));
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IA_NA);
+ opt->len = grub_cpu_to_be16_compile_time (sizeof(*iana) + sizeof(*opt) + sizeof(*iaaddr));
+
+ err = grub_netbuff_put (nb, sizeof(*iana));
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+
+ opt = (struct grub_net_dhcp6_option *)nb->tail;
+ err = grub_netbuff_put (nb, sizeof(*opt));
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_IAADDR);
+ opt->len = grub_cpu_to_be16_compile_time (sizeof (*iaaddr));
+
+ iaaddr = (struct grub_net_dhcp6_option_iaaddr *)nb->tail;
+ err = grub_netbuff_put (nb, sizeof(*iaaddr));
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ grub_memcpy (iaaddr->addr, ipv6->local_ip_address, sizeof(ipv6->local_ip_address));
+
+ opt = (struct grub_net_dhcp6_option *)nb->tail;
+ err = grub_netbuff_put (nb, sizeof(*opt) + uri_len);
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_BOOTFILE_URL);
+ opt->len = grub_cpu_to_be16 (uri_len);
+ grub_memcpy (opt->data, uri_dp->uri, uri_len);
+
+ *use_ipv6 = 1;
+ }
+
+ grub_free (ddp);
+ return nb;
+}
+
static void
grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
char **path)
@@ -361,6 +577,11 @@
grub_efi_device_path_t *cdp;
struct grub_efi_pxe *pxe;
struct grub_efi_pxe_mode *pxe_mode;
+ grub_uint8_t *packet_buf;
+ grub_size_t packet_bufsz ;
+ int ipv6;
+ struct grub_net_buff *nb = NULL;
+
if (card->driver != &efidriver)
continue;
cdp = grub_efi_get_device_path (card->efi_handle);
@@ -380,11 +601,21 @@
ldp = grub_efi_find_last_device_path (dp);
if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
|| (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
- && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE))
+ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE
+ && GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_URI_DEVICE_PATH_SUBTYPE))
continue;
dup_dp = grub_efi_duplicate_device_path (dp);
if (!dup_dp)
continue;
+
+ if (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_URI_DEVICE_PATH_SUBTYPE)
+ {
+ dup_ldp = grub_efi_find_last_device_path (dup_dp);
+ dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+ dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+ dup_ldp->length = sizeof (*dup_ldp);
+ }
+
dup_ldp = grub_efi_find_last_device_path (dup_dp);
dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
@@ -396,16 +627,31 @@
}
pxe = grub_efi_open_protocol (hnd, &pxe_io_guid,
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
- if (! pxe)
- continue;
- pxe_mode = pxe->mode;
+ if (!pxe)
+ {
+ nb = grub_efinet_create_dhcp_ack_from_device_path (dp, &ipv6);
+ if (!nb)
+ {
+ grub_print_error ();
+ continue;
+ }
+ packet_buf = nb->head;
+ packet_bufsz = nb->tail - nb->head;
+ }
+ else
+ {
+ pxe_mode = pxe->mode;
+ packet_buf = (grub_uint8_t *) &pxe_mode->dhcp_ack;
+ packet_bufsz = sizeof (pxe_mode->dhcp_ack);
+ ipv6 = pxe_mode->using_ipv6;
+ }
- if (pxe_mode->using_ipv6)
+ if (ipv6)
{
grub_net_configure_by_dhcpv6_reply (card->name, card, 0,
(struct grub_net_dhcp6_packet *)
- &pxe_mode->dhcp_ack,
- sizeof (pxe_mode->dhcp_ack),
+ packet_buf,
+ packet_bufsz,
1, device, path);
if (grub_errno)
grub_print_error ();
@@ -414,8 +660,8 @@
{
inter = grub_net_configure_by_dhcp_ack (card->name, card, 0,
(struct grub_net_bootp_packet *)
- &pxe_mode->dhcp_ack,
- sizeof (pxe_mode->dhcp_ack),
+ packet_buf,
+ packet_bufsz,
1, device, path);
if (inter != NULL)
@@ -441,6 +687,10 @@
}
}
}
+
+ if (nb)
+ grub_netbuff_free (nb);
+
return;
}
}
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -876,6 +876,8 @@
grub_efi_uint16_t remote_port;
grub_efi_uint16_t protocol;
grub_efi_uint8_t static_ip_address;
+ grub_efi_ipv4_address_t gateway_ip_address;
+ grub_efi_ipv4_address_t subnet_mask;
} GRUB_PACKED;
typedef struct grub_efi_ipv4_device_path grub_efi_ipv4_device_path_t;
@@ -939,6 +941,15 @@
} GRUB_PACKED;
typedef struct grub_efi_vlan_device_path grub_efi_vlan_device_path_t;
+#define GRUB_EFI_URI_DEVICE_PATH_SUBTYPE 24
+
+struct grub_efi_uri_device_path
+{
+ grub_efi_device_path_t header;
+ grub_efi_uint8_t uri[0];
+} GRUB_PACKED;
+typedef struct grub_efi_uri_device_path grub_efi_uri_device_path_t;
+
#define GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE 10
/* Media Device Path. */

View File

@ -0,0 +1,249 @@
From 2a84f1a50c6f8770808fd4ec590eb8cff4228aed Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Wed, 12 Sep 2018 16:03:55 -0400
Subject: [PATCH 07/11] x86-efi: Make our own allocator for kernel stuff
This helps enable allocations above 4GB.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/loader/i386/efi/linux.c | 155 ++++++++++++++++++------------
1 file changed, 94 insertions(+), 61 deletions(-)
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
index 096a52eb5..d284db5d1 100644
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -47,6 +47,65 @@ static char *linux_cmdline;
#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12)
+struct allocation_choice {
+ grub_efi_physical_address_t addr;
+ grub_efi_allocate_type_t alloc_type;
+};
+
+static struct allocation_choice max_addresses[] =
+ {
+ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
+ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
+ { GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
+ { 0, 0 }
+ };
+
+static inline void
+kernel_free(void *addr, grub_efi_uintn_t size)
+{
+ if (addr && size)
+ grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)addr,
+ BYTES_TO_PAGES(size));
+}
+
+static void *
+kernel_alloc(grub_efi_uintn_t size, const char * const errmsg)
+{
+ void *addr = 0;
+ unsigned int i;
+ grub_efi_physical_address_t prev_max = 0;
+
+ for (i = 0; max_addresses[i].addr != 0 && addr == 0; i++)
+ {
+ grub_uint64_t max = max_addresses[i].addr;
+ grub_efi_uintn_t pages;
+
+ if (max == prev_max)
+ continue;
+
+ pages = BYTES_TO_PAGES(size);
+ grub_dprintf ("linux", "Trying to allocate %" PRIuGRUB_SIZE" pages from %p\n",
+ pages, (void *)(grub_addr_t)max);
+
+ prev_max = max;
+ addr = grub_efi_allocate_pages_real (max, pages,
+ max_addresses[i].alloc_type,
+ GRUB_EFI_LOADER_DATA);
+ if (addr)
+ grub_dprintf ("linux", "Allocated at %p\n", addr);
+ }
+
+ while (grub_error_pop ())
+ {
+ ;
+ }
+
+ if (addr == NULL)
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, "%s", errmsg);
+
+ return addr;
+}
+
static grub_err_t
grub_linuxefi_boot (void)
{
@@ -62,14 +121,12 @@ grub_linuxefi_unload (void)
{
grub_dl_unref (my_mod);
loaded = 0;
- if (initrd_mem)
- grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)initrd_mem, BYTES_TO_PAGES(params->ramdisk_size));
- if (linux_cmdline)
- grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)linux_cmdline, BYTES_TO_PAGES(params->cmdline_size + 1));
- if (kernel_mem)
- grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)kernel_mem, BYTES_TO_PAGES(kernel_size));
- if (params)
- grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)params, BYTES_TO_PAGES(16384));
+
+ kernel_free(initrd_mem, params->ramdisk_size);
+ kernel_free(linux_cmdline, params->cmdline_size + 1);
+ kernel_free(kernel_mem, kernel_size);
+ kernel_free(params, sizeof(*params));
+
return GRUB_ERR_NONE;
}
@@ -146,17 +203,13 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
size += ALIGN_UP (grub_file_size (files[i]), 4);
}
- initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS, BYTES_TO_PAGES(size));
- if (!initrd_mem)
- initrd_mem = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS, BYTES_TO_PAGES(size));
- if (!initrd_mem)
- {
- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd"));
- goto fail;
- }
+ initrd_mem = kernel_alloc(size, N_("can't allocate initrd"));
+ if (initrd_mem == NULL)
+ goto fail;
+ grub_dprintf ("linux", "initrd_mem = %p\n", initrd_mem);
params->ramdisk_size = size;
- params->ramdisk_image = (grub_uint32_t)(grub_addr_t) initrd_mem;
+ params->ramdisk_image = initrd_mem;
ptr = initrd_mem;
@@ -214,7 +267,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
filelen = grub_file_size (file);
kernel = grub_malloc(filelen);
-
if (!kernel)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer"));
@@ -258,7 +310,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
-#if defined(__x86_64__) || defined(__aarch64__)
+#if defined(__x86_64__)
grub_dprintf ("linux", "checking lh->xloadflags\n");
if (!(lh->xloadflags & LINUX_XLF_KERNEL_64))
{
@@ -277,17 +329,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
}
#endif
- params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_ALLOCATION_ADDRESS,
- BYTES_TO_PAGES(sizeof(*params)));
+ params = kernel_alloc (sizeof(*params), "cannot allocate kernel parameters");
if (!params)
- params = grub_efi_allocate_pages_max (GRUB_EFI_MAX_USABLE_ADDRESS,
- BYTES_TO_PAGES(sizeof(*params)));
- if (! params)
- {
- grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters");
- goto fail;
- }
-
+ goto fail;
grub_dprintf ("linux", "params = %p\n", params);
grub_memset (params, 0, sizeof(*params));
@@ -306,16 +350,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_dprintf ("linux", "new lh is at %p\n", lh);
grub_dprintf ("linux", "setting up cmdline\n");
- linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS,
- BYTES_TO_PAGES(lh->cmdline_size + 1));
+ linux_cmdline = kernel_alloc (lh->cmdline_size + 1, N_("can't allocate cmdline"));
if (!linux_cmdline)
- linux_cmdline = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS,
- BYTES_TO_PAGES(lh->cmdline_size + 1));
- if (!linux_cmdline)
- {
- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline"));
- goto fail;
- }
+ goto fail;
+ grub_dprintf ("linux", "linux_cmdline = %p\n", linux_cmdline);
grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
err = grub_create_loader_cmdline (argc, argv,
@@ -326,27 +364,24 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
grub_dprintf ("linux", "cmdline:%s\n", linux_cmdline);
- grub_dprintf ("linux", "setting lh->cmd_line_ptr\n");
- lh->cmd_line_ptr = (grub_uint32_t)(grub_addr_t)linux_cmdline;
+ grub_dprintf ("linux", "setting lh->cmd_line_ptr to 0x%08x\n",
+ linux_cmdline);
+ lh->cmd_line_ptr = linux_cmdline;
handover_offset = lh->handover_offset;
- grub_dprintf("linux", "handover_offset: %08x\n", handover_offset);
+ grub_dprintf("linux", "handover_offset: 0x%08x\n", handover_offset);
start = (lh->setup_sects + 1) * 512;
- kernel_mem = grub_efi_allocate_pages_max(lh->pref_address,
- BYTES_TO_PAGES(lh->init_size));
- if (!kernel_mem)
- kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_ALLOCATION_ADDRESS,
- BYTES_TO_PAGES(lh->init_size));
- if (!kernel_mem)
- kernel_mem = grub_efi_allocate_pages_max(GRUB_EFI_MAX_USABLE_ADDRESS,
- BYTES_TO_PAGES(lh->init_size));
- if (!kernel_mem)
+ grub_dprintf ("linux", "lh->pref_address: %p\n", (void *)(grub_addr_t)lh->pref_address);
+ if (lh->pref_address < (grub_uint64_t)GRUB_EFI_MAX_ALLOCATION_ADDRESS)
{
- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel"));
- goto fail;
+ max_addresses[0].addr = lh->pref_address;
+ max_addresses[0].alloc_type = GRUB_EFI_ALLOCATE_ADDRESS;
}
+ kernel_mem = kernel_alloc (lh->init_size, N_("can't allocate kernel"));
+ if (!kernel_mem)
+ goto fail;
grub_dprintf("linux", "kernel_mem = %p\n", kernel_mem);
grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
@@ -382,16 +417,14 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
loaded = 0;
}
- if (linux_cmdline && lh && !loaded)
- grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)
- linux_cmdline,
- BYTES_TO_PAGES(lh->cmdline_size + 1));
-
- if (kernel_mem && !loaded)
- grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)kernel_mem, BYTES_TO_PAGES(kernel_size));
+ if (!loaded)
+ {
+ if (lh)
+ kernel_free (linux_cmdline, lh->cmdline_size + 1);
- if (params && !loaded)
- grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)params, BYTES_TO_PAGES(16384));
+ kernel_free (kernel_mem, kernel_size);
+ kernel_free (params, sizeof(*params));
+ }
return grub_errno;
}
--
2.31.1

View File

@ -0,0 +1,331 @@
From 0c7ae6d7527d08e54a6eeebddb6c5c697c4b37d2 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 14 Jul 2016 17:48:45 +0800
Subject: [PATCH 8/8] efinet: Setting DNS server from UEFI protocol
In the URI device path node, any name rahter than address can be used for
looking up the resources so that DNS service become needed to get answer of the
name's address. Unfortunately the DNS is not defined in any of the device path
nodes so that we use the EFI_IP4_CONFIG2_PROTOCOL and EFI_IP6_CONFIG_PROTOCOL
to obtain it.
These two protcols are defined the sections of UEFI specification.
27.5 EFI IPv4 Configuration II Protocol
27.7 EFI IPv6 Configuration Protocol
include/grub/efi/api.h:
Add new structure and protocol UUID of EFI_IP4_CONFIG2_PROTOCOL and
EFI_IP6_CONFIG_PROTOCOL.
grub-core/net/drivers/efi/efinet.c:
Use the EFI_IP4_CONFIG2_PROTOCOL and EFI_IP6_CONFIG_PROTOCOL to obtain the list
of DNS server address for IPv4 and IPv6 respectively. The address of DNS
servers is structured into DHCPACK packet and feed into the same DHCP packet
processing functions to ensure the network interface is setting up the same way
it used to be.
Signed-off-by: Michael Chang <mchang@suse.com>
Signed-off-by: Ken Lin <ken.lin@hpe.com>
---
grub-core/net/drivers/efi/efinet.c | 163 +++++++++++++++++++++++++++++++++++++
include/grub/efi/api.h | 76 +++++++++++++++++
2 files changed, 239 insertions(+)
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -30,6 +30,8 @@
/* GUID. */
static grub_guid_t net_io_guid = GRUB_EFI_SIMPLE_NETWORK_GUID;
static grub_guid_t pxe_io_guid = GRUB_EFI_PXE_GUID;
+static grub_guid_t ip4_config_guid = GRUB_EFI_IP4_CONFIG2_PROTOCOL_GUID;
+static grub_guid_t ip6_config_guid = GRUB_EFI_IP6_CONFIG_PROTOCOL_GUID;
static grub_err_t
send_card_buffer (struct grub_net_card *dev,
@@ -342,6 +344,125 @@
grub_free (handles);
}
+static grub_efi_handle_t
+grub_efi_locate_device_path (grub_efi_guid_t *protocol, grub_efi_device_path_t *device_path,
+ grub_efi_device_path_t **r_device_path)
+{
+ grub_efi_handle_t handle;
+ grub_efi_status_t status;
+
+ status = grub_efi_system_table->boot_services->locate_device_path (
+ protocol, &device_path, &handle);
+
+ if (status != GRUB_EFI_SUCCESS)
+ return 0;
+
+ if (r_device_path)
+ *r_device_path = device_path;
+
+ return handle;
+}
+
+static grub_efi_ipv4_address_t *
+grub_dns_server_ip4_address (grub_efi_device_path_t *dp, grub_efi_uintn_t *num_dns)
+{
+ grub_efi_handle_t hnd;
+ grub_efi_status_t status;
+ grub_efi_ip4_config2_protocol_t *conf;
+ grub_efi_ipv4_address_t *addrs;
+ grub_efi_uintn_t data_size = 1 * sizeof (grub_efi_ipv4_address_t);
+
+ hnd = grub_efi_locate_device_path (&ip4_config_guid, dp, NULL);
+
+ if (!hnd)
+ return 0;
+
+ conf = grub_efi_open_protocol (hnd, &ip4_config_guid,
+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ if (!conf)
+ return 0;
+
+ addrs = grub_malloc (data_size);
+ if (!addrs)
+ return 0;
+
+ status = conf->get_data (conf,
+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER,
+ &data_size, addrs);
+
+ if (status == GRUB_EFI_BUFFER_TOO_SMALL)
+ {
+ grub_free (addrs);
+ addrs = grub_malloc (data_size);
+ if (!addrs)
+ return 0;
+
+ status = conf->get_data (conf,
+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER,
+ &data_size, addrs);
+ }
+
+ if (status != GRUB_EFI_SUCCESS)
+ {
+ grub_free (addrs);
+ return 0;
+ }
+
+ *num_dns = data_size / sizeof (grub_efi_ipv4_address_t);
+ return addrs;
+}
+
+static grub_efi_ipv6_address_t *
+grub_dns_server_ip6_address (grub_efi_device_path_t *dp, grub_efi_uintn_t *num_dns)
+{
+ grub_efi_handle_t hnd;
+ grub_efi_status_t status;
+ grub_efi_ip6_config_protocol_t *conf;
+ grub_efi_ipv6_address_t *addrs;
+ grub_efi_uintn_t data_size = 1 * sizeof (grub_efi_ipv6_address_t);
+
+ hnd = grub_efi_locate_device_path (&ip6_config_guid, dp, NULL);
+
+ if (!hnd)
+ return 0;
+
+ conf = grub_efi_open_protocol (hnd, &ip6_config_guid,
+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ if (!conf)
+ return 0;
+
+ addrs = grub_malloc (data_size);
+ if (!addrs)
+ return 0;
+
+ status = conf->get_data (conf,
+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER,
+ &data_size, addrs);
+
+ if (status == GRUB_EFI_BUFFER_TOO_SMALL)
+ {
+ grub_free (addrs);
+ addrs = grub_malloc (data_size);
+ if (!addrs)
+ return 0;
+
+ status = conf->get_data (conf,
+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER,
+ &data_size, addrs);
+ }
+
+ if (status != GRUB_EFI_SUCCESS)
+ {
+ grub_free (addrs);
+ return 0;
+ }
+
+ *num_dns = data_size / sizeof (grub_efi_ipv6_address_t);
+ return addrs;
+}
+
static struct grub_net_buff *
grub_efinet_create_dhcp_ack_from_device_path (grub_efi_device_path_t *dp, int *use_ipv6)
{
@@ -394,6 +515,8 @@
grub_efi_ipv4_device_path_t *ipv4 = (grub_efi_ipv4_device_path_t *) ldp;
struct grub_net_bootp_packet *bp;
grub_uint8_t *ptr;
+ grub_efi_ipv4_address_t *dns;
+ grub_efi_uintn_t num_dns;
bp = (struct grub_net_bootp_packet *) nb->tail;
err = grub_netbuff_put (nb, sizeof (*bp) + 4);
@@ -455,6 +578,25 @@
*ptr++ = sizeof ("HTTPClient") - 1;
grub_memcpy (ptr, "HTTPClient", sizeof ("HTTPClient") - 1);
+ dns = grub_dns_server_ip4_address (dp, &num_dns);
+ if (dns)
+ {
+ grub_efi_uintn_t size_dns = sizeof (*dns) * num_dns;
+
+ ptr = nb->tail;
+ err = grub_netbuff_put (nb, size_dns + 2);
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ *ptr++ = GRUB_NET_BOOTP_DNS;
+ *ptr++ = size_dns;
+ grub_memcpy (ptr, dns, size_dns);
+ grub_free (dns);
+ }
+
ptr = nb->tail;
err = grub_netbuff_put (nb, 1);
if (err)
@@ -487,6 +629,8 @@
struct grub_net_dhcp6_option *opt;
struct grub_net_dhcp6_option_iana *iana;
struct grub_net_dhcp6_option_iaaddr *iaaddr;
+ grub_efi_ipv6_address_t *dns;
+ grub_efi_uintn_t num_dns;
d6p = (struct grub_net_dhcp6_packet *)nb->tail;
err = grub_netbuff_put (nb, sizeof(*d6p));
@@ -550,6 +694,25 @@
opt->len = grub_cpu_to_be16 (uri_len);
grub_memcpy (opt->data, uri_dp->uri, uri_len);
+ dns = grub_dns_server_ip6_address (dp, &num_dns);
+ if (dns)
+ {
+ grub_efi_uintn_t size_dns = sizeof (*dns) * num_dns;
+
+ opt = (struct grub_net_dhcp6_option *)nb->tail;
+ err = grub_netbuff_put (nb, sizeof(*opt) + size_dns);
+ if (err)
+ {
+ grub_free (ddp);
+ grub_netbuff_free (nb);
+ return NULL;
+ }
+ opt->code = grub_cpu_to_be16_compile_time (GRUB_NET_DHCP6_OPTION_DNS_SERVERS);
+ opt->len = grub_cpu_to_be16 (size_dns);
+ grub_memcpy (opt->data, dns, size_dns);
+ grub_free (dns);
+ }
+
*use_ipv6 = 1;
}
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -379,6 +379,16 @@
{0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f } \
}
+#define GRUB_EFI_IP4_CONFIG2_PROTOCOL_GUID \
+ { 0x5b446ed1, 0xe30b, 0x4faa, \
+ { 0x87, 0x1a, 0x36, 0x54, 0xec, 0xa3, 0x60, 0x80 } \
+ }
+
+#define GRUB_EFI_IP6_CONFIG_PROTOCOL_GUID \
+ { 0x937fe521, 0x95ae, 0x4d1a, \
+ { 0x89, 0x29, 0x48, 0xbc, 0xd9, 0x0a, 0xd3, 0x1a } \
+ }
+
struct grub_efi_sal_system_table
{
grub_uint32_t signature;
@@ -1879,4 +1889,70 @@
} GRUB_PACKED;
typedef struct initrd_media_device_path initrd_media_device_path_t;
+enum grub_efi_ip4_config2_data_type {
+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_INTERFACEINFO,
+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_POLICY,
+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS,
+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_GATEWAY,
+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_DNSSERVER,
+ GRUB_EFI_IP4_CONFIG2_DATA_TYPE_MAXIMUM
+};
+typedef enum grub_efi_ip4_config2_data_type grub_efi_ip4_config2_data_type_t;
+
+struct grub_efi_ip4_config2_protocol
+{
+ grub_efi_status_t (__grub_efi_api *set_data) (struct grub_efi_ip4_config2_protocol *this,
+ grub_efi_ip4_config2_data_type_t data_type,
+ grub_efi_uintn_t data_size,
+ void *data);
+
+ grub_efi_status_t (__grub_efi_api *get_data) (struct grub_efi_ip4_config2_protocol *this,
+ grub_efi_ip4_config2_data_type_t data_type,
+ grub_efi_uintn_t *data_size,
+ void *data);
+
+ grub_efi_status_t (__grub_efi_api *register_data_notify) (struct grub_efi_ip4_config2_protocol *this,
+ grub_efi_ip4_config2_data_type_t data_type,
+ grub_efi_event_t event);
+
+ grub_efi_status_t (__grub_efi_api *unregister_datanotify) (struct grub_efi_ip4_config2_protocol *this,
+ grub_efi_ip4_config2_data_type_t data_type,
+ grub_efi_event_t event);
+};
+typedef struct grub_efi_ip4_config2_protocol grub_efi_ip4_config2_protocol_t;
+
+enum grub_efi_ip6_config_data_type {
+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_INTERFACEINFO,
+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_ALT_INTERFACEID,
+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_POLICY,
+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DUP_ADDR_DETECT_TRANSMITS,
+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_MANUAL_ADDRESS,
+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_GATEWAY,
+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_DNSSERVER,
+ GRUB_EFI_IP6_CONFIG_DATA_TYPE_MAXIMUM
+};
+typedef enum grub_efi_ip6_config_data_type grub_efi_ip6_config_data_type_t;
+
+struct grub_efi_ip6_config_protocol
+{
+ grub_efi_status_t (__grub_efi_api *set_data) (struct grub_efi_ip6_config_protocol *this,
+ grub_efi_ip6_config_data_type_t data_type,
+ grub_efi_uintn_t data_size,
+ void *data);
+
+ grub_efi_status_t (__grub_efi_api *get_data) (struct grub_efi_ip6_config_protocol *this,
+ grub_efi_ip6_config_data_type_t data_type,
+ grub_efi_uintn_t *data_size,
+ void *data);
+
+ grub_efi_status_t (__grub_efi_api *register_data_notify) (struct grub_efi_ip6_config_protocol *this,
+ grub_efi_ip6_config_data_type_t data_type,
+ grub_efi_event_t event);
+
+ grub_efi_status_t (__grub_efi_api *unregister_datanotify) (struct grub_efi_ip6_config_protocol *this,
+ grub_efi_ip6_config_data_type_t data_type,
+ grub_efi_event_t event);
+};
+typedef struct grub_efi_ip6_config_protocol grub_efi_ip6_config_protocol_t;
+
#endif /* ! GRUB_EFI_API_HEADER */

View File

@ -0,0 +1,151 @@
From adf486860fe0d395579be8b01d4fda8b93377768 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
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 <mchang@suse.com>
---
grub-core/loader/i386/efi/linux.c | 87 ++++---------------------------
1 file changed, 10 insertions(+), 77 deletions(-)
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -30,6 +30,7 @@
#include <grub/cpu/efi/memory.h>
#include <grub/tpm.h>
#include <grub/safemath.h>
+#include <grub/linux.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -146,44 +147,6 @@
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 @@
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 @@
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 @@
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, 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));

View File

@ -0,0 +1,181 @@
From 923c8f6807cbd93b72d4dcb16c213d0d2a6b5b9a Mon Sep 17 00:00:00 2001
From: Daniel Axtens <dja@axtens.net>
Date: Thu, 1 Oct 2020 20:23:48 +1000
Subject: [PATCH 08/23] pgp: factor out rsa_pad
rsa_pad does the PKCS#1 v1.5 padding for the RSA signature scheme.
We want to use it in other RSA signature verification applications.
I considered and rejected putting it in lib/crypto.c. That file doesn't
currently require any MPI functions, but rsa_pad does. That's not so
much of a problem for the grub kernel and modules, but crypto.c also
gets built into all the grub utilities. So - despite the utils not
using any asymmetric ciphers - we would need to built the entire MPI
infrastructure in to them.
A better and simpler solution is just to spin rsa_pad out into its own
PKCS#1 v1.5 module.
Signed-off-by: Daniel Axtens <dja@axtens.net>
---
grub-core/Makefile.core.def | 8 +++++
grub-core/commands/pgp.c | 28 ++----------------
grub-core/lib/pkcs1_v15.c | 59 +++++++++++++++++++++++++++++++++++++
include/grub/pkcs1_v15.h | 27 +++++++++++++++++
4 files changed, 96 insertions(+), 26 deletions(-)
create mode 100644 grub-core/lib/pkcs1_v15.c
create mode 100644 include/grub/pkcs1_v15.h
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2542,6 +2542,14 @@
};
module = {
+ name = pkcs1_v15;
+ common = lib/pkcs1_v15.c;
+
+ cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare';
+ cppflags = '$(CPPFLAGS_GCRY)';
+};
+
+module = {
name = all_video;
common = lib/fake_module.c;
};
--- a/grub-core/commands/pgp.c
+++ b/grub-core/commands/pgp.c
@@ -24,6 +24,7 @@
#include <grub/file.h>
#include <grub/command.h>
#include <grub/crypto.h>
+#include <grub/pkcs1_v15.h>
#include <grub/i18n.h>
#include <grub/gcrypt/gcrypt.h>
#include <grub/pubkey.h>
@@ -411,32 +412,7 @@
rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval,
const gcry_md_spec_t *hash, struct grub_public_subkey *sk)
{
- grub_size_t tlen, emlen, fflen;
- grub_uint8_t *em, *emptr;
- unsigned nbits = gcry_mpi_get_nbits (sk->mpis[0]);
- int ret;
- tlen = hash->mdlen + hash->asnlen;
- emlen = (nbits + 7) / 8;
- if (emlen < tlen + 11)
- return 1;
-
- em = grub_malloc (emlen);
- if (!em)
- return 1;
-
- em[0] = 0x00;
- em[1] = 0x01;
- fflen = emlen - tlen - 3;
- for (emptr = em + 2; emptr < em + 2 + fflen; emptr++)
- *emptr = 0xff;
- *emptr++ = 0x00;
- grub_memcpy (emptr, hash->asnoid, hash->asnlen);
- emptr += hash->asnlen;
- grub_memcpy (emptr, hval, hash->mdlen);
-
- ret = gcry_mpi_scan (hmpi, GCRYMPI_FMT_USG, em, emlen, 0);
- grub_free (em);
- return ret;
+ return grub_crypto_rsa_pad(hmpi, hval, hash, sk->mpis[0]);
}
struct grub_pubkey_context
--- /dev/null
+++ b/grub-core/lib/pkcs1_v15.c
@@ -0,0 +1,59 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/gcrypt/gcrypt.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+/*
+ * Given a hash value 'hval', of hash specification 'hash', perform
+ * the EMSA-PKCS1-v1_5 padding suitable for a key with modulus 'mod'
+ * (see RFC 8017 s 9.2) and place the result in 'hmpi'.
+ */
+gcry_err_code_t
+grub_crypto_rsa_pad (gcry_mpi_t * hmpi, grub_uint8_t * hval,
+ const gcry_md_spec_t * hash, gcry_mpi_t mod)
+{
+ grub_size_t tlen, emlen, fflen;
+ grub_uint8_t *em, *emptr;
+ unsigned nbits = gcry_mpi_get_nbits (mod);
+ int ret;
+ tlen = hash->mdlen + hash->asnlen;
+ emlen = (nbits + 7) / 8;
+ if (emlen < tlen + 11)
+ return GPG_ERR_TOO_SHORT;
+
+ em = grub_malloc (emlen);
+ if (!em)
+ return 1;
+
+ em[0] = 0x00;
+ em[1] = 0x01;
+ fflen = emlen - tlen - 3;
+ for (emptr = em + 2; emptr < em + 2 + fflen; emptr++)
+ *emptr = 0xff;
+ *emptr++ = 0x00;
+ grub_memcpy (emptr, hash->asnoid, hash->asnlen);
+ emptr += hash->asnlen;
+ grub_memcpy (emptr, hval, hash->mdlen);
+
+ ret = gcry_mpi_scan (hmpi, GCRYMPI_FMT_USG, em, emlen, 0);
+ grub_free (em);
+ return ret;
+}
--- /dev/null
+++ b/include/grub/pkcs1_v15.h
@@ -0,0 +1,27 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2013 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Given a hash value 'hval', of hash specification 'hash', perform
+ * the EMSA-PKCS1-v1_5 padding suitable for a key with modulus 'mod'
+ * (See RFC 8017 s 9.2)
+ */
+gcry_err_code_t
+grub_crypto_rsa_pad (gcry_mpi_t * hmpi, grub_uint8_t * hval,
+ const gcry_md_spec_t * hash, gcry_mpi_t mod);
+

View File

@ -0,0 +1,175 @@
From 8fbcf9f2e97c98bdb63ae7d544aa9bb273022403 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Wed, 12 Sep 2018 16:12:27 -0400
Subject: [PATCH 08/11] x86-efi: Allow initrd+params+cmdline allocations above
4GB.
This enables everything except the kernel itself to be above 4GB.
Putting the kernel up there still doesn't work, because of the way
params->code32_start is used.
Signed-off-by: Peter Jones <pjones@redhat.com>
---
grub-core/loader/i386/efi/linux.c | 67 +++++++++++++++++++++++++++----
include/grub/i386/linux.h | 6 ++-
2 files changed, 65 insertions(+), 8 deletions(-)
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
index d284db5d1..d49749269 100644
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -52,13 +52,22 @@ struct allocation_choice {
grub_efi_allocate_type_t alloc_type;
};
-static struct allocation_choice max_addresses[] =
+static struct allocation_choice max_addresses[4] =
{
+ /* the kernel overrides this one with pref_address and
+ * GRUB_EFI_ALLOCATE_ADDRESS */
{ GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
+ /* this one is always below 4GB, which we still *prefer* even if the flag
+ * is set. */
{ GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
+ /* If the flag in params is set, this one gets changed to be above 4GB. */
{ GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
{ 0, 0 }
};
+static struct allocation_choice saved_addresses[4];
+
+#define save_addresses() grub_memcpy(saved_addresses, max_addresses, sizeof(max_addresses))
+#define restore_addresses() grub_memcpy(max_addresses, saved_addresses, sizeof(max_addresses))
static inline void
kernel_free(void *addr, grub_efi_uintn_t size)
@@ -80,6 +89,11 @@ kernel_alloc(grub_efi_uintn_t size, const char * const errmsg)
grub_uint64_t max = max_addresses[i].addr;
grub_efi_uintn_t pages;
+ /*
+ * When we're *not* loading the kernel, or >4GB allocations aren't
+ * supported, these entries are basically all the same, so don't re-try
+ * the same parameters.
+ */
if (max == prev_max)
continue;
@@ -168,6 +182,9 @@ read(grub_file_t file, grub_uint8_t *bufp, grub_size_t len)
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))
+
static grub_err_t
grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
@@ -208,8 +225,12 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
goto fail;
grub_dprintf ("linux", "initrd_mem = %p\n", initrd_mem);
- params->ramdisk_size = size;
- params->ramdisk_image = initrd_mem;
+ params->ramdisk_size = LOW_U32(size);
+ params->ramdisk_image = LOW_U32(initrd_mem);
+#if defined(__x86_64__)
+ params->ext_ramdisk_size = HIGH_U32(size);
+ params->ext_ramdisk_image = HIGH_U32(initrd_mem);
+#endif
ptr = initrd_mem;
@@ -329,6 +350,18 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
}
#endif
+#if defined(__x86_64__)
+ if (lh->xloadflags & LINUX_XLF_CAN_BE_LOADED_ABOVE_4G)
+ {
+ grub_dprintf ("linux", "Loading kernel above 4GB is supported; enabling.\n");
+ max_addresses[2].addr = GRUB_EFI_MAX_USABLE_ADDRESS;
+ }
+ else
+ {
+ grub_dprintf ("linux", "Loading kernel above 4GB is not supported\n");
+ }
+#endif
+
params = kernel_alloc (sizeof(*params), "cannot allocate kernel parameters");
if (!params)
goto fail;
@@ -365,21 +398,40 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_dprintf ("linux", "cmdline:%s\n", linux_cmdline);
grub_dprintf ("linux", "setting lh->cmd_line_ptr to 0x%08x\n",
- linux_cmdline);
- lh->cmd_line_ptr = linux_cmdline;
+ LOW_U32(linux_cmdline));
+ lh->cmd_line_ptr = LOW_U32(linux_cmdline);
+#if defined(__x86_64__)
+ if ((grub_efi_uintn_t)linux_cmdline > 0xffffffffull)
+ {
+ grub_dprintf ("linux", "setting params->ext_cmd_line_ptr to 0x%08x\n",
+ HIGH_U32(linux_cmdline));
+ params->ext_cmd_line_ptr = HIGH_U32(linux_cmdline);
+ }
+#endif
handover_offset = lh->handover_offset;
grub_dprintf("linux", "handover_offset: 0x%08x\n", handover_offset);
start = (lh->setup_sects + 1) * 512;
+ /*
+ * AFAICS >4GB for kernel *cannot* work because of params->code32_start being
+ * 32-bit and getting called unconditionally in head_64.S from either entry
+ * point.
+ *
+ * so nerf that out here...
+ */
+ save_addresses();
grub_dprintf ("linux", "lh->pref_address: %p\n", (void *)(grub_addr_t)lh->pref_address);
if (lh->pref_address < (grub_uint64_t)GRUB_EFI_MAX_ALLOCATION_ADDRESS)
{
max_addresses[0].addr = lh->pref_address;
max_addresses[0].alloc_type = GRUB_EFI_ALLOCATE_ADDRESS;
}
+ max_addresses[1].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS;
+ max_addresses[2].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS;
kernel_mem = kernel_alloc (lh->init_size, N_("can't allocate kernel"));
+ restore_addresses();
if (!kernel_mem)
goto fail;
grub_dprintf("linux", "kernel_mem = %p\n", kernel_mem);
@@ -388,8 +440,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
loaded = 1;
- grub_dprintf ("linux", "setting lh->code32_start to %p\n", kernel_mem);
- lh->code32_start = (grub_uint32_t)(grub_addr_t) kernel_mem;
+ grub_dprintf ("linux", "setting lh->code32_start to 0x%08x\n",
+ LOW_U32(kernel_mem));
+ lh->code32_start = LOW_U32(kernel_mem);
grub_memcpy (kernel_mem, (char *)kernel + start, filelen - start);
diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h
index 25ef52c04..fac22476c 100644
--- a/include/grub/i386/linux.h
+++ b/include/grub/i386/linux.h
@@ -236,7 +236,11 @@ struct linux_kernel_params
grub_uint32_t ofw_cif_handler; /* b8 */
grub_uint32_t ofw_idt; /* bc */
- grub_uint8_t padding7[0x1b8 - 0xc0];
+ grub_uint32_t ext_ramdisk_image; /* 0xc0 */
+ grub_uint32_t ext_ramdisk_size; /* 0xc4 */
+ grub_uint32_t ext_cmd_line_ptr; /* 0xc8 */
+
+ grub_uint8_t padding7[0x1b8 - 0xcc];
union
{
--
2.31.1

View File

@ -0,0 +1,327 @@
From 749f7dee6f63217e536663aebb817aec72a65d5a Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
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 <volume-name> <encrypted-device> <key-file>
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 <mchang@suse.com>
---
grub-core/Makefile.core.def | 5 +
grub-core/commands/crypttab.c | 47 ++++++++++++++
grub-core/disk/cryptodisk.c | 6 +
grub-core/loader/linux.c | 137 ++++++++++++++++++++++++++++++++++++++++--
include/grub/linux.h | 3
5 files changed, 193 insertions(+), 5 deletions(-)
create mode 100644 grub-core/commands/crypttab.c
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2695,3 +2695,8 @@
cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)';
cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)';
};
+
+module = {
+ name = crypttab;
+ common = commands/crypttab.c;
+};
--- /dev/null
+++ b/grub-core/commands/crypttab.c
@@ -0,0 +1,47 @@
+
+#include <grub/dl.h>
+#include <grub/command.h>
+#include <grub/misc.h>
+#include <grub/i18n.h>
+#include <grub/linux.h>
+
+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 = NULL;
+
+ if (argc == 2)
+ path = NULL;
+ else if (argc == 3)
+ path = argv[2];
+ else
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two or three arguments expected"));
+
+ if (!path
+ || grub_strcmp (path, "none") == 0
+ || grub_strcmp (path, "-") == 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);
+}
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -30,6 +30,8 @@
#ifdef GRUB_UTIL
#include <grub/emu/hostdisk.h>
+#else
+#include <grub/linux.h>
#endif
GRUB_MOD_LICENSE ("GPLv3+");
@@ -1235,6 +1237,10 @@
if (cargs->hdr_file != NULL)
source->read_hook = NULL;
+#ifndef GRUB_UTIL
+ if (cargs->key_data && dev)
+ grub_initrd_publish_key (dev->uuid, (const char *)cargs->key_data, cargs->key_len, NULL);
+#endif
if (askpass)
{
cargs->key_len = 0;
--- a/grub-core/loader/linux.c
+++ b/grub-core/loader/linux.c
@@ -5,6 +5,7 @@
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/safemath.h>
+#include <grub/list.h>
struct newc_head
{
@@ -27,6 +28,7 @@
struct grub_linux_initrd_component
{
grub_file_t file;
+ char *buf;
char *newc_name;
grub_off_t size;
};
@@ -38,6 +40,18 @@
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)
{
@@ -162,6 +176,65 @@
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)
@@ -169,11 +242,17 @@
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;
@@ -253,6 +332,10 @@
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:
@@ -276,7 +359,9 @@
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;
@@ -325,7 +410,12 @@
}
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)
@@ -346,3 +436,45 @@
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 = NULL;
+
+ FOR_LIST_ELEMENTS (cur, kpuber)
+ if (grub_uuidcasecmp (cur->name, uuid, sizeof (cur->name)) == 0)
+ break;
+
+ 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;
+}
--- a/include/grub/linux.h
+++ b/include/grub/linux.h
@@ -22,3 +22,6 @@
grub_err_t
grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx,
void *target);
+
+grub_err_t
+grub_initrd_publish_key (const char *uuid, const char *key, grub_size_t key_len, const char *path);

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