22 Commits

Author SHA256 Message Date
7bebe4975c Accepting request 1310602 from openSUSE:Factory
https://bugzilla.opensuse.org/show_bug.cgi?id=1251862

OBS-URL: https://build.opensuse.org/request/show/1310602
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/grub2?expand=0&rev=375
2025-10-10 15:10:13 +00:00
2947cf51fa Accepting request 1310602 from openSUSE:Factory
https://bugzilla.opensuse.org/show_bug.cgi?id=1251862

OBS-URL: https://build.opensuse.org/request/show/1310602
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/grub2?expand=0&rev=375
2025-10-10 15:10:13 +00:00
6ae9de2829 Accepting request 1309413 from Base:System
OBS-URL: https://build.opensuse.org/request/show/1309413
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/grub2?expand=0&rev=374
2025-10-08 16:12:32 +00:00
65b3a4a414 - make grub plugin compatible with snapper's plugin API (bsc#1246172)
- clean up some unused code

OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=567
2025-10-07 05:06:55 +00:00
928faeb505 Accepting request 1306728 from Base:System
- turn off page flipping for i386-pc using VBE video backend (bsc#1245636)
  * grub2-i386-pc-no-pageflipping.patch

- Fix boot hangs in setting up serial console when ACPI SPCR table is present
  and redirection is disabled (bsc#1249088)
  * 0001-term-ns8250-spcr-Return-if-redirection-is-disabled.patch

OBS-URL: https://build.opensuse.org/request/show/1306728
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/grub2?expand=0&rev=373
2025-09-23 18:47:08 +00:00
462262e6ea - turn off page flipping for i386-pc using VBE video backend (bsc#1245636)
* grub2-i386-pc-no-pageflipping.patch

OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=566
2025-09-23 12:32:51 +00:00
3872727a8d - Fix boot hangs in setting up serial console when ACPI SPCR table is present
and redirection is disabled (bsc#1249088)
  * 0001-term-ns8250-spcr-Return-if-redirection-is-disabled.patch

OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=565
2025-09-23 12:29:27 +00:00
8c20cdcab0 osc copypac from project:Base:System package:grub2 revision:562
OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=564
2025-09-23 12:29:12 +00:00
4085ef8f96 - turn off page flipping for i386-pc using VBE video backend (bsc#1245636)
* grub2-i386-pc-no-pageflipping.patch

OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=563
2025-09-23 09:32:53 +00:00
7437f32a34 Accepting request 1304184 from Base:System
OBS-URL: https://build.opensuse.org/request/show/1304184
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/grub2?expand=0&rev=372
2025-09-12 19:09:17 +00:00
3db63b85e2 - Add support for LoaderEntryDefault EFI variable
* grub2-bls-loader-entry-default.patch

OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=562
2025-09-12 04:09:11 +00:00
f509f29f48 Accepting request 1303110 from Base:System
OBS-URL: https://build.opensuse.org/request/show/1303110
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/grub2?expand=0&rev=371
2025-09-08 11:05:03 +00:00
c90e5054ec - Optimize PBKDF2 to reduce the decryption time
* 0001-lib-crypto-Introduce-new-HMAC-functions-to-reuse-buf.patch
  * 0002-lib-pbkdf2-Optimize-PBKDF2-by-reusing-HMAC-handle.patch
  * 0001-kern-misc-Implement-faster-grub_memcpy-for-aligned-b.patch

OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=561
2025-09-08 04:52:47 +00:00
ef9fe84701 Accepting request 1299305 from Base:System
OBS-URL: https://build.opensuse.org/request/show/1299305
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/grub2?expand=0&rev=370
2025-08-15 19:51:02 +00:00
29e0b8290c - UEFI NX support and NX Linux loader using shim loader protocol (bsc#1205588)
(jsc#PED-13361)
  * 0001-modules-Make-.module_license-read-only.patch
  * 0002-modules-Strip-.llvm_addrsig-sections-and-similar.patch
  * 0003-modules-Don-t-allocate-space-for-non-allocable-secti.patch
  * 0004-modules-Load-module-sections-at-page-aligned-address.patch
  * 0005-nx-Add-memory-attribute-get-set-API.patch
  * 0006-nx-Set-page-permissions-for-loaded-modules.patch
  * 0007-nx-Set-the-NX-compatible-flag-for-the-GRUB-EFI-image.patch
  * 0008-efi-Provide-wrappers-for-load_image-start_image-and-.patch
  * 0009-efi-sb-Add-support-for-the-shim-loader-protocol.patch
  * 0010-efi-sb-Add-API-for-retrieving-shim-loader-image-hand.patch
  * 0011-loader-efi-chainloader-Use-shim-loader-image-handle-.patch
  * 0012-loader-efi-linux-Use-shim-loader-image-handle-where-.patch
  * 0013-nx-Rename-GRUB_DL_ALIGN-to-DL_ALIGN.patch
- Fallback for legacy shim lock protocol while secure boot is enabled
  * 0001-linux-fallback-to-EFI-handover-on-x86_64.patch
  * 0002-linux-fallback-to-direct-PE-entry-boot-on-arm64.patch
  * 0003-efi-chainloader-fallback-to-direct-image-execution.patch
  * 0004-efi-chainloader-fix-missing-file_path-in-loaded_imag.patch
- Removed patch
  * 0001-xen_boot-add-missing-grub_arch_efi_linux_load_image_.patch

OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=560
2025-08-14 02:40:02 +00:00
0108c5290e Accepting request 1298703 from Base:System
OBS-URL: https://build.opensuse.org/request/show/1298703
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/grub2?expand=0&rev=369
2025-08-12 15:03:08 +00:00
4962b71520 - Fix timeout when loading initrd via http after PPC CAS reboot (bsc#1245953)
* 0001-tcp-Fix-TCP-port-number-reused-on-reboot.patch

OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=559
2025-08-11 02:50:27 +00:00
e3c4848fca Accepting request 1297414 from Base:System
OBS-URL: https://build.opensuse.org/request/show/1297414
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/grub2?expand=0&rev=368
2025-08-07 14:48:22 +00:00
575dbfe9e9 - Skip mount point in grub_find_device function (bsc#1246231)
* 0001-getroot-Skip-mount-points-in-grub_find_device.patch

OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=558
2025-08-04 07:44:31 +00:00
0f03cac870 Accepting request 1296922 from Base:System
- Fix CVE-2024-56738: side-channel attack due to not constant-time
  algorithm in grub_crypto_memcmp (bsc#1234959)
  * grub2-constant-time-grub_crypto_memcmp.patch

- Update the bug tag for 0001-tpm2-Add-extra-RSA-SRK-types.patch

OBS-URL: https://build.opensuse.org/request/show/1296922
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/grub2?expand=0&rev=367
2025-08-03 11:36:23 +00:00
03767e119a Update the bug tag for 0001-tpm2-Add-extra-RSA-SRK-types.patch
OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=557
2025-08-01 03:01:52 +00:00
5bb0fbd333 - Fix CVE-2024-56738: side-channel attack due to not constant-time
algorithm in grub_crypto_memcmp (bsc#1234959)
  * grub2-constant-time-grub_crypto_memcmp.patch

OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=556
2025-08-01 02:45:33 +00:00
29 changed files with 2728 additions and 85 deletions

View File

@@ -0,0 +1,66 @@
From ff3165a3e519892ec4bf9a31f4f1132668f83394 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Tue, 15 Jul 2025 14:15:22 +0800
Subject: [PATCH] getroot: Skip mount points in grub_find_device
The grub_find_device function scans a starting directory, typically
/dev, for device files with matching major and minor numbers. During
this process, it recursively descends into subdirectories.
However, this can significantly slow down the scan if a subdirectory is
a mount point not related to devtmpfs, especially if it contains a large
number of files.
This patch modifies grub_find_device() to skip subdirectories that are
mount points. A mount point is detected by comparing the st_dev of the
subdirectory against that of the parent or starting directory. While
this method does not catch all types of mounts, for eg bind mounts, it
is a practical solution that avoids the need to parse /proc/self/mounts.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/osdep/unix/getroot.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/grub-core/osdep/unix/getroot.c b/grub-core/osdep/unix/getroot.c
index dce94b52e..9759cc59b 100644
--- a/grub-core/osdep/unix/getroot.c
+++ b/grub-core/osdep/unix/getroot.c
@@ -353,6 +353,7 @@ grub_find_device (const char *dir, dev_t dev)
DIR *dp;
struct saved_cwd saved_cwd;
struct dirent *ent;
+ struct stat st_dir;
if (! dir)
dir = "/dev";
@@ -361,6 +362,12 @@ grub_find_device (const char *dir, dev_t dev)
if (! dp)
return 0;
+ if (stat (dir, &st_dir) < 0)
+ {
+ closedir (dp);
+ return 0;
+ }
+
if (save_cwd (&saved_cwd) < 0)
{
grub_util_error ("%s", _("cannot save the original directory"));
@@ -410,6 +417,13 @@ grub_find_device (const char *dir, dev_t dev)
/* Find it recursively. */
char *res;
+ /* Skip mount point */
+ if (st.st_dev != st_dir.st_dev)
+ {
+ grub_util_info ("skip mount point %s/%s", dir, ent->d_name);
+ continue;
+ }
+
res = grub_find_device (ent->d_name, dev);
if (res)
--
2.50.0

View File

@@ -0,0 +1,116 @@
From 1fbd2a278cfc645adc45c0e1357e58bcd1909f8d Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Thu, 28 Aug 2025 15:03:35 +0800
Subject: [PATCH] kern/misc: Implement faster grub_memcpy() for aligned buffers
When both "dest" and "src" are aligned, copying the data in chunks
(unsigned long) is more efficient than a byte-by-byte copy.
Also tweak '__aeabi_memcpy()', '__aeabi_memcpy4()', and
'__aeabi_memcpy8()', since 'grub_memcpy()' is not inline anymore.
Signed-off-by: Gary Lin <glin@suse.com>
---
grub-core/kern/compiler-rt.c | 8 ++++----
grub-core/kern/misc.c | 30 ++++++++++++++++++++++++++++++
include/grub/misc.h | 8 +-------
3 files changed, 35 insertions(+), 11 deletions(-)
diff --git a/grub-core/kern/compiler-rt.c b/grub-core/kern/compiler-rt.c
index eda689a0c..8f3865e95 100644
--- a/grub-core/kern/compiler-rt.c
+++ b/grub-core/kern/compiler-rt.c
@@ -24,7 +24,7 @@
void * GRUB_BUILTIN_ATTR
memcpy (void *dest, const void *src, grub_size_t n)
{
- return grub_memmove (dest, src, n);
+ return grub_memcpy (dest, src, n);
}
void * GRUB_BUILTIN_ATTR
memmove (void *dest, const void *src, grub_size_t n)
@@ -372,11 +372,11 @@ grub_int32_t
__aeabi_idiv (grub_int32_t a, grub_int32_t b)
__attribute__ ((alias ("__divsi3")));
void *__aeabi_memcpy (void *dest, const void *src, grub_size_t n)
- __attribute__ ((alias ("grub_memcpy")));
+ __attribute__ ((alias ("memcpy")));
void *__aeabi_memcpy4 (void *dest, const void *src, grub_size_t n)
- __attribute__ ((alias ("grub_memcpy")));
+ __attribute__ ((alias ("memcpy")));
void *__aeabi_memcpy8 (void *dest, const void *src, grub_size_t n)
- __attribute__ ((alias ("grub_memcpy")));
+ __attribute__ ((alias ("memcpy")));
void *__aeabi_memset (void *s, int c, grub_size_t n)
__attribute__ ((alias ("memset")));
diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
index 2b7922393..016932583 100644
--- a/grub-core/kern/misc.c
+++ b/grub-core/kern/misc.c
@@ -99,6 +99,36 @@ grub_memmove (void *dest, const void *src, grub_size_t n)
return dest;
}
+static void *
+__memcpy_aligned (void *dest, const void *src, grub_size_t n)
+{
+ unsigned long *dw = (unsigned long *) dest;
+ const unsigned long *sw = (const unsigned long *) src;
+ grub_uint8_t *d;
+ const grub_uint8_t *s;
+
+ for (; n >= sizeof (unsigned long); n -= sizeof (unsigned long))
+ *dw++ = *sw++;
+
+ d = (grub_uint8_t *) dw;
+ s = (const grub_uint8_t *) sw;
+ for (; n > 0; n--)
+ *d++ = *s++;
+
+ return dest;
+}
+
+void *
+grub_memcpy (void *dest, const void *src, grub_size_t n)
+{
+ /* Check if 'dest' and 'src' are aligned */
+ if (((grub_addr_t) dest & (sizeof (unsigned long) - 1)) == 0 &&
+ ((grub_addr_t) src & (sizeof (unsigned long) - 1)) == 0)
+ return __memcpy_aligned (dest, src, n);
+
+ return grub_memmove (dest, src, n);
+}
+
char *
grub_strcpy (char *dest, const char *src)
{
diff --git a/include/grub/misc.h b/include/grub/misc.h
index e087e7b3e..b6b14ca55 100644
--- a/include/grub/misc.h
+++ b/include/grub/misc.h
@@ -38,6 +38,7 @@
#define grub_dprintf(condition, ...) grub_real_dprintf(GRUB_FILE, __LINE__, condition, __VA_ARGS__)
void *EXPORT_FUNC(grub_memmove) (void *dest, const void *src, grub_size_t n);
+void *EXPORT_FUNC(grub_memcpy) (void *dest, const void *src, grub_size_t n);
char *EXPORT_FUNC(grub_strcpy) (char *dest, const char *src);
static inline char *
@@ -103,13 +104,6 @@ grub_strlcpy (char *dest, const char *src, grub_size_t size)
return res;
}
-/* XXX: If grub_memmove is too slow, we must implement grub_memcpy. */
-static inline void *
-grub_memcpy (void *dest, const void *src, grub_size_t n)
-{
- return grub_memmove (dest, src, n);
-}
-
#if defined(__x86_64__) && !defined (GRUB_UTIL)
#if defined (__MINGW32__) || defined (__CYGWIN__) || defined (__MINGW64__)
#define GRUB_ASM_ATTR __attribute__ ((sysv_abi))
--
2.51.0

View File

@@ -0,0 +1,234 @@
From e98e880b67be178f3a5951fb345ded8c002eb6e5 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Wed, 13 Aug 2025 11:43:40 +0800
Subject: [PATCH 1/2] lib/crypto: Introduce new HMAC functions to reuse buffers
To enable more efficient buffer reuse for HMAC operations, three new
functions have been introduced. This change prevents the need to
reallocate memory for each HMAC operation.
* grub_crypto_hmac_reset(): Reinitializes the hash contexts in the HMAC
handle.
* grub_crypto_hmac_final(): Provides the final HMAC result without
freeing the handle, allowing it to be reused immediately.
* grub_crypto_hmac_free(): Deallocates the HMAC handle and its
associated memory.
To further facilitate buffer reuse, 'ctx2' is now included within the HMAC
handle struct, and the initialization of 'ctx2' is moved to
grub_crypto_hmac_init().
The intermediate hash states ('ctx' and 'ctx2') for the inner and outer
padded keys are now cached. grub_crypto_hmac_reset() restores these cached
states for new operations, which avoids redundant hashing of the keys.
Signed-off-by: Gary Lin <glin@suse.com>
---
grub-core/disk/geli.c | 4 +-
grub-core/lib/crypto.c | 91 ++++++++++++++++++++++++++++++------------
include/grub/crypto.h | 8 +++-
3 files changed, 74 insertions(+), 29 deletions(-)
Index: grub-2.12/grub-core/disk/geli.c
===================================================================
--- grub-2.12.orig/grub-core/disk/geli.c
+++ grub-2.12/grub-core/disk/geli.c
@@ -464,9 +464,7 @@ geli_recover_key (grub_disk_t source, gr
grub_crypto_hmac_write (hnd, header.salt, sizeof (header.salt));
grub_crypto_hmac_write (hnd, cargs->key_data, cargs->key_len);
- gcry_err = grub_crypto_hmac_fini (hnd, geomkey);
- if (gcry_err)
- return grub_crypto_gcry_error (gcry_err);
+ grub_crypto_hmac_fini (hnd, geomkey);
}
gcry_err = grub_crypto_hmac_buffer (dev->hash, geomkey,
Index: grub-2.12/grub-core/lib/crypto.c
===================================================================
--- grub-2.12.orig/grub-core/lib/crypto.c
+++ grub-2.12/grub-core/lib/crypto.c
@@ -31,7 +31,9 @@ struct grub_crypto_hmac_handle
{
const struct gcry_md_spec *md;
void *ctx;
- void *opad;
+ void *ctx2;
+ void *ctx_cache;
+ void *ctx2_cache;
};
static gcry_cipher_spec_t *grub_ciphers = NULL;
@@ -307,7 +309,8 @@ grub_crypto_hmac_init (const struct gcry
{
grub_uint8_t *helpkey = NULL;
grub_uint8_t *ipad = NULL, *opad = NULL;
- void *ctx = NULL;
+ void *ctx = NULL, *ctx2 = NULL;
+ void *ctx_cache = NULL, *ctx2_cache = NULL;
struct grub_crypto_hmac_handle *ret = NULL;
unsigned i;
@@ -318,6 +321,18 @@ grub_crypto_hmac_init (const struct gcry
if (!ctx)
goto err;
+ ctx2 = grub_malloc (md->contextsize);
+ if (!ctx2)
+ goto err;
+
+ ctx_cache = grub_malloc (md->contextsize);
+ if (!ctx_cache)
+ goto err;
+
+ ctx2_cache = grub_malloc (md->contextsize);
+ if (!ctx2_cache)
+ goto err;
+
if ( keylen > md->blocksize )
{
helpkey = grub_malloc (md->mdlen);
@@ -347,26 +362,40 @@ grub_crypto_hmac_init (const struct gcry
grub_free (helpkey);
helpkey = NULL;
+ /* inner pad */
md->init (ctx);
-
- md->write (ctx, ipad, md->blocksize); /* inner pad */
+ md->write (ctx, ipad, md->blocksize);
+ grub_memcpy (ctx_cache, ctx, md->contextsize);
grub_memset (ipad, 0, md->blocksize);
grub_free (ipad);
ipad = NULL;
+ /* outer pad */
+ md->init (ctx2);
+ md->write (ctx2, opad, md->blocksize);
+ grub_memcpy (ctx2_cache, ctx2, md->contextsize);
+ grub_memset (opad, 0, md->blocksize);
+ grub_free (opad);
+ opad = NULL;
+
ret = grub_malloc (sizeof (*ret));
if (!ret)
goto err;
ret->md = md;
ret->ctx = ctx;
- ret->opad = opad;
+ ret->ctx2 = ctx2;
+ ret->ctx_cache = ctx_cache;
+ ret->ctx2_cache = ctx2_cache;
return ret;
err:
grub_free (helpkey);
grub_free (ctx);
+ grub_free (ctx2);
+ grub_free (ctx_cache);
+ grub_free (ctx2_cache);
grub_free (ipad);
grub_free (opad);
return NULL;
@@ -380,37 +409,48 @@ grub_crypto_hmac_write (struct grub_cryp
hnd->md->write (hnd->ctx, data, datalen);
}
-gcry_err_code_t
+void
grub_crypto_hmac_fini (struct grub_crypto_hmac_handle *hnd, void *out)
{
- grub_uint8_t *p;
- grub_uint8_t *ctx2;
+ grub_crypto_hmac_final (hnd, out);
+ grub_crypto_hmac_free (hnd);
+}
- ctx2 = grub_malloc (hnd->md->contextsize);
- if (!ctx2)
- return GPG_ERR_OUT_OF_MEMORY;
+void
+grub_crypto_hmac_reset (struct grub_crypto_hmac_handle *hnd)
+{
+ grub_memcpy (hnd->ctx, hnd->ctx_cache, hnd->md->contextsize);
+ grub_memcpy (hnd->ctx2, hnd->ctx2_cache, hnd->md->contextsize);
+}
+
+void
+grub_crypto_hmac_final (struct grub_crypto_hmac_handle *hnd, void *out)
+{
+ grub_uint8_t *p;
hnd->md->final (hnd->ctx);
hnd->md->read (hnd->ctx);
p = hnd->md->read (hnd->ctx);
- hnd->md->init (ctx2);
- hnd->md->write (ctx2, hnd->opad, hnd->md->blocksize);
- hnd->md->write (ctx2, p, hnd->md->mdlen);
- hnd->md->final (ctx2);
- grub_memset (hnd->opad, 0, hnd->md->blocksize);
- grub_free (hnd->opad);
- grub_memset (hnd->ctx, 0, hnd->md->contextsize);
- grub_free (hnd->ctx);
+ hnd->md->write (hnd->ctx2, p, hnd->md->mdlen);
+ hnd->md->final (hnd->ctx2);
- grub_memcpy (out, hnd->md->read (ctx2), hnd->md->mdlen);
- grub_memset (ctx2, 0, hnd->md->contextsize);
- grub_free (ctx2);
+ grub_memcpy (out, hnd->md->read (hnd->ctx2), hnd->md->mdlen);
+}
+void
+grub_crypto_hmac_free (struct grub_crypto_hmac_handle *hnd)
+{
+ grub_memset (hnd->ctx, 0, hnd->md->contextsize);
+ grub_free (hnd->ctx);
+ grub_memset (hnd->ctx2, 0, hnd->md->contextsize);
+ grub_free (hnd->ctx2);
+ grub_memset (hnd->ctx_cache, 0, hnd->md->contextsize);
+ grub_free (hnd->ctx_cache);
+ grub_memset (hnd->ctx2_cache, 0, hnd->md->contextsize);
+ grub_free (hnd->ctx2_cache);
grub_memset (hnd, 0, sizeof (*hnd));
grub_free (hnd);
-
- return GPG_ERR_NO_ERROR;
}
gcry_err_code_t
@@ -425,7 +465,8 @@ grub_crypto_hmac_buffer (const struct gc
return GPG_ERR_OUT_OF_MEMORY;
grub_crypto_hmac_write (hnd, data, datalen);
- return grub_crypto_hmac_fini (hnd, out);
+ grub_crypto_hmac_fini (hnd, out);
+ return GPG_ERR_NO_ERROR;
}
Index: grub-2.12/include/grub/crypto.h
===================================================================
--- grub-2.12.orig/include/grub/crypto.h
+++ grub-2.12/include/grub/crypto.h
@@ -358,8 +358,14 @@ void
grub_crypto_hmac_write (struct grub_crypto_hmac_handle *hnd,
const void *data,
grub_size_t datalen);
-gcry_err_code_t
+void
grub_crypto_hmac_fini (struct grub_crypto_hmac_handle *hnd, void *out);
+void
+grub_crypto_hmac_reset (struct grub_crypto_hmac_handle *hnd);
+void
+grub_crypto_hmac_final (struct grub_crypto_hmac_handle *hnd, void *out);
+void
+grub_crypto_hmac_free (struct grub_crypto_hmac_handle *hnd);
gcry_err_code_t
grub_crypto_hmac_buffer (const struct gcry_md_spec *md,

View File

@@ -0,0 +1,119 @@
From f770cc82c3d65c65d812e96e006c17861d357d99 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Sat, 26 Apr 2025 15:07:36 +0800
Subject: [PATCH 1/4] linux: fallback to EFI handover on x86_64
On the x86_64 platform, when the shim loader protocol is unavailable and
UEFI Secure Boot is enabled, fall back to the Linux EFI handover boot
protocol. This legacy method supports the in-kernel EFI stub and is used
instead of the 32-bit boot entry.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/Makefile.core.def | 2 ++
grub-core/loader/efi/linux.c | 13 +++++++------
grub-core/loader/i386/efi/linux.c | 30 ++++--------------------------
3 files changed, 13 insertions(+), 32 deletions(-)
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 80ea6656a..1811661c3 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1902,6 +1902,8 @@ module = {
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;
i386_efi = loader/efi/linux_boot.c;
diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
index 394df6039..b20dec404 100644
--- a/grub-core/loader/efi/linux.c
+++ b/grub-core/loader/efi/linux.c
@@ -71,10 +71,10 @@ static initrd_media_device_path_t initrd_lf2_device_path = {
};
extern grub_err_t
-grub_cmd_linux_x86_legacy (grub_command_t cmd, int argc, char *argv[]);
+grub_cmd_linux_efi_fallback (grub_command_t cmd, int argc, char *argv[]);
extern grub_err_t
-grub_cmd_initrd_x86_legacy (grub_command_t cmd, int argc, char *argv[]);
+grub_cmd_initrd_efi_fallback (grub_command_t cmd, int argc, char *argv[]);
static grub_efi_status_t __grub_efi_api
grub_efi_initrd_load_file2 (grub_efi_load_file2_t *this,
@@ -389,8 +389,9 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
}
#if defined(__i386__) || defined(__x86_64__)
- if (!initrd_use_loadfile2)
- return grub_cmd_initrd_x86_legacy (cmd, argc, argv);
+ if (grub_is_using_legacy_shim_lock_protocol () == true ||
+ !initrd_use_loadfile2)
+ return grub_cmd_initrd_efi_fallback (cmd, argc, argv);
#endif
if (!loaded)
@@ -474,7 +475,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
#if defined(__i386__) || defined(__x86_64__)
grub_dprintf ("linux", "using legacy shim_lock protocol, falling back to legacy Linux kernel loader\n");
- err = grub_cmd_linux_x86_legacy (cmd, argc, argv);
+ err = grub_cmd_linux_efi_fallback (cmd, argc, argv);
if (err == GRUB_ERR_NONE)
return GRUB_ERR_NONE;
@@ -513,7 +514,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
*/
fallback:
grub_file_close (file);
- return grub_cmd_linux_x86_legacy (cmd, argc, argv);
+ return grub_cmd_linux_efi_fallback (cmd, argc, argv);
}
#endif
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
index ca3435a88..49e4a3f19 100644
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -421,30 +421,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
return grub_errno;
}
-static grub_command_t cmd_linux, cmd_initrd;
-static grub_command_t cmd_linuxefi, cmd_initrdefi;
+extern grub_err_t __attribute__((alias("grub_cmd_linux")))
+grub_cmd_linux_efi_fallback (grub_command_t cmd, int argc, char *argv[]);
-GRUB_MOD_INIT(linux)
-{
- cmd_linuxefi =
- grub_register_command ("linuxefi", grub_cmd_linux,
- 0, N_("Load Linux."));
- 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(linux)
-{
- grub_unregister_command (cmd_linuxefi);
- grub_unregister_command (cmd_initrdefi);
- grub_unregister_command (cmd_linux);
- grub_unregister_command (cmd_initrd);
-}
+extern grub_err_t __attribute__((alias("grub_cmd_initrd")))
+grub_cmd_initrd_efi_fallback (grub_command_t cmd, int argc, char *argv[]);
--
2.50.1

View File

@@ -0,0 +1,35 @@
From a05d4896327e87b2986ddb44ef0947bbc9010da6 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Wed, 9 Oct 2024 09:16:36 +0100
Subject: [PATCH 01/13] modules: Make .module_license read-only
Currently .module_license is set writable, that is, the section has the
SHF_WRITE flag set, in the module's ELF headers. This probably never
actually matters but it can't possibly be correct. The patch sets that
data as "const" which causes that flag not to be set.
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Jan Setje-Eilers <jan.setjeeilers@oracle.com>
Signed-off-by: Mate Kukri <mate.kukri@canonical.com>
Reviewed-By: Vladimir Serbinenko <phcoder@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
include/grub/dl.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/grub/dl.h b/include/grub/dl.h
index c5ab18cb1..fb4476797 100644
--- a/include/grub/dl.h
+++ b/include/grub/dl.h
@@ -119,7 +119,7 @@ grub_mod_fini (void)
#define ATTRIBUTE_USED __unused__
#endif
#define GRUB_MOD_LICENSE(license) \
- static char grub_module_license[] __attribute__ ((section (GRUB_MOD_SECTION (module_license)), ATTRIBUTE_USED)) = "LICENSE=" license;
+ static const char grub_module_license[] __attribute__ ((section (GRUB_MOD_SECTION (module_license)), ATTRIBUTE_USED)) = "LICENSE=" license;
#define GRUB_MOD_DEP(name) \
static const char grub_module_depend_##name[] \
__attribute__((section(GRUB_MOD_SECTION(moddeps)), ATTRIBUTE_USED)) = #name
--
2.50.1

View File

@@ -0,0 +1,116 @@
From 468a37601083ef3352ff6e5d4f40ec8b1cebc4ef Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Tue, 8 Jul 2025 11:57:42 +0800
Subject: [PATCH] tcp: Fix TCP port number reused on reboot
GRUB's TCP stack assigns source ports for outgoing connections starting
at 21550 and increments sequentially by 1 (e.g., 21550, 21551, ...).
While this generally works, it can lead to failures if the system
reboots rapidly and reuses the same source port too soon.
This issue was observed on powerpc-ieee1275 platforms using CAS (Client
Architecture Support) reboot. In such cases, loading the initrd over
HTTP may fail with connection timeouts. Packet captures show the failed
connections are flagged as "TCP Port Number Reused" by Wireshark.
The root cause is that GRUB reuses the same port shortly after reboot,
while the server may still be tracking the previous connection in
TIME_WAIT. This can result in the server rejecting the connection
attempt or responding with a stale ACK or RST, leading to handshake
failure.
This patch fixes the issue by introducing a time based source port
selection strategy. Instead of always starting from port 21550, GRUB now
computes an initial base port based on the current RTC time, divided
into 5 minute windows. The purpose of this time based strategy is to
ensure that GRUB avoids reusing the same source port within a 5 minute
window, thereby preventing collisions with stale server side connection
tracking that could interfere with a new TCP handshake.
A step size of 8 ensures that the same port will not be reused across
reboots unless GRUB opens more than 8 TCP connections per second on
average, something that is highly unlikely. In typical usage, a GRUB
boot cycle lasts about 15 seconds and may open fewer than 100
connections total, well below the reuse threshold. This makes the
approach robust against short reboot intervals while keeping the logic
simple and deterministic.
Signed-off-by: Michael Chang <mchang@suse.com>
Reviewed-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
---
grub-core/net/tcp.c | 39 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 38 insertions(+), 1 deletion(-)
diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c
index 93dee0caa..d0cc602dc 100644
--- a/grub-core/net/tcp.c
+++ b/grub-core/net/tcp.c
@@ -22,6 +22,7 @@
#include <grub/net/netbuff.h>
#include <grub/time.h>
#include <grub/priority_queue.h>
+#include <grub/datetime.h>
#define TCP_SYN_RETRANSMISSION_TIMEOUT GRUB_NET_INTERVAL
#define TCP_SYN_RETRANSMISSION_COUNT GRUB_NET_TRIES
@@ -552,6 +553,36 @@ grub_net_tcp_accept (grub_net_tcp_socket_t sock,
return GRUB_ERR_NONE;
}
+/*
+ * Derive a time-based source port to avoid reusing the same port across
+ * reboots. This helps prevent failures caused by server side TCP state (e.g.
+ * TIME_WAIT) from interfering with new connections using the same socket.
+ *
+ * The base port starts at 21550 and increments every second by 8 across a 5
+ * minute window (300 seconds), giving 2400 possible distinct base ports per
+ * window. In typical GRUB usage, the number of connections per boot is small,
+ * so reuse is effectively avoided.
+ */
+static grub_uint16_t
+get_initial_base_port (void)
+{
+ grub_err_t err;
+ struct grub_datetime date;
+ grub_int64_t t = 0;
+ grub_uint64_t r = 0;
+
+ err = grub_get_datetime (&date);
+ if (err != GRUB_ERR_NONE || !grub_datetime2unixtime (&date, &t))
+ {
+ grub_errno = GRUB_ERR_NONE;
+ return 21550;
+ }
+
+ grub_divmod64 (t, 300, &r);
+
+ return 21550 + (r << 3);
+}
+
grub_net_tcp_socket_t
grub_net_tcp_open (char *server,
grub_uint16_t out_port,
@@ -569,13 +600,19 @@ grub_net_tcp_open (char *server,
struct grub_net_network_level_interface *inf;
grub_net_network_level_address_t gateway;
grub_net_tcp_socket_t socket;
- static grub_uint16_t in_port = 21550;
+ static grub_uint16_t in_port;
struct grub_net_buff *nb;
struct tcphdr *tcph;
int i;
grub_uint8_t *nbd;
grub_net_link_level_address_t ll_target_addr;
+ if (!in_port)
+ {
+ in_port = get_initial_base_port ();
+ grub_dprintf ("net", "base port: %d\n", in_port);
+ }
+
err = grub_net_resolve_address (server, &addr);
if (err)
return NULL;
--
2.50.1

View File

@@ -0,0 +1,38 @@
From f0a08324d0f923527ba611887a3780c1f2cb1578 Mon Sep 17 00:00:00 2001
From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Date: Tue, 21 Jan 2025 11:01:26 -0600
Subject: [PATCH] term/ns8250-spcr: Return if redirection is disabled
The Microsoft spec for SPCR says "The base address of the Serial Port
register set described using the ACPI Generic Address Structure, or
0 if console redirection is disabled". So, return early if redirection
is disabled (base address = 0). If this check is not done we may get
invalid ports on machines with redirection disabled and boot may hang
when reading the grub.cfg file.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Reviewed-by: Leo Sandoval <lsandova@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/term/ns8250-spcr.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/grub-core/term/ns8250-spcr.c b/grub-core/term/ns8250-spcr.c
index 4efaaf768..428b2d59a 100644
--- a/grub-core/term/ns8250-spcr.c
+++ b/grub-core/term/ns8250-spcr.c
@@ -76,6 +76,11 @@ grub_ns8250_spcr_init (void)
config.speed = 115200;
break;
};
+
+ /* If base address is 0 it means redirection is disabled. */
+ if (spcr->base_addr.addr == 0)
+ return NULL;
+
switch (spcr->base_addr.space_id)
{
case GRUB_ACPI_GENADDR_MEM_SPACE:
--
2.51.0

View File

@@ -1,83 +0,0 @@
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,91 @@
From 7126da87f17ff41334b9fa6969ad032ff9940979 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Wed, 13 Aug 2025 09:57:04 +0800
Subject: [PATCH 2/2] lib/pbkdf2: Optimize PBKDF2 by reusing HMAC handle
The previous PBKDF2 implementation used grub_crypto_hmac_buffer(), which
allocates and frees an HMAC handle on every call. This approach caused
significant performance overhead, slowing down the boot process
considerably.
This commit refactors the PBKDF2 code to use the new HMAC functions,
allowing the HMAC handle and its buffers to be allocated once and reused
across multiple operations. This change significantly reduces disk
unlocking time.
In a QEMU/OVMF test environment, this patch reduced the time to unlock a
LUKS2(*) partition from approximately 15 seconds to 4 seconds.
(*) PBKDF2 SHA256 with 3454944 iterations
Signed-off-by: Gary Lin <glin@suse.com>
---
grub-core/lib/pbkdf2.c | 21 +++++++++++++--------
1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/grub-core/lib/pbkdf2.c b/grub-core/lib/pbkdf2.c
index 28aa96c46..410eff580 100644
--- a/grub-core/lib/pbkdf2.c
+++ b/grub-core/lib/pbkdf2.c
@@ -39,6 +39,7 @@ grub_crypto_pbkdf2 (const struct gcry_md_spec *md,
unsigned int c,
grub_uint8_t *DK, grub_size_t dkLen)
{
+ struct grub_crypto_hmac_handle *hnd = NULL;
unsigned int hLen = md->mdlen;
grub_uint8_t U[GRUB_CRYPTO_MAX_MDLEN];
grub_uint8_t T[GRUB_CRYPTO_MAX_MDLEN];
@@ -47,7 +48,6 @@ grub_crypto_pbkdf2 (const struct gcry_md_spec *md,
unsigned int r;
unsigned int i;
unsigned int k;
- gcry_err_code_t rc;
grub_uint8_t *tmp;
grub_size_t tmplen = Slen + 4;
@@ -72,6 +72,13 @@ grub_crypto_pbkdf2 (const struct gcry_md_spec *md,
grub_memcpy (tmp, S, Slen);
+ hnd = grub_crypto_hmac_init (md, P, Plen);
+ if (hnd == NULL)
+ {
+ grub_free (tmp);
+ return GPG_ERR_OUT_OF_MEMORY;
+ }
+
for (i = 1; i - 1 < l; i++)
{
grub_memset (T, 0, hLen);
@@ -85,16 +92,13 @@ grub_crypto_pbkdf2 (const struct gcry_md_spec *md,
tmp[Slen + 2] = (i & 0x0000ff00) >> 8;
tmp[Slen + 3] = (i & 0x000000ff) >> 0;
- rc = grub_crypto_hmac_buffer (md, P, Plen, tmp, tmplen, U);
+ grub_crypto_hmac_write (hnd, tmp, tmplen);
}
else
- rc = grub_crypto_hmac_buffer (md, P, Plen, U, hLen, U);
+ grub_crypto_hmac_write (hnd, U, hLen);
- if (rc != GPG_ERR_NO_ERROR)
- {
- grub_free (tmp);
- return rc;
- }
+ grub_crypto_hmac_final (hnd, U);
+ grub_crypto_hmac_reset (hnd);
for (k = 0; k < hLen; k++)
T[k] ^= U[k];
@@ -103,6 +107,7 @@ grub_crypto_pbkdf2 (const struct gcry_md_spec *md,
grub_memcpy (DK + (i - 1) * hLen, T, i == l ? r : hLen);
}
+ grub_crypto_hmac_free (hnd);
grub_free (tmp);
return GPG_ERR_NO_ERROR;
--
2.51.0

View File

@@ -0,0 +1,113 @@
From 1e5d19972bb64b0fcb39083042a69cf05e0cb783 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Sat, 26 Apr 2025 15:33:28 +0800
Subject: [PATCH 2/4] linux: fallback to direct PE entry boot on arm64
On the arm64 platform, when the shim loader protocol is unavailable and
UEFI Secure Boot is enabled, fall back to booting via the direct PE/COFF
image entry point instead of requesting UEFI to load and start the
image. This fallback allows booting binaries validated by shim's vendor
DB, even if they are not listed in the UEFI DB.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/Makefile.core.def | 1 +
grub-core/loader/arm64/efi/linux.c | 26 +++++++-------------------
grub-core/loader/efi/linux.c | 6 +++---
3 files changed, 11 insertions(+), 22 deletions(-)
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 1811661c3..2100d7ff2 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1898,6 +1898,7 @@ module = {
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;
diff --git a/grub-core/loader/arm64/efi/linux.c b/grub-core/loader/arm64/efi/linux.c
index a9f5e05e4..8eab1dc86 100644
--- a/grub-core/loader/arm64/efi/linux.c
+++ b/grub-core/loader/arm64/efi/linux.c
@@ -190,8 +190,8 @@ free_params (void)
}
}
-grub_err_t
-grub_arch_efi_linux_boot_image (grub_addr_t addr,
+static grub_err_t
+grub_arm64_efi_linux_boot_image (grub_addr_t addr,
grub_size_t size __attribute__ ((unused)),
char *args)
{
@@ -213,7 +213,7 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr,
static grub_err_t
grub_linux_boot (void)
{
- return (grub_arch_efi_linux_boot_image ((grub_addr_t)kernel_addr, kernel_size, linux_args));
+ return (grub_arm64_efi_linux_boot_image ((grub_addr_t)kernel_addr, kernel_size, linux_args));
}
static grub_err_t
@@ -464,20 +464,8 @@ fail:
return grub_errno;
}
+extern grub_err_t __attribute__((alias("grub_cmd_linux")))
+grub_cmd_linux_efi_fallback (grub_command_t cmd, int argc, char *argv[]);
-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);
-}
+extern grub_err_t __attribute__((alias("grub_cmd_initrd")))
+grub_cmd_initrd_efi_fallback (grub_command_t cmd, int argc, char *argv[]);
diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
index b20dec404..d29e32cba 100644
--- a/grub-core/loader/efi/linux.c
+++ b/grub-core/loader/efi/linux.c
@@ -388,7 +388,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
if (grub_is_using_legacy_shim_lock_protocol () == true ||
!initrd_use_loadfile2)
return grub_cmd_initrd_efi_fallback (cmd, argc, argv);
@@ -472,7 +472,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
if (grub_is_using_legacy_shim_lock_protocol () == true)
{
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__) || defined(__x86_64__) || defined (__aarch64__)
grub_dprintf ("linux", "using legacy shim_lock protocol, falling back to legacy Linux kernel loader\n");
err = grub_cmd_linux_efi_fallback (cmd, argc, argv);
@@ -499,7 +499,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
kernel_size = grub_file_size (file);
if (grub_arch_efi_linux_load_image_header (file, &lh) != GRUB_ERR_NONE)
-#if !defined(__i386__) && !defined(__x86_64__)
+#if !defined(__i386__) && !defined(__x86_64__) && !defined (__aarch64__)
goto fail;
#else
goto fallback;
--
2.50.1

View File

@@ -0,0 +1,44 @@
From 5407ea9241aae78a724f00126e4e6b49dd08e92b Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Wed, 9 Oct 2024 09:16:37 +0100
Subject: [PATCH 02/13] modules: Strip .llvm_addrsig sections and similar
Currently GRUB modules built with Clang or GCC have several sections
which we don't actually need or support. We already have a list of
sections to skip in genmod.sh and this patch adds the following
sections to that list (as well as a few newlines):
- .note.gnu.property
- .llvm*
Note that the glob there won't work without a new enough linker but the
failure is just reversion to the status quo. So, that's not a big problem.
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Jan Setje-Eilers <jan.setjeeilers@oracle.com>
Signed-off-by: Mate Kukri <mate.kukri@canonical.com>
Reviewed-By: Vladimir Serbinenko <phcoder@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/genmod.sh.in | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/grub-core/genmod.sh.in b/grub-core/genmod.sh.in
index e57c4d920..337753c57 100644
--- a/grub-core/genmod.sh.in
+++ b/grub-core/genmod.sh.in
@@ -57,8 +57,11 @@ if test x@TARGET_APPLE_LINKER@ != x1; then
@TARGET_STRIP@ --strip-unneeded \
-K grub_mod_init -K grub_mod_fini \
-K _grub_mod_init -K _grub_mod_fini \
- -R .note.gnu.gold-version -R .note.GNU-stack \
+ -R .note.GNU-stack \
+ -R .note.gnu.gold-version \
+ -R .note.gnu.property \
-R .gnu.build.attributes \
+ -R '.llvm*' \
-R .rel.gnu.build.attributes \
-R .rela.gnu.build.attributes \
-R .eh_frame -R .rela.eh_frame -R .rel.eh_frame \
--
2.50.1

View File

@@ -0,0 +1,43 @@
From 43b0319936f51dc6b4cba3518449195924e83dc8 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Sat, 26 Apr 2025 15:39:43 +0800
Subject: [PATCH 3/4] efi/chainloader: fallback to direct image execution
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
When the shim loader protocol is unavailable and UEFI Secure Boot is
enabled, fall back to chainloading the PE/COFF image by manually
relocating it to the loaded memory address and jumping to its entry
point, rather than invoking UEFI to load and start the image. This
fallback supports booting binaries validated by shims vendor DB, even
if they are not present in the UEFI DB.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/loader/efi/chainloader.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
index 1830de223..7e2847217 100644
--- a/grub-core/loader/efi/chainloader.c
+++ b/grub-core/loader/efi/chainloader.c
@@ -805,10 +805,14 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
#ifdef SUPPORT_SECURE_BOOT
/* FIXME is secure boot possible also with universal binaries? */
- if (debug_secureboot || (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED && grub_secure_validate ((void *)address, size)))
+ if (debug_secureboot ||
+ (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED &&
+ grub_is_using_legacy_shim_lock_protocol () == true &&
+ grub_secure_validate ((void *)address, size)))
{
struct grub_secureboot_chainloader_context *sb_context;
+ grub_dprintf ("chain", "Falling back to PE loader\n");
sb_context = grub_malloc (sizeof (*sb_context));
if (!sb_context)
goto fail;
--
2.50.1

View File

@@ -0,0 +1,41 @@
From 5696bf9bebb17b6a7837163149287586b90dc14c Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Wed, 9 Oct 2024 09:16:38 +0100
Subject: [PATCH 03/13] modules: Don't allocate space for non-allocable
sections
Currently when loading GRUB modules we allocate space for all sections
including those without SHF_ALLOC set. We then copy the sections that
/do/ have SHF_ALLOC set into the allocated memory leaving some of our
allocation untouched forever. Additionally, on platforms with GOT fixups
and trampolines we currently compute alignment round-ups for the
sections and sections with sh_size = 0. This patch removes the extra
space from the allocation computation and makes the allocation
computation loop skip empty sections as the loading loop does.
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Jan Setje-Eilers <jan.setjeeilers@oracle.com>
Signed-off-by: Mate Kukri <mate.kukri@canonical.com>
Reviewed-By: Vladimir Serbinenko <phcoder@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/kern/dl.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
index 73a5b9e0f..6af031072 100644
--- a/grub-core/kern/dl.c
+++ b/grub-core/kern/dl.c
@@ -241,6 +241,9 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
i < e->e_shnum;
i++, s = (const Elf_Shdr *)((const char *) s + e->e_shentsize))
{
+ if (s->sh_size == 0 || !(s->sh_flags & SHF_ALLOC))
+ continue;
+
tsize = ALIGN_UP (tsize, s->sh_addralign) + s->sh_size;
if (talign < s->sh_addralign)
talign = s->sh_addralign;
--
2.50.1

View File

@@ -0,0 +1,97 @@
From e2a6f238920ab547d216ce96283bca6faf36378b Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Wed, 30 Apr 2025 21:16:50 +0800
Subject: [PATCH 4/4] efi/chainloader: fix missing file_path in loaded_image
The file_path field in the loaded_image protocol may be unset for
chainloaded target images. When this occurs, populate the file_path to
ensure the target image can use the loaded_image protocol for location
dependent operations, such as reading configuration files from its
directory. Without this, the chainloaded image may fail to start due to
an inability to reconfigure itself properly.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/loader/efi/chainloader.c | 52 +++++++++++++++++-------------
1 file changed, 29 insertions(+), 23 deletions(-)
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
index 7e2847217..9b70e1e61 100644
--- a/grub-core/loader/efi/chainloader.c
+++ b/grub-core/loader/efi/chainloader.c
@@ -222,6 +222,29 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
return file_path;
}
+static grub_efi_device_path_t *
+grub_efi_get_media_file_path (grub_efi_device_path_t *dp)
+{
+ while (1)
+ {
+ grub_efi_uint8_t type;
+ grub_efi_uint8_t subtype;
+
+ if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
+ break;
+
+ type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
+ subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
+
+ if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE && subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE)
+ return dp;
+
+ dp = GRUB_EFI_NEXT_DEVICE_PATH (dp);
+ }
+
+ return NULL;
+}
+
#ifdef SUPPORT_SECURE_BOOT
#define SHIM_LOCK_GUID \
{ 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
@@ -461,29 +484,6 @@ relocate_coff (pe_coff_loader_image_context_t *context, void *data)
return GRUB_EFI_SUCCESS;
}
-static grub_efi_device_path_t *
-grub_efi_get_media_file_path (grub_efi_device_path_t *dp)
-{
- while (1)
- {
- grub_efi_uint8_t type;
- grub_efi_uint8_t subtype;
-
- if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
- break;
-
- type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
- subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
-
- if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE && subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE)
- return dp;
-
- dp = GRUB_EFI_NEXT_DEVICE_PATH (dp);
- }
-
- return NULL;
-}
-
static grub_efi_boolean_t
handle_image (struct grub_secureboot_chainloader_context *load_context)
{
@@ -881,6 +881,12 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
}
loaded_image->device_handle = dev_handle;
+ if (! loaded_image->file_path)
+ {
+ grub_dprintf ("chain", "bailout file_path\n");
+ loaded_image->file_path = grub_efi_get_media_file_path (file_path);
+ }
+
/* Build load options with arguments from chainloader command line. */
if (cmdline)
{
--
2.50.1

View File

@@ -0,0 +1,170 @@
From db7bee2f67310219f7431b28a4b6c1385ac211d3 Mon Sep 17 00:00:00 2001
From: Mate Kukri <mate.kukri@canonical.com>
Date: Wed, 9 Oct 2024 09:16:39 +0100
Subject: [PATCH 04/13] modules: Load module sections at page-aligned addresses
Currently we load module sections at whatever alignment gcc+ld happened
to dump into the ELF section header which is often less then the page
size. Since NX protections are page based this alignment must be rounded
up to page size on platforms supporting NX protections. This patch
switches EFI platforms to load module sections at 4 KiB page-aligned
addresses. It then changes the allocation size computation and the
loader code in grub_dl_load_segments() to align the locations and sizes
up to these boundaries and fills any added padding with zeros. All of
this happens before relocations are applied, so the relocations factor
that in with no change.
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Jan Setje-Eilers <jan.setjeeilers@oracle.com>
Signed-off-by: Mate Kukri <mate.kukri@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/kern/dl.c | 54 ++++++++++++++++++++++++++++++---------------
1 file changed, 36 insertions(+), 18 deletions(-)
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
index 6af031072..b384412d1 100644
--- a/grub-core/kern/dl.c
+++ b/grub-core/kern/dl.c
@@ -33,6 +33,10 @@
#include <grub/cache.h>
#include <grub/i18n.h>
+#ifdef GRUB_MACHINE_EFI
+#include <grub/efi/memory.h>
+#endif
+
/* Platforms where modules are in a readonly area of memory. */
#if defined(GRUB_MACHINE_QEMU)
#define GRUB_MODULES_MACHINE_READONLY
@@ -40,10 +44,11 @@
#ifdef GRUB_MACHINE_EFI
#include <grub/efi/sb.h>
+#define DL_ALIGN GRUB_EFI_PAGE_SIZE
+#else
+#define DL_ALIGN 1
#endif
-
-
#pragma GCC diagnostic ignored "-Wcast-align"
grub_dl_t grub_dl_head = 0;
@@ -228,25 +233,34 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
{
unsigned i;
const Elf_Shdr *s;
- grub_size_t tsize = 0, talign = 1;
+ grub_size_t tsize = 0, talign = 1, arch_addralign = 1;
#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) && \
!defined (__loongarch__) && !defined (__s390x__)
grub_size_t tramp;
+ grub_size_t tramp_align;
grub_size_t got;
+ grub_size_t got_align;
grub_err_t err;
#endif
char *ptr;
+ arch_addralign = DL_ALIGN;
+
for (i = 0, s = (const Elf_Shdr *)((const char *) e + e->e_shoff);
i < e->e_shnum;
i++, s = (const Elf_Shdr *)((const char *) s + e->e_shentsize))
{
+ grub_size_t sh_addralign;
+ grub_size_t sh_size;
+
if (s->sh_size == 0 || !(s->sh_flags & SHF_ALLOC))
continue;
- tsize = ALIGN_UP (tsize, s->sh_addralign) + s->sh_size;
- if (talign < s->sh_addralign)
- talign = s->sh_addralign;
+ sh_addralign = ALIGN_UP (s->sh_addralign, arch_addralign);
+ sh_size = ALIGN_UP (s->sh_size, sh_addralign);
+
+ tsize = ALIGN_UP (tsize, sh_addralign) + sh_size;
+ talign = grub_max (talign, sh_addralign);
}
#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) && \
@@ -254,12 +268,12 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
err = grub_arch_dl_get_tramp_got_size (e, &tramp, &got);
if (err)
return err;
- tsize += ALIGN_UP (tramp, GRUB_ARCH_DL_TRAMP_ALIGN);
- if (talign < GRUB_ARCH_DL_TRAMP_ALIGN)
- talign = GRUB_ARCH_DL_TRAMP_ALIGN;
- tsize += ALIGN_UP (got, GRUB_ARCH_DL_GOT_ALIGN);
- if (talign < GRUB_ARCH_DL_GOT_ALIGN)
- talign = GRUB_ARCH_DL_GOT_ALIGN;
+ tramp_align = grub_max (GRUB_ARCH_DL_TRAMP_ALIGN, arch_addralign);
+ tsize += ALIGN_UP (tramp, tramp_align);
+ talign = grub_max (talign, tramp_align);
+ got_align = grub_max (GRUB_ARCH_DL_GOT_ALIGN, arch_addralign);
+ tsize += ALIGN_UP (got, got_align);
+ talign = grub_max (talign, got_align);
#endif
#ifdef GRUB_MACHINE_EMU
@@ -276,6 +290,9 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
i < e->e_shnum;
i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize))
{
+ grub_size_t sh_addralign = ALIGN_UP (s->sh_addralign, arch_addralign);
+ grub_size_t sh_size = ALIGN_UP (s->sh_size, sh_addralign);
+
if (s->sh_flags & SHF_ALLOC)
{
grub_dl_segment_t seg;
@@ -288,17 +305,18 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
{
void *addr;
- ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, s->sh_addralign);
+ ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, sh_addralign);
addr = ptr;
- ptr += s->sh_size;
+ ptr += sh_size;
switch (s->sh_type)
{
case SHT_PROGBITS:
grub_memcpy (addr, (char *) e + s->sh_offset, s->sh_size);
+ grub_memset ((char *) addr + s->sh_size, 0, sh_size - s->sh_size);
break;
case SHT_NOBITS:
- grub_memset (addr, 0, s->sh_size);
+ grub_memset (addr, 0, sh_size);
break;
}
@@ -307,7 +325,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
else
seg->addr = 0;
- seg->size = s->sh_size;
+ seg->size = sh_size;
seg->section = i;
seg->next = mod->segment;
mod->segment = seg;
@@ -315,11 +333,11 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
}
#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) && \
!defined (__loongarch__) && !defined (__s390x__)
- ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_TRAMP_ALIGN);
+ ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, tramp_align);
mod->tramp = ptr;
mod->trampptr = ptr;
ptr += tramp;
- ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_GOT_ALIGN);
+ ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, got_align);
mod->got = ptr;
mod->gotptr = ptr;
ptr += got;
--
2.50.1

View File

@@ -0,0 +1,236 @@
From ae9bf340b0ae7b0b8f968e89468d7eac13583a8d Mon Sep 17 00:00:00 2001
From: Mate Kukri <mate.kukri@canonical.com>
Date: Wed, 9 Oct 2024 09:16:40 +0100
Subject: [PATCH 05/13] nx: Add memory attribute get/set API
For NX we need to set the page access permission attributes for write
and execute permissions. This patch adds two new primitives, grub_set_mem_attrs()
and grub_clear_mem_attrs(), and associated constants definitions used
for that purpose. For most platforms it adds a dummy implementation.
On EFI platforms it implements the primitives using the EFI Memory
Attribute Protocol, defined in UEFI 2.10 specification.
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Jan Setje-Eilers <jan.setjeeilers@oracle.com>
Signed-off-by: Mate Kukri <mate.kukri@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/kern/efi/mm.c | 109 ++++++++++++++++++++++++++++++++++++++++
include/grub/efi/api.h | 25 +++++++++
include/grub/mm.h | 35 +++++++++++++
3 files changed, 169 insertions(+)
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
index 9b1d3add7..93566e916 100644
--- a/grub-core/kern/efi/mm.c
+++ b/grub-core/kern/efi/mm.c
@@ -736,3 +736,112 @@ grub_efi_get_ram_base(grub_addr_t *base_addr)
return GRUB_ERR_NONE;
}
#endif
+
+static grub_uint64_t
+grub_mem_attrs_to_uefi_mem_attrs (grub_mem_attr_t attrs)
+{
+ grub_efi_uint64_t ret = GRUB_EFI_MEMORY_RP | GRUB_EFI_MEMORY_RO | GRUB_EFI_MEMORY_XP;
+
+ if (attrs & GRUB_MEM_ATTR_R)
+ ret &= ~GRUB_EFI_MEMORY_RP;
+
+ if (attrs & GRUB_MEM_ATTR_W)
+ ret &= ~GRUB_EFI_MEMORY_RO;
+
+ if (attrs & GRUB_MEM_ATTR_X)
+ ret &= ~GRUB_EFI_MEMORY_XP;
+
+ return ret;
+}
+
+static grub_mem_attr_t
+uefi_mem_attrs_to_grub_mem_attrs (grub_efi_uint64_t attrs)
+{
+ grub_mem_attr_t ret = GRUB_MEM_ATTR_R | GRUB_MEM_ATTR_W | GRUB_MEM_ATTR_X;
+
+ if (attrs & GRUB_EFI_MEMORY_RP)
+ ret &= ~GRUB_MEM_ATTR_R;
+
+ if (attrs & GRUB_EFI_MEMORY_RO)
+ ret &= ~GRUB_MEM_ATTR_W;
+
+ if (attrs & GRUB_EFI_MEMORY_XP)
+ ret &= ~GRUB_MEM_ATTR_X;
+
+ return ret;
+}
+
+grub_err_t
+grub_get_mem_attrs (grub_addr_t addr, grub_size_t size, grub_mem_attr_t *attrs)
+{
+ grub_efi_memory_attribute_protocol_t *proto;
+ grub_efi_physical_address_t physaddr = addr;
+ static grub_guid_t protocol_guid = GRUB_EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID;
+ grub_efi_status_t efi_status;
+ grub_efi_uint64_t efi_attrs;
+
+ if (physaddr & (GRUB_EFI_PAGE_SIZE - 1) || size & (GRUB_EFI_PAGE_SIZE - 1) || size == 0 || attrs == NULL)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "%s() called with invalid arguments", __FUNCTION__);
+
+ proto = grub_efi_locate_protocol (&protocol_guid, 0);
+ if (proto == NULL)
+ {
+ /* No protocol -> do nothing, all memory is RWX in boot services */
+ *attrs = GRUB_MEM_ATTR_R | GRUB_MEM_ATTR_W | GRUB_MEM_ATTR_X;
+ return GRUB_ERR_NONE;
+ }
+
+ efi_status = proto->get_memory_attributes (proto, physaddr, size, &efi_attrs);
+ if (efi_status != GRUB_EFI_SUCCESS)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "%s() called with invalid arguments", __FUNCTION__);
+
+ *attrs = uefi_mem_attrs_to_grub_mem_attrs (efi_attrs);
+
+ grub_dprintf ("nx", "get 0x%" PRIxGRUB_ADDR "-0x%" PRIxGRUB_ADDR ":%c%c%c\n",
+ addr, addr + size - 1,
+ (*attrs & GRUB_MEM_ATTR_R) ? 'r' : '-',
+ (*attrs & GRUB_MEM_ATTR_W) ? 'w' : '-',
+ (*attrs & GRUB_MEM_ATTR_X) ? 'x' : '-');
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_update_mem_attrs (grub_addr_t addr, grub_size_t size,
+ grub_mem_attr_t set_attrs, grub_mem_attr_t clear_attrs)
+{
+ grub_efi_memory_attribute_protocol_t *proto;
+ grub_efi_physical_address_t physaddr = addr;
+ static grub_guid_t protocol_guid = GRUB_EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID;
+ grub_efi_status_t efi_status = GRUB_EFI_SUCCESS;
+ grub_efi_uint64_t uefi_set_attrs, uefi_clear_attrs;
+
+ if (physaddr & (GRUB_EFI_PAGE_SIZE - 1) || size & (GRUB_EFI_PAGE_SIZE - 1) || size == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "%s() called with invalid arguments", __FUNCTION__);
+
+ proto = grub_efi_locate_protocol (&protocol_guid, 0);
+ if (proto == NULL)
+ /* No protocol -> do nothing, all memory is RWX in boot services */
+ return GRUB_ERR_NONE;
+
+ uefi_set_attrs = grub_mem_attrs_to_uefi_mem_attrs (set_attrs);
+ uefi_clear_attrs = grub_mem_attrs_to_uefi_mem_attrs (clear_attrs);
+ if (uefi_set_attrs)
+ efi_status = proto->set_memory_attributes (proto, physaddr, size, uefi_set_attrs);
+ if (efi_status == GRUB_EFI_SUCCESS && uefi_clear_attrs)
+ efi_status = proto->clear_memory_attributes (proto, physaddr, size, uefi_clear_attrs);
+
+ if (efi_status != GRUB_EFI_SUCCESS)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "%s() called with invalid arguments", __FUNCTION__);
+
+ grub_dprintf ("nx", "set +%s%s%s -%s%s%s on 0x%" PRIxGRUB_ADDR "-0x%" PRIxGRUB_ADDR "\n",
+ (set_attrs & GRUB_MEM_ATTR_R) ? "r" : "",
+ (set_attrs & GRUB_MEM_ATTR_W) ? "w" : "",
+ (set_attrs & GRUB_MEM_ATTR_X) ? "x" : "",
+ (clear_attrs & GRUB_MEM_ATTR_R) ? "r" : "",
+ (clear_attrs & GRUB_MEM_ATTR_W) ? "w" : "",
+ (clear_attrs & GRUB_MEM_ATTR_X) ? "x" : "",
+ addr, addr + size - 1);
+
+ return GRUB_ERR_NONE;
+}
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index 975b90b09..5d1aada34 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -394,6 +394,11 @@
{ 0x93, 0x87, 0x6d, 0x87, 0x60, 0x50, 0xdc, 0x67 } \
}
+#define GRUB_EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID \
+ { 0xf4560cf6, 0x40ec, 0x4b4a, \
+ { 0xa1, 0x92, 0xbf, 0x1d, 0x57, 0xd0, 0xb1, 0x89 } \
+ }
+
struct grub_efi_sal_system_table
{
grub_uint32_t signature;
@@ -2105,4 +2110,24 @@ struct grub_efi_ip6_config_manual_address {
};
typedef struct grub_efi_ip6_config_manual_address grub_efi_ip6_config_manual_address_t;
+struct grub_efi_memory_attribute_protocol
+{
+ grub_efi_status_t (__grub_efi_api *get_memory_attributes) (
+ struct grub_efi_memory_attribute_protocol *this,
+ grub_efi_physical_address_t base_address,
+ grub_efi_uint64_t length,
+ grub_efi_uint64_t *attributes);
+ grub_efi_status_t (__grub_efi_api *set_memory_attributes) (
+ struct grub_efi_memory_attribute_protocol *this,
+ grub_efi_physical_address_t base_address,
+ grub_efi_uint64_t length,
+ grub_efi_uint64_t attributes);
+ grub_efi_status_t (__grub_efi_api *clear_memory_attributes) (
+ struct grub_efi_memory_attribute_protocol *this,
+ grub_efi_physical_address_t base_address,
+ grub_efi_uint64_t length,
+ grub_efi_uint64_t attributes);
+};
+typedef struct grub_efi_memory_attribute_protocol grub_efi_memory_attribute_protocol_t;
+
#endif /* ! GRUB_EFI_API_HEADER */
diff --git a/include/grub/mm.h b/include/grub/mm.h
index 75894dbbe..494133b4c 100644
--- a/include/grub/mm.h
+++ b/include/grub/mm.h
@@ -23,6 +23,7 @@
#include <grub/err.h>
#include <grub/types.h>
#include <grub/symbol.h>
+#include <grub/err.h>
#include <config.h>
#ifndef NULL
@@ -86,6 +87,40 @@ grub_calloc (grub_size_t nmemb, grub_size_t size)
void *EXPORT_FUNC(grub_calloc) (grub_size_t nmemb, grub_size_t size);
#endif
+typedef grub_uint64_t grub_mem_attr_t;
+
+#define GRUB_MEM_ATTR_R ((grub_mem_attr_t) 0x0000000000000004)
+#define GRUB_MEM_ATTR_W ((grub_mem_attr_t) 0x0000000000000002)
+#define GRUB_MEM_ATTR_X ((grub_mem_attr_t) 0x0000000000000001)
+
+#ifdef GRUB_MACHINE_EFI
+grub_err_t EXPORT_FUNC(grub_get_mem_attrs) (grub_addr_t addr,
+ grub_size_t size,
+ grub_mem_attr_t *attrs);
+grub_err_t EXPORT_FUNC(grub_update_mem_attrs) (grub_addr_t addr,
+ grub_size_t size,
+ grub_mem_attr_t set_attrs,
+ grub_mem_attr_t clear_attrs);
+#else /* !GRUB_MACHINE_EFI */
+static inline grub_err_t
+grub_get_mem_attrs (grub_addr_t addr __attribute__((__unused__)),
+ grub_size_t size __attribute__((__unused__)),
+ grub_mem_attr_t *attrs)
+{
+ *attrs = GRUB_MEM_ATTR_R | GRUB_MEM_ATTR_W | GRUB_MEM_ATTR_X;
+ return GRUB_ERR_NONE;
+}
+
+static inline grub_err_t
+grub_update_mem_attrs (grub_addr_t addr __attribute__((__unused__)),
+ grub_size_t size __attribute__((__unused__)),
+ grub_mem_attr_t set_attrs __attribute__((__unused__)),
+ grub_mem_attr_t clear_attrs __attribute__((__unused__)))
+{
+ return GRUB_ERR_NONE;
+}
+#endif /* GRUB_MACHINE_EFI */
+
void grub_mm_check_real (const char *file, int line);
#define grub_mm_check() grub_mm_check_real (GRUB_FILE, __LINE__);
--
2.50.1

View File

@@ -0,0 +1,135 @@
From 12e6c0f3ca23481a552cf3acd5365b1356add5c0 Mon Sep 17 00:00:00 2001
From: Mate Kukri <mate.kukri@canonical.com>
Date: Wed, 9 Oct 2024 09:16:41 +0100
Subject: [PATCH 06/13] nx: Set page permissions for loaded modules
For NX we need to set write and executable permissions on the sections
of GRUB modules when we load them. All allocatable sections are marked
readable. In addition:
- SHF_WRITE sections are marked as writable,
- and SHF_EXECINSTR sections are marked as executable.
Where relevant for the platform the tramp and GOT areas are marked non-writable.
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Jan Setje-Eilers <jan.setjeeilers@oracle.com>
Signed-off-by: Mate Kukri <mate.kukri@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/kern/dl.c | 91 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 90 insertions(+), 1 deletion(-)
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
index b384412d1..da31db218 100644
--- a/grub-core/kern/dl.c
+++ b/grub-core/kern/dl.c
@@ -636,6 +636,94 @@ grub_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
return GRUB_ERR_NONE;
}
+/* Only define this on EFI to save space in core. */
+#ifdef GRUB_MACHINE_EFI
+static grub_err_t
+grub_dl_set_mem_attrs (grub_dl_t mod, void *ehdr)
+{
+ unsigned i;
+ const Elf_Shdr *s;
+ const Elf_Ehdr *e = ehdr;
+ grub_err_t err;
+#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) && \
+ !defined (__loongarch__)
+ grub_size_t arch_addralign = GRUB_DL_ALIGN;
+ grub_addr_t tgaddr;
+ grub_size_t tgsz;
+#endif
+
+ for (i = 0, s = (const Elf_Shdr *) ((const char *) e + e->e_shoff);
+ i < e->e_shnum;
+ i++, s = (const Elf_Shdr *) ((const char *) s + e->e_shentsize))
+ {
+ grub_dl_segment_t seg;
+ grub_uint64_t set_attrs = GRUB_MEM_ATTR_R;
+ grub_uint64_t clear_attrs = GRUB_MEM_ATTR_W | GRUB_MEM_ATTR_X;
+
+ for (seg = mod->segment; seg; seg = seg->next)
+ /* Does this ELF section's index match GRUB DL segment? */
+ if (seg->section == s->sh_info)
+ break;
+
+ /* No GRUB DL segment found for this ELF section, skip it. */
+ if (!seg)
+ continue;
+
+ if (seg->size == 0 || !(s->sh_flags & SHF_ALLOC))
+ continue;
+
+ if (s->sh_flags & SHF_WRITE)
+ {
+ set_attrs |= GRUB_MEM_ATTR_W;
+ clear_attrs &= ~GRUB_MEM_ATTR_W;
+ }
+
+ if (s->sh_flags & SHF_EXECINSTR)
+ {
+ set_attrs |= GRUB_MEM_ATTR_X;
+ clear_attrs &= ~GRUB_MEM_ATTR_X;
+ }
+
+ err = grub_update_mem_attrs ((grub_addr_t) seg->addr, seg->size,
+ set_attrs, clear_attrs);
+ if (err != GRUB_ERR_NONE)
+ return err;
+ }
+
+#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) && \
+ !defined (__loongarch__)
+ tgaddr = grub_min ((grub_addr_t) mod->tramp, (grub_addr_t) mod->got);
+ tgsz = grub_max ((grub_addr_t) mod->trampptr, (grub_addr_t) mod->gotptr) - tgaddr;
+
+ if (tgsz)
+ {
+ tgsz = ALIGN_UP (tgsz, arch_addralign);
+
+ if (tgaddr < (grub_addr_t) mod->base ||
+ tgsz > (grub_addr_t) -1 - tgaddr ||
+ tgaddr + tgsz > (grub_addr_t) mod->base + mod->sz)
+ return grub_error (GRUB_ERR_BUG,
+ "BUG: trying to protect pages outside of module "
+ "allocation (\"%s\"): module base %p, size 0x%"
+ PRIxGRUB_SIZE "; tramp/GOT base 0x%" PRIxGRUB_ADDR
+ ", size 0x%" PRIxGRUB_SIZE,
+ mod->name, mod->base, mod->sz, tgaddr, tgsz);
+ err = grub_update_mem_attrs (tgaddr, tgsz, GRUB_MEM_ATTR_R | GRUB_MEM_ATTR_X, GRUB_MEM_ATTR_W);
+ if (err != GRUB_ERR_NONE)
+ return err;
+ }
+#endif
+
+ return GRUB_ERR_NONE;
+}
+#else
+static grub_err_t
+grub_dl_set_mem_attrs (grub_dl_t mod __attribute__ ((unused)), void *ehdr __attribute__ ((unused)))
+{
+ return GRUB_ERR_NONE;
+}
+#endif
+
/* Load a module from core memory. */
grub_dl_t
grub_dl_load_core_noinit (void *addr, grub_size_t size)
@@ -682,7 +770,8 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size)
|| grub_dl_resolve_dependencies (mod, e)
|| grub_dl_load_segments (mod, e)
|| grub_dl_resolve_symbols (mod, e)
- || grub_dl_relocate_symbols (mod, e))
+ || grub_dl_relocate_symbols (mod, e)
+ || grub_dl_set_mem_attrs (mod, e))
{
mod->fini = 0;
grub_dl_unload (mod);
--
2.50.1

View File

@@ -0,0 +1,54 @@
From fad957c68f157ae0c30cab52d69d0dc4e74b9909 Mon Sep 17 00:00:00 2001
From: Mate Kukri <mate.kukri@canonical.com>
Date: Wed, 9 Oct 2024 09:16:42 +0100
Subject: [PATCH 07/13] nx: Set the NX compatible flag for the GRUB EFI images
For NX the GRUB binary has to announce that it is compatible with the
NX feature. This implies that when loading the executable GRUB image
several attributes are true:
- the binary doesn't need an executable stack,
- the binary doesn't need sections to be both executable and writable,
- the binary knows how to use the EFI Memory Attributes Protocol on code
it is loading.
This patch:
- adds a definition for the PE DLL Characteristics flag GRUB_PE32_NX_COMPAT,
- changes grub-mkimage to set that flag.
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Jan Setje-Eilers <jan.setjeeilers@oracle.com>
Signed-off-by: Mate Kukri <mate.kukri@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
include/grub/efi/pe32.h | 2 ++
util/mkimage.c | 1 +
2 files changed, 3 insertions(+)
diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h
index 4e6e9d254..9887e14b2 100644
--- a/include/grub/efi/pe32.h
+++ b/include/grub/efi/pe32.h
@@ -231,6 +231,8 @@ struct grub_pe64_optional_header
#define GRUB_PE32_SUBSYSTEM_EFI_APPLICATION 10
+#define GRUB_PE32_NX_COMPAT 0x0100
+
#define GRUB_PE32_NUM_DATA_DIRECTORIES 16
struct grub_pe32_section_table
diff --git a/util/mkimage.c b/util/mkimage.c
index 6c0581836..5d7a47e70 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -1453,6 +1453,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdangling-pointer"
#endif
+ PE_OHDR (o32, o64, dll_characteristics) = grub_host_to_target16 (GRUB_PE32_NX_COMPAT);
PE_OHDR (o32, o64, header_size) = grub_host_to_target32 (header_size);
PE_OHDR (o32, o64, entry_addr) = grub_host_to_target32 (layout.start_address);
PE_OHDR (o32, o64, image_base) = 0;
--
2.50.1

View File

@@ -0,0 +1,233 @@
From 24187b38b89d011f748e462b9ae684316c5e4d57 Mon Sep 17 00:00:00 2001
From: Julian Andres Klode <julian.klode@canonical.com>
Date: Tue, 8 Jul 2025 21:21:13 +0100
Subject: [PATCH 08/13] efi: Provide wrappers for load_image, start_image and
unload_image
These can be used to register a different implementation later,
for example, when shim provides a protocol with those functions.
Signed-off-by: Julian Andres Klode <julian.klode@canonical.com>
Signed-off-by: Mate Kukri <mate.kukri@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/kern/efi/efi.c | 57 ++++++++++++++++++++++++++++++
grub-core/loader/efi/chainloader.c | 13 +++----
grub-core/loader/efi/linux.c | 12 +++----
include/grub/efi/efi.h | 42 ++++++++++++++++++++++
4 files changed, 109 insertions(+), 15 deletions(-)
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index b674816aa..1e330a2cc 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -1109,3 +1109,60 @@ grub_efi_find_configuration_table (const grub_guid_t *target_guid)
return 0;
}
+
+static const grub_efi_loader_t *override_loader = NULL;
+
+grub_err_t
+grub_efi_register_loader (const grub_efi_loader_t *loader)
+{
+ if (override_loader != NULL)
+ return grub_error (GRUB_ERR_BUG, "trying to register different loader");
+ override_loader = loader;
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_efi_unregister_loader (const grub_efi_loader_t *loader)
+{
+ if (loader != override_loader)
+ return grub_error (GRUB_ERR_BUG, "trying to unregister different loader");
+
+ override_loader = NULL;
+ return GRUB_ERR_NONE;
+}
+
+grub_efi_status_t
+grub_efi_load_image (grub_efi_boolean_t boot_policy,
+ grub_efi_handle_t parent_image_handle,
+ grub_efi_device_path_t *file_path, void *source_buffer,
+ grub_efi_uintn_t source_size,
+ grub_efi_handle_t *image_handle)
+{
+ if (override_loader != NULL)
+ return override_loader->load_image (boot_policy, parent_image_handle,
+ file_path, source_buffer, source_size,
+ image_handle);
+ return grub_efi_system_table->boot_services->load_image (
+ boot_policy, parent_image_handle, file_path, source_buffer, source_size,
+ image_handle);
+}
+
+grub_efi_status_t
+grub_efi_start_image (grub_efi_handle_t image_handle,
+ grub_efi_uintn_t *exit_data_size,
+ grub_efi_char16_t **exit_data)
+{
+ if (override_loader != NULL)
+ return override_loader->start_image (image_handle, exit_data_size,
+ exit_data);
+ return grub_efi_system_table->boot_services->start_image (
+ image_handle, exit_data_size, exit_data);
+}
+
+grub_efi_status_t
+grub_efi_unload_image (grub_efi_handle_t image_handle)
+{
+ if (override_loader != NULL)
+ return override_loader->unload_image (image_handle);
+ return grub_efi_system_table->boot_services->unload_image (image_handle);
+}
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
index 655aaad9d..04b9e3553 100644
--- a/grub-core/loader/efi/chainloader.c
+++ b/grub-core/loader/efi/chainloader.c
@@ -64,14 +64,12 @@ grub_chainloader_unload (void *context)
{
grub_efi_handle_t image_handle = (grub_efi_handle_t) context;
grub_efi_loaded_image_t *loaded_image;
- grub_efi_boot_services_t *b;
loaded_image = grub_efi_get_loaded_image (image_handle);
if (loaded_image != NULL)
grub_free (loaded_image->load_options);
- b = grub_efi_system_table->boot_services;
- b->unload_image (image_handle);
+ grub_efi_unload_image (image_handle);
grub_dl_unref (my_mod);
return GRUB_ERR_NONE;
@@ -87,7 +85,7 @@ grub_chainloader_boot (void *context)
grub_efi_char16_t *exit_data = NULL;
b = grub_efi_system_table->boot_services;
- status = b->start_image (image_handle, &exit_data_size, &exit_data);
+ status = grub_efi_start_image (image_handle, &exit_data_size, &exit_data);
if (status != GRUB_EFI_SUCCESS)
{
if (exit_data)
@@ -826,9 +824,8 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
}
#endif
- status = b->load_image (0, grub_efi_image_handle, file_path,
- boot_image, size,
- &image_handle);
+ status = grub_efi_load_image (0, grub_efi_image_handle, file_path,
+ boot_image, size, &image_handle);
#ifdef SUPPORT_SECURE_BOOT
if (status == GRUB_EFI_SECURITY_VIOLATION && grub_efi_get_secureboot () != GRUB_EFI_SECUREBOOT_MODE_ENABLED)
{
@@ -907,7 +904,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
b->free_pages (address, pages);
if (image_handle != NULL)
- b->unload_image (image_handle);
+ grub_efi_unload_image (image_handle);
grub_dl_unref (my_mod);
diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
index bfbd95aee..58be3c9f8 100644
--- a/grub-core/loader/efi/linux.c
+++ b/grub-core/loader/efi/linux.c
@@ -187,7 +187,6 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args)
{
grub_efi_memory_mapped_device_path_t *mempath;
grub_efi_handle_t image_handle;
- grub_efi_boot_services_t *b;
grub_efi_status_t status;
grub_efi_loaded_image_t *loaded_image;
int len;
@@ -207,10 +206,9 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args)
mempath[1].header.subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
mempath[1].header.length = sizeof (grub_efi_device_path_t);
- b = grub_efi_system_table->boot_services;
- status = b->load_image (0, grub_efi_image_handle,
- (grub_efi_device_path_t *) mempath,
- (void *) addr, size, &image_handle);
+ status = grub_efi_load_image (0, grub_efi_image_handle,
+ (grub_efi_device_path_t *)mempath,
+ (void *)addr, size, &image_handle);
if (status != GRUB_EFI_SUCCESS)
return grub_error (GRUB_ERR_BAD_OS, "cannot load image");
@@ -235,14 +233,14 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args)
(grub_uint8_t *) args, len, NULL);
grub_dprintf ("linux", "starting image %p\n", image_handle);
- status = b->start_image (image_handle, 0, NULL);
+ status = grub_efi_start_image (image_handle, 0, NULL);
/* When successful, not reached */
grub_error (GRUB_ERR_BAD_OS, "start_image() returned 0x%" PRIxGRUB_EFI_UINTN_T, status);
grub_efi_free_pages ((grub_addr_t) loaded_image->load_options,
GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
unload:
- b->unload_image (image_handle);
+ grub_efi_unload_image (image_handle);
return grub_errno;
}
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index 87aa1ce25..6c7bfc865 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -135,6 +135,48 @@ grub_err_t grub_arch_efi_linux_load_image_header(grub_file_t file,
grub_err_t grub_arch_efi_linux_boot_image(grub_addr_t addr, grub_size_t size,
char *args);
+grub_efi_status_t
+EXPORT_FUNC (grub_efi_load_image) (grub_efi_boolean_t boot_policy,
+ grub_efi_handle_t parent_image_handle,
+ grub_efi_device_path_t *file_path,
+ void *source_buffer, grub_efi_uintn_t source_size,
+ grub_efi_handle_t *image_handle);
+
+grub_efi_status_t
+EXPORT_FUNC (grub_efi_start_image) (grub_efi_handle_t image_handle,
+ grub_efi_uintn_t *exit_data_size,
+ grub_efi_char16_t **exit_data);
+
+grub_efi_status_t
+EXPORT_FUNC (grub_efi_unload_image) (grub_efi_handle_t image_handle);
+
+typedef struct grub_efi_loader
+{
+ grub_efi_status_t (__grub_efi_api *load_image) (grub_efi_boolean_t boot_policy,
+ grub_efi_handle_t parent_image_handle,
+ grub_efi_device_path_t *file_path,
+ void *source_buffer,
+ grub_efi_uintn_t source_size,
+ grub_efi_handle_t *image_handle);
+
+ grub_efi_status_t (__grub_efi_api *start_image) (grub_efi_handle_t image_handle,
+ grub_efi_uintn_t *exit_data_size,
+ grub_efi_char16_t **exit_data);
+
+ grub_efi_status_t (__grub_efi_api *exit) (grub_efi_handle_t image_handle,
+ grub_efi_status_t exit_status,
+ grub_efi_uintn_t exit_data_size,
+ grub_efi_char16_t *exit_data);
+
+ grub_efi_status_t (__grub_efi_api *unload_image) (grub_efi_handle_t image_handle);
+} grub_efi_loader_t;
+
+grub_err_t
+EXPORT_FUNC (grub_efi_register_loader) (const grub_efi_loader_t *loader);
+
+grub_err_t
+EXPORT_FUNC (grub_efi_unregister_loader) (const grub_efi_loader_t *loader);
+
grub_addr_t grub_efi_section_addr (const char *section);
void grub_efi_mm_init (void);
--
2.50.1

View File

@@ -0,0 +1,186 @@
From bd43c9011d3006a93b22861b6d3d18f62076d5f7 Mon Sep 17 00:00:00 2001
From: Mate Kukri <mate.kukri@canonical.com>
Date: Tue, 8 Jul 2025 21:21:14 +0100
Subject: [PATCH 09/13] efi/sb: Add support for the shim loader protocol
Use loader protocol for image verification where available, otherwise
fall back to the old shim lock protocol.
Signed-off-by: Mate Kukri <mate.kukri@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/kern/efi/sb.c | 59 ++++++++++++++++++++----------------
grub-core/loader/efi/linux.c | 6 ++--
include/grub/efi/api.h | 5 +++
include/grub/efi/sb.h | 2 +-
4 files changed, 42 insertions(+), 30 deletions(-)
diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c
index 8d3e41360..48d1ea968 100644
--- a/grub-core/kern/efi/sb.c
+++ b/grub-core/kern/efi/sb.c
@@ -31,8 +31,10 @@
#include <grub/verify.h>
static grub_guid_t shim_lock_guid = GRUB_EFI_SHIM_LOCK_GUID;
+static grub_guid_t shim_loader_guid = GRUB_EFI_SHIM_IMAGE_LOADER_GUID;
-static bool shim_lock_enabled = false;
+static grub_efi_loader_t *shim_loader = NULL;
+static grub_efi_shim_lock_protocol_t *shim_lock = NULL;
/*
* Determine whether we're in secure boot mode.
@@ -95,14 +97,6 @@ grub_efi_get_secureboot (void)
if (!(attr & GRUB_EFI_VARIABLE_RUNTIME_ACCESS) && *moksbstate == 1)
{
secureboot = GRUB_EFI_SECUREBOOT_MODE_DISABLED;
- /*
- * TODO: Replace this all with shim's LoadImage protocol, delegating policy to it.
- *
- * We need to set shim_lock_enabled here because we disabled secure boot
- * validation *inside* shim but not in the firmware, so we set this variable
- * here to trigger that code path, whereas the actual verifier is not enabled.
- */
- shim_lock_enabled = true;
goto out;
}
@@ -183,15 +177,25 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)),
static grub_err_t
shim_lock_verifier_write (void *context __attribute__ ((unused)), void *buf, grub_size_t size)
{
- grub_efi_shim_lock_protocol_t *sl = grub_efi_locate_protocol (&shim_lock_guid, 0);
+ grub_efi_handle_t image_handle;
- if (!sl)
- return grub_error (GRUB_ERR_ACCESS_DENIED, N_("shim_lock protocol not found"));
+ if (shim_loader != NULL)
+ {
+ if (shim_loader->load_image (false, grub_efi_image_handle, NULL, buf, size, &image_handle) != GRUB_EFI_SUCCESS)
+ /* If verification fails no handle is produced */
+ return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad shim loader signature"));
- if (sl->verify (buf, size) != GRUB_EFI_SUCCESS)
- return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad shim signature"));
+ shim_loader->unload_image (image_handle);
+ return GRUB_ERR_NONE;
+ }
+ if (shim_lock != NULL)
+ {
+ if (shim_lock->verify (buf, size) != GRUB_EFI_SUCCESS)
+ return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad shim lock signature"));
+ return GRUB_ERR_NONE;
+ }
- return GRUB_ERR_NONE;
+ return grub_error (GRUB_ERR_ACCESS_DENIED, N_("shim protocols not found"));
}
struct grub_file_verifier shim_lock_verifier =
@@ -205,11 +209,17 @@ void
grub_shim_lock_verifier_setup (void)
{
struct grub_module_header *header;
- grub_efi_shim_lock_protocol_t *sl =
- grub_efi_locate_protocol (&shim_lock_guid, 0);
- /* shim_lock is missing, check if GRUB image is built with --disable-shim-lock. */
- if (!sl)
+ /* Secure Boot is off. Ignore shim. */
+ if (grub_efi_get_secureboot () != GRUB_EFI_SECUREBOOT_MODE_ENABLED)
+ return;
+
+ /* Find both shim protocols. */
+ shim_loader = grub_efi_locate_protocol (&shim_loader_guid, 0);
+ shim_lock = grub_efi_locate_protocol (&shim_lock_guid, 0);
+
+ /* shim is missing, check if GRUB image is built with --disable-shim-lock. */
+ if (shim_loader == NULL && shim_lock == NULL)
{
FOR_MODULES (header)
{
@@ -218,21 +228,18 @@ grub_shim_lock_verifier_setup (void)
}
}
- /* Secure Boot is off. Do not load shim_lock. */
- if (grub_efi_get_secureboot () != GRUB_EFI_SECUREBOOT_MODE_ENABLED)
- return;
-
/* Enforce shim_lock_verifier. */
grub_verifier_register (&shim_lock_verifier);
- shim_lock_enabled = true;
+ /* Register shim loader if supported. */
+ grub_efi_register_loader (shim_loader);
grub_env_set ("shim_lock", "y");
grub_env_export ("shim_lock");
}
bool
-grub_is_shim_lock_enabled (void)
+grub_is_using_legacy_shim_lock_protocol (void)
{
- return shim_lock_enabled;
+ return (shim_loader == NULL && shim_lock != NULL) ? true : false;
}
diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
index 58be3c9f8..993d18546 100644
--- a/grub-core/loader/efi/linux.c
+++ b/grub-core/loader/efi/linux.c
@@ -460,10 +460,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_dl_ref (my_mod);
- if (grub_is_shim_lock_enabled () == true)
+ if (grub_is_using_legacy_shim_lock_protocol () == true)
{
#if defined(__i386__) || defined(__x86_64__)
- grub_dprintf ("linux", "shim_lock enabled, falling back to legacy Linux kernel loader\n");
+ grub_dprintf ("linux", "using legacy shim_lock protocol, falling back to legacy Linux kernel loader\n");
err = grub_cmd_linux_x86_legacy (cmd, argc, argv);
@@ -472,7 +472,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
else
goto fail;
#else
- grub_dprintf ("linux", "shim_lock enabled, trying Linux kernel EFI stub loader\n");
+ grub_dprintf ("linux", "using legacy shim_lock protocol on non-x86, only db verifiable kernels will work\n");
#endif
}
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index 5d1aada34..72017eaa7 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -364,6 +364,11 @@
{ 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } \
}
+#define GRUB_EFI_SHIM_IMAGE_LOADER_GUID \
+ { 0x1f492041, 0xfadb, 0x4e59, \
+ {0x9e, 0x57, 0x7c, 0xaf, 0xe7, 0x3a, 0x55, 0xab } \
+ }
+
#define GRUB_EFI_RNG_PROTOCOL_GUID \
{ 0x3152bca5, 0xeade, 0x433d, \
{ 0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44 } \
diff --git a/include/grub/efi/sb.h b/include/grub/efi/sb.h
index 49a9ad01c..4cae88376 100644
--- a/include/grub/efi/sb.h
+++ b/include/grub/efi/sb.h
@@ -32,7 +32,7 @@ extern grub_uint8_t
EXPORT_FUNC (grub_efi_get_secureboot) (void);
extern bool
-EXPORT_FUNC (grub_is_shim_lock_enabled) (void);
+EXPORT_FUNC (grub_is_using_legacy_shim_lock_protocol) (void);
extern void
grub_shim_lock_verifier_setup (void);
--
2.50.1

View File

@@ -0,0 +1,100 @@
From b0e9763fd6b4c7635d190439973276ed57ee7af8 Mon Sep 17 00:00:00 2001
From: Mate Kukri <mate.kukri@canonical.com>
Date: Tue, 8 Jul 2025 21:21:15 +0100
Subject: [PATCH 10/13] efi/sb: Add API for retrieving shim loader image
handles
Not reusing these handles will result in image measurements showing up
twice in the event log.
Signed-off-by: Mate Kukri <mate.kukri@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/kern/efi/sb.c | 34 ++++++++++++++++++++++++++++++++--
include/grub/efi/sb.h | 4 ++++
2 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c
index 48d1ea968..4409e03c5 100644
--- a/grub-core/kern/efi/sb.c
+++ b/grub-core/kern/efi/sb.c
@@ -36,6 +36,8 @@ static grub_guid_t shim_loader_guid = GRUB_EFI_SHIM_IMAGE_LOADER_GUID;
static grub_efi_loader_t *shim_loader = NULL;
static grub_efi_shim_lock_protocol_t *shim_lock = NULL;
+static grub_efi_handle_t last_verified_image_handle = NULL;
+
/*
* Determine whether we're in secure boot mode.
*
@@ -181,11 +183,25 @@ shim_lock_verifier_write (void *context __attribute__ ((unused)), void *buf, gru
if (shim_loader != NULL)
{
+ if (last_verified_image_handle != NULL)
+ {
+ /*
+ * Unload the previous image because ownership of the handle was
+ * not transfered to a loader, and a new image is being loaded.
+ */
+ shim_loader->unload_image (last_verified_image_handle);
+ last_verified_image_handle = NULL;
+ }
+
if (shim_loader->load_image (false, grub_efi_image_handle, NULL, buf, size, &image_handle) != GRUB_EFI_SUCCESS)
- /* If verification fails no handle is produced */
+ /* If verification fails no handle is produced. */
return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad shim loader signature"));
- shim_loader->unload_image (image_handle);
+ /*
+ * Not unloading the image here because chainloader and linux
+ * might use this handle to avoid double TPM measurements.
+ */
+ last_verified_image_handle = image_handle;
return GRUB_ERR_NONE;
}
if (shim_lock != NULL)
@@ -243,3 +259,17 @@ grub_is_using_legacy_shim_lock_protocol (void)
{
return (shim_loader == NULL && shim_lock != NULL) ? true : false;
}
+
+grub_efi_handle_t
+grub_efi_get_last_verified_image_handle (void)
+{
+ grub_efi_handle_t tmp = last_verified_image_handle;
+
+ /*
+ * This function is intended to act as a "transfer of ownership"
+ * of the handle. We set it to NULL so that it cannot be buggily
+ * retrieved more than once and reused for the wrong image.
+ */
+ last_verified_image_handle = NULL;
+ return tmp;
+}
diff --git a/include/grub/efi/sb.h b/include/grub/efi/sb.h
index 4cae88376..149005ced 100644
--- a/include/grub/efi/sb.h
+++ b/include/grub/efi/sb.h
@@ -21,6 +21,7 @@
#include <grub/types.h>
#include <grub/dl.h>
+#include <grub/efi/api.h>
#define GRUB_EFI_SECUREBOOT_MODE_UNSET 0
#define GRUB_EFI_SECUREBOOT_MODE_UNKNOWN 1
@@ -34,6 +35,9 @@ EXPORT_FUNC (grub_efi_get_secureboot) (void);
extern bool
EXPORT_FUNC (grub_is_using_legacy_shim_lock_protocol) (void);
+extern grub_efi_handle_t
+EXPORT_FUNC (grub_efi_get_last_verified_image_handle) (void);
+
extern void
grub_shim_lock_verifier_setup (void);
#else
--
2.50.1

View File

@@ -0,0 +1,107 @@
From 918af0d51fe594a7e6cbb0fe8a4889e773bba4bb Mon Sep 17 00:00:00 2001
From: Mate Kukri <mate.kukri@canonical.com>
Date: Tue, 8 Jul 2025 21:21:16 +0100
Subject: [PATCH 11/13] loader/efi/chainloader: Use shim loader image handle
where available
Not reusing these handles will result in image measurements showing up
twice in the event log.
Signed-off-by: Mate Kukri <mate.kukri@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/loader/efi/chainloader.c | 67 ++++++++++++++++--------------
1 file changed, 36 insertions(+), 31 deletions(-)
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
index 04b9e3553..1830de223 100644
--- a/grub-core/loader/efi/chainloader.c
+++ b/grub-core/loader/efi/chainloader.c
@@ -33,6 +33,7 @@
#include <grub/efi/efi.h>
#include <grub/efi/disk.h>
#include <grub/efi/memory.h>
+#include <grub/efi/sb.h>
#include <grub/command.h>
#include <grub/i18n.h>
#include <grub/net.h>
@@ -824,41 +825,45 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
}
#endif
- status = grub_efi_load_image (0, grub_efi_image_handle, file_path,
+ image_handle = grub_efi_get_last_verified_image_handle ();
+ if (image_handle == NULL)
+ {
+ status = grub_efi_load_image (0, grub_efi_image_handle, file_path,
boot_image, size, &image_handle);
#ifdef SUPPORT_SECURE_BOOT
- if (status == GRUB_EFI_SECURITY_VIOLATION && grub_efi_get_secureboot () != GRUB_EFI_SECUREBOOT_MODE_ENABLED)
- {
- /* If it failed with security violation while not in secure boot mode,
- the firmware might be broken. We try to workaround on that by forcing
- the SB method! (bsc#887793) */
- struct grub_secureboot_chainloader_context *sb_context;
-
- grub_dprintf ("chain", "Possible firmware flaw! Security violation while not in secure boot mode.\n");
- sb_context = grub_malloc (sizeof (*sb_context));
- if (!sb_context)
- goto fail;
- sb_context->cmdline = cmdline;
- sb_context->cmdline_len = cmdline_len;
- sb_context->fsize = size;
- sb_context->dev_handle = dev_handle;
- sb_context->address = address;
- sb_context->pages = pages;
- sb_context->file_path = file_path;
- grub_file_close (file);
- grub_loader_set_ex (grub_secureboot_chainloader_boot,
- grub_secureboot_chainloader_unload, sb_context, 0);
- return 0;
- }
+ if (status == GRUB_EFI_SECURITY_VIOLATION && grub_efi_get_secureboot () != GRUB_EFI_SECUREBOOT_MODE_ENABLED)
+ {
+ /* If it failed with security violation while not in secure boot mode,
+ the firmware might be broken. We try to workaround on that by forcing
+ the SB method! (bsc#887793) */
+ struct grub_secureboot_chainloader_context *sb_context;
+
+ grub_dprintf ("chain", "Possible firmware flaw! Security violation while not in secure boot mode.\n");
+ sb_context = grub_malloc (sizeof (*sb_context));
+ if (!sb_context)
+ goto fail;
+ sb_context->cmdline = cmdline;
+ sb_context->cmdline_len = cmdline_len;
+ sb_context->fsize = size;
+ sb_context->dev_handle = dev_handle;
+ sb_context->address = address;
+ sb_context->pages = pages;
+ sb_context->file_path = file_path;
+ grub_file_close (file);
+ grub_loader_set_ex (grub_secureboot_chainloader_boot,
+ grub_secureboot_chainloader_unload, sb_context, 0);
+ return 0;
+ }
#endif
- if (status != GRUB_EFI_SUCCESS)
- {
- if (status == GRUB_EFI_OUT_OF_RESOURCES)
- grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of resources");
- else
- grub_error (GRUB_ERR_BAD_OS, "cannot load image");
+ if (status != GRUB_EFI_SUCCESS)
+ {
+ if (status == GRUB_EFI_OUT_OF_RESOURCES)
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of resources");
+ else
+ grub_error (GRUB_ERR_BAD_OS, "cannot load image");
- goto fail;
+ goto fail;
+ }
}
/* LoadImage does not set a device handler when the image is
--
2.50.1

View File

@@ -0,0 +1,50 @@
From e4855838e156b3509a2fd774c69ab4681e774427 Mon Sep 17 00:00:00 2001
From: Mate Kukri <mate.kukri@canonical.com>
Date: Tue, 8 Jul 2025 21:21:17 +0100
Subject: [PATCH 12/13] loader/efi/linux: Use shim loader image handle where
available
Not reusing these handles will result in image measurements showing up
twice in the event log.
On the occasion add missing grub_free() call.
Signed-off-by: Mate Kukri <mate.kukri@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/loader/efi/linux.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
index 993d18546..394df6039 100644
--- a/grub-core/loader/efi/linux.c
+++ b/grub-core/loader/efi/linux.c
@@ -206,11 +206,20 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args)
mempath[1].header.subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
mempath[1].header.length = sizeof (grub_efi_device_path_t);
- status = grub_efi_load_image (0, grub_efi_image_handle,
- (grub_efi_device_path_t *)mempath,
- (void *)addr, size, &image_handle);
- if (status != GRUB_EFI_SUCCESS)
- return grub_error (GRUB_ERR_BAD_OS, "cannot load image");
+ image_handle = grub_efi_get_last_verified_image_handle ();
+ if (image_handle == NULL)
+ {
+ status = grub_efi_load_image (0, grub_efi_image_handle,
+ (grub_efi_device_path_t *) mempath,
+ (void *) addr, size, &image_handle);
+ if (status != GRUB_EFI_SUCCESS)
+ {
+ grub_free (mempath);
+ return grub_error (GRUB_ERR_BAD_OS, "cannot load image");
+ }
+ }
+
+ grub_free (mempath);
grub_dprintf ("linux", "linux command line: '%s'\n", args);
--
2.50.1

View File

@@ -0,0 +1,32 @@
From d36e8d9cc3bf2bbaf90d15fdb7a7594275892ec7 Mon Sep 17 00:00:00 2001
From: Daniel Kiper <daniel.kiper@oracle.com>
Date: Wed, 16 Oct 2024 15:04:17 +0200
Subject: [PATCH 13/13] nx: Rename GRUB_DL_ALIGN to DL_ALIGN
Rename has been skipped by mistake in the original commit.
Fixes: 94649c026 (nx: Set page permissions for loaded modules)
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-by: Sudeep Holla <sudeep.holla@arm.com>
Reviewed-by: Ross Philipson <ross.philipson@oracle.com>
---
grub-core/kern/dl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
index da31db218..cf1a5a24d 100644
--- a/grub-core/kern/dl.c
+++ b/grub-core/kern/dl.c
@@ -647,7 +647,7 @@ grub_dl_set_mem_attrs (grub_dl_t mod, void *ehdr)
grub_err_t err;
#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) && \
!defined (__loongarch__)
- grub_size_t arch_addralign = GRUB_DL_ALIGN;
+ grub_size_t arch_addralign = DL_ALIGN;
grub_addr_t tgaddr;
grub_size_t tgsz;
#endif
--
2.50.1

View File

@@ -0,0 +1,93 @@
Factoring out get_entry_from_efivar helper to reduce code duplication
and add support for LoaderEntryDefault.
Index: grub-2.12/grub-core/normal/menu.c
===================================================================
--- grub-2.12.orig/grub-core/normal/menu.c
+++ grub-2.12/grub-core/normal/menu.c
@@ -741,6 +741,38 @@ workaround_snapshot_menu_default_entry (
return;
}
+#ifdef GRUB_MACHINE_EFI
+static int
+get_entry_from_efivar(grub_menu_t menu, const char* efivar)
+{
+ grub_efi_status_t status;
+ grub_size_t entry_size;
+ grub_efi_char16_t *entry_efi = NULL;
+ char *entry_name = NULL;
+ int entry_index = -1;
+ status = grub_efi_get_variable(efivar,
+ &grub_efi_loader_guid,
+ &entry_size,
+ (void**) &entry_efi);
+ if (status == GRUB_EFI_SUCCESS)
+ {
+ grub_efi_char16_t *src = entry_efi;
+ int size = 0;
+ while (*src++)
+ size++;
+ if (size != 0)
+ {
+ entry_name = grub_malloc (size * sizeof (char));
+ grub_utf16_to_utf8 ((grub_uint8_t*) entry_name,
+ (grub_uint16_t*) entry_efi, size);
+ entry_index = search_entry (menu, entry_name);
+ }
+ }
+ grub_free(entry_name);
+ return entry_index;
+}
+#endif
+
#define GRUB_MENU_PAGE_SIZE 10
/* Show the menu and handle menu entry selection. Returns the menu entry
@@ -766,36 +798,19 @@ run_menu (grub_menu_t menu, int nested,
const char* val = grub_env_get ("enable_blscfg");
if (val && (val[0] == '1' || val[0] == 'y'))
{
- grub_efi_status_t status;
- int oneshot_entry_index;
- grub_efi_char16_t *oneshot_entry_efi = NULL;
- char *oneshot_entry = NULL;
- grub_size_t oneshot_entry_size;
- status = grub_efi_get_variable("LoaderEntryOneShot",
- &grub_efi_loader_guid,
- &oneshot_entry_size,
- (void**) &oneshot_entry_efi);
- if (status == GRUB_EFI_SUCCESS)
+ int oneshot_entry, default_entry_efi;
+ oneshot_entry = get_entry_from_efivar(menu, "LoaderEntryOneShot");
+ if (oneshot_entry != -1)
{
- grub_efi_char16_t *src = oneshot_entry_efi;
- int size = 0;
- while (*src++)
- size++;
- if (size == 0)
+ default_entry = oneshot_entry;
+ grub_efi_set_variable_to_string("LoaderEntryOneShot",
+ &grub_efi_loader_guid, "", 0);
+ } else {
+ default_entry_efi = get_entry_from_efivar(menu, "LoaderEntryDefault");
+ if (default_entry_efi != -1)
{
- oneshot_entry = grub_malloc (size * sizeof (char));
- grub_utf16_to_utf8 ((grub_uint8_t*) oneshot_entry,
- (grub_uint16_t*) oneshot_entry_efi, size);
- oneshot_entry_index = search_entry (menu, oneshot_entry);
- if (oneshot_entry_index != -1)
- {
- default_entry = oneshot_entry_index;
- grub_efi_set_variable_to_string("LoaderEntryOneShot",
- &grub_efi_loader_guid, "", 0);
- }
- grub_free(oneshot_entry);
+ default_entry = default_entry_efi;
}
- grub_free(oneshot_entry_efi);
}
}
#endif

View File

@@ -0,0 +1,59 @@
From be4670936bc86a14f20a8c9c40d34c45aad0d0b2 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Fri, 25 Jul 2025 13:50:23 +0800
Subject: [PATCH] Constant-time grub_crypto_memcmp()
Use the constant-time algorithm to compare the given memory blocks.
The code is extracted from the upstream commit:
0739d24cd1648531d0708d1079ff6bbfa6140268
Fix: bsc#1234959
Signed-off-by: Gary Lin <glin@suse.com>
---
grub-core/lib/crypto.c | 23 ++++++++++++++++-------
1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c
index 396f764..19db787 100644
--- a/grub-core/lib/crypto.c
+++ b/grub-core/lib/crypto.c
@@ -433,19 +433,28 @@ grub_crypto_gcry_error (gcry_err_code_t in)
return GRUB_ACCESS_DENIED;
}
+/*
+ * Compare byte arrays of length LEN, return 1 if it's not same,
+ * 0, otherwise.
+ */
int
-grub_crypto_memcmp (const void *a, const void *b, grub_size_t n)
+grub_crypto_memcmp (const void *b1, const void *b2, grub_size_t len)
{
- register grub_size_t counter = 0;
- const grub_uint8_t *pa, *pb;
+ const grub_uint8_t *a = b1;
+ const grub_uint8_t *b = b2;
+ int ab, ba;
+ grub_size_t i;
- for (pa = a, pb = b; n; pa++, pb++, n--)
+ /* Constant-time compare. */
+ for (i = 0, ab = 0, ba = 0; i < len; i++)
{
- if (*pa != *pb)
- counter++;
+ /* If a[i] != b[i], either ab or ba will be negative. */
+ ab |= a[i] - b[i];
+ ba |= b[i] - a[i];
}
- return !!counter;
+ /* 'ab | ba' is negative when buffers are not equal, extract sign bit. */
+ return ((unsigned int)(ab | ba) >> (sizeof(unsigned int) * 8 - 1)) & 1;
}
#ifndef GRUB_UTIL
--
2.43.0

View File

@@ -0,0 +1,20 @@
In x86 Legacy BIOS mode, on some Lenovo machines, the grub menu is not
visible, although it demonstrably has been drawn (bsc#1245636).
A workaround to avoid this is to not use page flipping mode.
This patch enforces that no page flipping is used in the VBE framebuffer
backend for i386-pc.
--- a/grub-core/video/i386/pc/vbe.c
+++ b/grub-core/video/i386/pc/vbe.c
@@ -1137,7 +1137,8 @@ grub_video_vbe_setup (unsigned int width, unsigned int height,
page_size = framebuffer.mode_info.pitch * framebuffer.mode_info.height;
- if (vram_size >= 2 * page_size)
+ /* avoid page flipping mode (bsc#1245636) */
+ if (0 && vram_size >= 2 * page_size)
err = grub_video_fb_setup (mode_type, mode_mask,
&framebuffer.mode_info,
framebuffer.ptr,

View File

@@ -1,3 +1,75 @@
-------------------------------------------------------------------
Tue Sep 23 08:47:49 UTC 2025 - Steffen Winterfeldt <snwint@suse.com>
- turn off page flipping for i386-pc using VBE video backend (bsc#1245636)
* grub2-i386-pc-no-pageflipping.patch
-------------------------------------------------------------------
Mon Sep 22 07:15:00 UTC 2025 - Michael Chang <mchang@suse.com>
- Fix boot hangs in setting up serial console when ACPI SPCR table is present
and redirection is disabled (bsc#1249088)
* 0001-term-ns8250-spcr-Return-if-redirection-is-disabled.patch
-------------------------------------------------------------------
Tue Sep 9 14:25:42 UTC 2025 - Danilo Spinella <danilo.spinella@suse.com>
- Add support for `LoaderEntryDefault` EFI variable
* grub2-bls-loader-entry-default.patch
-------------------------------------------------------------------
Tue Sep 2 07:46:46 UTC 2025 - Gary Ching-Pang Lin <glin@suse.com>
- Optimize PBKDF2 to reduce the decryption time
* 0001-lib-crypto-Introduce-new-HMAC-functions-to-reuse-buf.patch
* 0002-lib-pbkdf2-Optimize-PBKDF2-by-reusing-HMAC-handle.patch
* 0001-kern-misc-Implement-faster-grub_memcpy-for-aligned-b.patch
-------------------------------------------------------------------
Mon Aug 11 02:57:30 UTC 2025 - Michael Chang <mchang@suse.com>
- UEFI NX support and NX Linux loader using shim loader protocol (bsc#1205588)
(jsc#PED-13361)
* 0001-modules-Make-.module_license-read-only.patch
* 0002-modules-Strip-.llvm_addrsig-sections-and-similar.patch
* 0003-modules-Don-t-allocate-space-for-non-allocable-secti.patch
* 0004-modules-Load-module-sections-at-page-aligned-address.patch
* 0005-nx-Add-memory-attribute-get-set-API.patch
* 0006-nx-Set-page-permissions-for-loaded-modules.patch
* 0007-nx-Set-the-NX-compatible-flag-for-the-GRUB-EFI-image.patch
* 0008-efi-Provide-wrappers-for-load_image-start_image-and-.patch
* 0009-efi-sb-Add-support-for-the-shim-loader-protocol.patch
* 0010-efi-sb-Add-API-for-retrieving-shim-loader-image-hand.patch
* 0011-loader-efi-chainloader-Use-shim-loader-image-handle-.patch
* 0012-loader-efi-linux-Use-shim-loader-image-handle-where-.patch
* 0013-nx-Rename-GRUB_DL_ALIGN-to-DL_ALIGN.patch
- Fallback for legacy shim lock protocol while secure boot is enabled
* 0001-linux-fallback-to-EFI-handover-on-x86_64.patch
* 0002-linux-fallback-to-direct-PE-entry-boot-on-arm64.patch
* 0003-efi-chainloader-fallback-to-direct-image-execution.patch
* 0004-efi-chainloader-fix-missing-file_path-in-loaded_imag.patch
- Removed patch
* 0001-xen_boot-add-missing-grub_arch_efi_linux_load_image_.patch
-------------------------------------------------------------------
Thu Aug 7 06:19:53 UTC 2025 - Michael Chang <mchang@suse.com>
- Fix timeout when loading initrd via http after PPC CAS reboot (bsc#1245953)
* 0001-tcp-Fix-TCP-port-number-reused-on-reboot.patch
-------------------------------------------------------------------
Mon Aug 4 06:44:01 UTC 2025 - Michael Chang <mchang@suse.com>
- Skip mount point in grub_find_device function (bsc#1246231)
* 0001-getroot-Skip-mount-points-in-grub_find_device.patch
-------------------------------------------------------------------
Fri Jul 25 05:56:26 UTC 2025 - Gary Ching-Pang Lin <glin@suse.com>
- Fix CVE-2024-56738: side-channel attack due to not constant-time
algorithm in grub_crypto_memcmp (bsc#1234959)
* grub2-constant-time-grub_crypto_memcmp.patch
-------------------------------------------------------------------
Wed Jul 16 11:19:21 UTC 2025 - Michael Chang <mchang@suse.com>
@@ -168,7 +240,7 @@ Mon Mar 17 08:27:29 UTC 2025 - Michael Chang <mchang@suse.com>
Thu Mar 13 06:50:37 UTC 2025 - Gary Ching-Pang Lin <glin@suse.com>
- Update the patch to fix "SRK not matched" errors when unsealing
the key (bsc#1232411)
the key (bsc#1232411) (bsc#1247242)
* 0001-tpm2-Add-extra-RSA-SRK-types.patch
-------------------------------------------------------------------

View File

@@ -2,6 +2,7 @@
# spec file for package grub2
#
# Copyright (c) 2025 SUSE LLC
# Copyright (c) 2025 SUSE LLC and contributors
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -369,7 +370,6 @@ Patch176: 0001-ieee1275-ofdisk-retry-on-open-and-read-failure.patch
Patch177: 0002-Restrict-cryptsetup-key-file-permission-for-better-s.patch
Patch178: 0001-openfw-Ensure-get_devargs-and-get_devname-functions-.patch
Patch179: 0002-prep_loadenv-Fix-regex-for-Open-Firmware-device-spec.patch
Patch180: 0001-xen_boot-add-missing-grub_arch_efi_linux_load_image_.patch
Patch181: 0001-font-Try-memdisk-fonts-with-the-same-name.patch
Patch182: 0001-Make-grub.cfg-compatible-to-old-binaries.patch
Patch183: grub2-change-bash-completion-dir.patch
@@ -493,6 +493,32 @@ Patch315: 0001-test-Fix-f-test-on-files-over-network.patch
Patch316: 0002-http-Return-HTTP-status-code-in-http_establish.patch
Patch317: 0003-docs-Clarify-test-for-files-on-TFTP-and-HTTP.patch
Patch318: 0004-tftp-Fix-hang-when-file-is-a-directory.patch
Patch319: grub2-constant-time-grub_crypto_memcmp.patch
Patch320: 0001-getroot-Skip-mount-points-in-grub_find_device.patch
Patch321: 0001-tcp-Fix-TCP-port-number-reused-on-reboot.patch
Patch322: 0001-modules-Make-.module_license-read-only.patch
Patch323: 0002-modules-Strip-.llvm_addrsig-sections-and-similar.patch
Patch324: 0003-modules-Don-t-allocate-space-for-non-allocable-secti.patch
Patch325: 0004-modules-Load-module-sections-at-page-aligned-address.patch
Patch326: 0005-nx-Add-memory-attribute-get-set-API.patch
Patch327: 0006-nx-Set-page-permissions-for-loaded-modules.patch
Patch328: 0007-nx-Set-the-NX-compatible-flag-for-the-GRUB-EFI-image.patch
Patch329: 0008-efi-Provide-wrappers-for-load_image-start_image-and-.patch
Patch330: 0009-efi-sb-Add-support-for-the-shim-loader-protocol.patch
Patch331: 0010-efi-sb-Add-API-for-retrieving-shim-loader-image-hand.patch
Patch332: 0011-loader-efi-chainloader-Use-shim-loader-image-handle-.patch
Patch333: 0012-loader-efi-linux-Use-shim-loader-image-handle-where-.patch
Patch334: 0013-nx-Rename-GRUB_DL_ALIGN-to-DL_ALIGN.patch
Patch335: 0001-linux-fallback-to-EFI-handover-on-x86_64.patch
Patch336: 0002-linux-fallback-to-direct-PE-entry-boot-on-arm64.patch
Patch337: 0003-efi-chainloader-fallback-to-direct-image-execution.patch
Patch338: 0004-efi-chainloader-fix-missing-file_path-in-loaded_imag.patch
Patch339: 0001-lib-crypto-Introduce-new-HMAC-functions-to-reuse-buf.patch
Patch340: 0002-lib-pbkdf2-Optimize-PBKDF2-by-reusing-HMAC-handle.patch
Patch341: 0001-kern-misc-Implement-faster-grub_memcpy-for-aligned-b.patch
Patch342: grub2-bls-loader-entry-default.patch
Patch343: 0001-term-ns8250-spcr-Return-if-redirection-is-disabled.patch
Patch344: grub2-i386-pc-no-pageflipping.patch
%if 0%{?suse_version} < 1600
Requires: gettext-runtime