fix the vulnerabilities announced on February 18th, 2025

Signed-off-by: Qiumiao Zhang <zhangqiumiao1@huawei.com>
This commit is contained in:
Qiumiao Zhang 2025-02-24 10:54:44 +00:00
parent ca2f63b444
commit 2087a1b402
32 changed files with 2847 additions and 2 deletions

View File

@ -0,0 +1,187 @@
From 450a423b1074d0f0f4909038cb40b54ac95cd241 Mon Sep 17 00:00:00 2001
From: Glenn Washburn <development@efficientek.com>
Date: Thu, 9 Dec 2021 11:14:51 -0600
Subject: [PATCH 01/30] cryptodisk: Refactor to discard have_it global
The global "have_it" was never used by the crypto-backends, but was used to
determine if a crypto-backend successfully mounted a cryptodisk with a given
UUID. This is not needed however, because grub_device_iterate() will return
1 if and only if grub_cryptodisk_scan_device() returns 1. And
grub_cryptodisk_scan_device() will now only return 1 if a search_uuid has
been specified and a cryptodisk was successfully setup by a crypto-backend or
a cryptodisk of the requested UUID is already open.
To implement this grub_cryptodisk_scan_device_real() is modified to return
a cryptodisk or NULL on failure and having the appropriate grub_errno set to
indicated failure. Note that grub_cryptodisk_scan_device_real() will fail now
with a new errno GRUB_ERR_BAD_MODULE when none of the cryptodisk backend
modules succeed in identifying the source disk.
With this change grub_device_iterate() will return 1 when a crypto device is
successfully decrypted or when the source device has already been successfully
opened. Prior to this change, trying to mount an already successfully opened
device would trigger an error with the message "no such cryptodisk found",
which is at best misleading. The mount should silently succeed in this case,
which is what happens with this patch.
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/disk/cryptodisk.c | 56 +++++++++++++++++++++++--------------
1 file changed, 35 insertions(+), 21 deletions(-)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 6883f48..66f5e8c 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -807,7 +807,7 @@ grub_util_cryptodisk_get_uuid (grub_disk_t disk)
#endif
-static int check_boot, have_it;
+static int check_boot;
static char *search_uuid;
static void
@@ -819,7 +819,7 @@ cryptodisk_close (grub_cryptodisk_t dev)
grub_free (dev);
}
-static grub_err_t
+static grub_cryptodisk_t
grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
{
grub_err_t err;
@@ -829,13 +829,13 @@ grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
dev = grub_cryptodisk_get_by_source_disk (source);
if (dev)
- return GRUB_ERR_NONE;
+ return dev;
FOR_CRYPTODISK_DEVS (cr)
{
dev = cr->scan (source, search_uuid, check_boot);
if (grub_errno)
- return grub_errno;
+ return NULL;
if (!dev)
continue;
@@ -843,16 +843,16 @@ grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
if (err)
{
cryptodisk_close (dev);
- return err;
+ return NULL;
}
grub_cryptodisk_insert (dev, name, source);
- have_it = 1;
-
- return GRUB_ERR_NONE;
+ return dev;
}
- return GRUB_ERR_NONE;
+
+ grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk module can handle this device");
+ return NULL;
}
#ifdef GRUB_UTIL
@@ -906,8 +906,10 @@ static int
grub_cryptodisk_scan_device (const char *name,
void *data __attribute__ ((unused)))
{
- grub_err_t err;
+ int ret = 0;
grub_disk_t source;
+ grub_cryptodisk_t dev;
+ grub_errno = GRUB_ERR_NONE;
/* Try to open disk. */
source = grub_disk_open (name);
@@ -917,13 +919,26 @@ grub_cryptodisk_scan_device (const char *name,
return 0;
}
- err = grub_cryptodisk_scan_device_real (name, source);
+ dev = grub_cryptodisk_scan_device_real (name, source);
+ if (dev)
+ {
+ ret = (search_uuid != NULL && grub_strcasecmp (search_uuid, dev->uuid) == 0);
+ goto cleanup;
+ }
- grub_disk_close (source);
-
- if (err)
+ /*
+ * Do not print error when err is GRUB_ERR_BAD_MODULE to avoid many unhelpful
+ * error messages.
+ */
+ if (grub_errno == GRUB_ERR_BAD_MODULE)
+ grub_error_pop ();
+
+ if (grub_errno != GRUB_ERR_NONE)
grub_print_error ();
- return have_it && search_uuid ? 1 : 0;
+
+ cleanup:
+ grub_disk_close (source);
+ return ret;
}
static grub_err_t
@@ -934,9 +949,9 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
if (argc < 1 && !state[1].set && !state[2].set)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
- have_it = 0;
if (state[0].set)
{
+ int found_uuid;
grub_cryptodisk_t dev;
dev = grub_cryptodisk_get_by_uuid (args[0]);
@@ -949,10 +964,10 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
check_boot = state[2].set;
search_uuid = args[0];
- grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
+ found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
search_uuid = NULL;
- if (!have_it)
+ if (!found_uuid)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such cryptodisk found");
return GRUB_ERR_NONE;
}
@@ -966,7 +981,6 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
}
else
{
- grub_err_t err;
grub_disk_t disk;
grub_cryptodisk_t dev;
char *diskname;
@@ -1002,13 +1016,13 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
return GRUB_ERR_NONE;
}
- err = grub_cryptodisk_scan_device_real (diskname, disk);
+ dev = grub_cryptodisk_scan_device_real (diskname, disk);
grub_disk_close (disk);
if (disklast)
*disklast = ')';
- return err;
+ return (dev == NULL) ? grub_errno : GRUB_ERR_NONE;
}
}
--
2.33.0

View File

@ -0,0 +1,32 @@
From 542b8e8cb389ab411f8b5044fd3e8bcffc22d2f9 Mon Sep 17 00:00:00 2001
From: Glenn Washburn <development@efficientek.com>
Date: Thu, 9 Dec 2021 11:14:52 -0600
Subject: [PATCH 02/30] cryptodisk: Return failure in cryptomount when no
cryptodisk modules are loaded
This displays an error notifying the user that they'll want to load
a backend module to make cryptomount useful.
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/disk/cryptodisk.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 66f5e8c..ea68794 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -949,6 +949,9 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
if (argc < 1 && !state[1].set && !state[2].set)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
+ if (grub_cryptodisk_list == NULL)
+ return grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk modules loaded");
+
if (state[0].set)
{
int found_uuid;
--
2.33.0

View File

@ -0,0 +1,58 @@
From 9f5be9d4e5a7192e498e5b8e9a3ed1f64c065e63 Mon Sep 17 00:00:00 2001
From: Glenn Washburn <development@efficientek.com>
Date: Thu, 9 Dec 2021 11:14:53 -0600
Subject: [PATCH 03/30] cryptodisk: Improve error messaging in cryptomount
invocations
Update such that "cryptomount -u UUID" will not print two error messages
when an invalid passphrase is given and the most relevant error message
will be displayed.
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/disk/cryptodisk.c | 21 +++++++++++++++++----
1 file changed, 17 insertions(+), 4 deletions(-)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index ea68794..770f51e 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -933,7 +933,10 @@ grub_cryptodisk_scan_device (const char *name,
if (grub_errno == GRUB_ERR_BAD_MODULE)
grub_error_pop ();
- if (grub_errno != GRUB_ERR_NONE)
+ if (search_uuid != NULL)
+ /* Push error onto stack to save for cryptomount. */
+ grub_error_push ();
+ else
grub_print_error ();
cleanup:
@@ -970,9 +973,19 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
search_uuid = NULL;
- if (!found_uuid)
- return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such cryptodisk found");
- return GRUB_ERR_NONE;
+ if (found_uuid)
+ return GRUB_ERR_NONE;
+ else if (grub_errno == GRUB_ERR_NONE)
+ {
+ /*
+ * Try to pop the next error on the stack. If there is not one, then
+ * no device matched the given UUID.
+ */
+ grub_error_pop ();
+ if (grub_errno == GRUB_ERR_NONE)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such cryptodisk found");
+ }
+ return grub_errno;
}
else if (state[1].set || (argc == 0 && state[2].set))
{
--
2.33.0

View File

@ -0,0 +1,31 @@
From e499cd344a68a1e3491492f0b0ac17a4e9c21eaf Mon Sep 17 00:00:00 2001
From: Glenn Washburn <development@efficientek.com>
Date: Thu, 9 Dec 2021 11:14:54 -0600
Subject: [PATCH 04/30] cryptodisk: Improve cryptomount -u error message
When a cryptmount is specified with a UUID, but no cryptodisk backends find
a disk with that UUID, return a more detailed message giving telling the
user that they might not have a needed cryptobackend module loaded.
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/disk/cryptodisk.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 770f51e..8dd0817 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -983,7 +983,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
*/
grub_error_pop ();
if (grub_errno == GRUB_ERR_NONE)
- return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such cryptodisk found");
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such cryptodisk found, perhaps a needed disk or cryptodisk module is not loaded");
}
return grub_errno;
}
--
2.33.0

View File

@ -0,0 +1,226 @@
From 1fc707bb9d86981efbb54d71bc0016a11fa61c42 Mon Sep 17 00:00:00 2001
From: Glenn Washburn <development@efficientek.com>
Date: Thu, 9 Dec 2021 11:14:55 -0600
Subject: [PATCH 05/30] cryptodisk: Add infrastructure to pass data from
cryptomount to cryptodisk modules
Previously, the cryptomount arguments were passed by global variable and
function call argument, neither of which are ideal. This change passes data
via a grub_cryptomount_args struct, which can be added to over time as
opposed to continually adding arguments to the cryptodisk scan and
recover_key.
As an example, passing a password as a cryptomount argument is implemented.
However, the backends are not implemented, so testing this will return a not
implemented error.
Also, add comments to cryptomount argument parsing to make it more obvious
which argument states are being handled.
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/disk/cryptodisk.c | 31 +++++++++++++++++++++----------
grub-core/disk/geli.c | 6 +++++-
grub-core/disk/luks.c | 7 ++++++-
include/grub/cryptodisk.h | 9 ++++++++-
4 files changed, 40 insertions(+), 13 deletions(-)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 8dd0817..f01b027 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -41,6 +41,7 @@ static const struct grub_arg_option options[] =
/* TRANSLATORS: It's still restricted to cryptodisks only. */
{"all", 'a', 0, N_("Mount all."), 0, 0},
{"boot", 'b', 0, N_("Mount all volumes with `boot' flag set."), 0, 0},
+ {"password", 'p', 0, N_("Password to open volumes."), 0, ARG_TYPE_STRING},
{0, 0, 0, 0, 0, 0}
};
@@ -820,7 +821,9 @@ cryptodisk_close (grub_cryptodisk_t dev)
}
static grub_cryptodisk_t
-grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
+grub_cryptodisk_scan_device_real (const char *name,
+ grub_disk_t source,
+ grub_cryptomount_args_t cargs)
{
grub_err_t err;
grub_cryptodisk_t dev;
@@ -839,7 +842,7 @@ grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
if (!dev)
continue;
- err = cr->recover_key (source, dev);
+ err = cr->recover_key (source, dev, cargs);
if (err)
{
cryptodisk_close (dev);
@@ -904,11 +907,12 @@ grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat)
static int
grub_cryptodisk_scan_device (const char *name,
- void *data __attribute__ ((unused)))
+ void *data)
{
int ret = 0;
grub_disk_t source;
grub_cryptodisk_t dev;
+ grub_cryptomount_args_t cargs = data;
grub_errno = GRUB_ERR_NONE;
/* Try to open disk. */
@@ -919,7 +923,7 @@ grub_cryptodisk_scan_device (const char *name,
return 0;
}
- dev = grub_cryptodisk_scan_device_real (name, source);
+ dev = grub_cryptodisk_scan_device_real (name, source, cargs);
if (dev)
{
ret = (search_uuid != NULL && grub_strcasecmp (search_uuid, dev->uuid) == 0);
@@ -948,6 +952,7 @@ static grub_err_t
grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
{
struct grub_arg_list *state = ctxt->state;
+ struct grub_cryptomount_args cargs = {0};
if (argc < 1 && !state[1].set && !state[2].set)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
@@ -955,7 +960,13 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
if (grub_cryptodisk_list == NULL)
return grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk modules loaded");
- if (state[0].set)
+ if (state[3].set) /* password */
+ {
+ cargs.key_data = (grub_uint8_t *) state[3].arg;
+ cargs.key_len = grub_strlen (state[3].arg);
+ }
+
+ if (state[0].set) /* uuid */
{
int found_uuid;
grub_cryptodisk_t dev;
@@ -970,7 +981,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
check_boot = state[2].set;
search_uuid = args[0];
- found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
+ found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
search_uuid = NULL;
if (found_uuid)
@@ -987,11 +998,11 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
}
return grub_errno;
}
- else if (state[1].set || (argc == 0 && state[2].set))
+ else if (state[1].set || (argc == 0 && state[2].set)) /* -a|-b */
{
search_uuid = NULL;
check_boot = state[2].set;
- grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
+ grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
search_uuid = NULL;
return GRUB_ERR_NONE;
}
@@ -1032,7 +1043,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
return GRUB_ERR_NONE;
}
- dev = grub_cryptodisk_scan_device_real (diskname, disk);
+ dev = grub_cryptodisk_scan_device_real (diskname, disk, &cargs);
grub_disk_close (disk);
if (disklast)
@@ -1171,7 +1182,7 @@ GRUB_MOD_INIT (cryptodisk)
{
grub_disk_dev_register (&grub_cryptodisk_dev);
cmd = grub_register_extcmd ("cryptomount", grub_cmd_cryptomount, 0,
- N_("SOURCE|-u UUID|-a|-b"),
+ N_("[-p password] <SOURCE|-u UUID|-a|-b>"),
N_("Mount a crypto device."), options);
grub_procfs_register ("luks_script", &luks_script);
}
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
index e9d2329..48d9be9 100644
--- a/grub-core/disk/geli.c
+++ b/grub-core/disk/geli.c
@@ -398,7 +398,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
}
static grub_err_t
-recover_key (grub_disk_t source, grub_cryptodisk_t dev)
+recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_cryptomount_args_t cargs)
{
grub_size_t keysize;
grub_uint8_t digest[GRUB_CRYPTO_MAX_MDLEN];
@@ -414,6 +414,10 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev)
grub_disk_addr_t sector;
grub_err_t err;
+ /* Keyfiles are not implemented yet */
+ if (cargs->key_data != NULL || cargs->key_len)
+ return GRUB_ERR_NOT_IMPLEMENTED_YET;
+
if (dev->cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
return grub_error (GRUB_ERR_BUG, "cipher block is too long");
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 18b3a8b..86bf951 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -309,7 +309,8 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
static grub_err_t
luks_recover_key (grub_disk_t source,
- grub_cryptodisk_t dev)
+ grub_cryptodisk_t dev,
+ grub_cryptomount_args_t cargs)
{
struct grub_luks_phdr header;
grub_size_t keysize;
@@ -322,6 +323,10 @@ luks_recover_key (grub_disk_t source,
grub_size_t max_stripes = 1;
char *tmp;
+ /* Keyfiles are not implemented yet */
+ if (cargs->key_data != NULL || cargs->key_len)
+ return GRUB_ERR_NOT_IMPLEMENTED_YET;
+
err = grub_disk_read (source, 0, 0, sizeof (header), &header);
if (err)
return err;
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index 32f564a..a41b426 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -60,6 +60,13 @@ typedef gcry_err_code_t
(*grub_cryptodisk_rekey_func_t) (struct grub_cryptodisk *dev,
grub_uint64_t zoneno);
+struct grub_cryptomount_args
+{
+ grub_uint8_t *key_data;
+ grub_size_t key_len;
+};
+typedef struct grub_cryptomount_args *grub_cryptomount_args_t;
+
struct grub_cryptodisk
{
struct grub_cryptodisk *next;
@@ -108,7 +115,7 @@ struct grub_cryptodisk_dev
grub_cryptodisk_t (*scan) (grub_disk_t disk, const char *check_uuid,
int boot_only);
- grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev);
+ grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev, grub_cryptomount_args_t cargs);
};
typedef struct grub_cryptodisk_dev *grub_cryptodisk_dev_t;
--
2.33.0

View File

@ -0,0 +1,270 @@
From 964793a17bfecdb4bfa1e766e6880337c02dcd2c Mon Sep 17 00:00:00 2001
From: Glenn Washburn <development@efficientek.com>
Date: Thu, 9 Dec 2021 11:14:56 -0600
Subject: [PATCH 06/30] cryptodisk: Refactor password input out of crypto dev
modules into cryptodisk
The crypto device modules should only be setting up the crypto devices and
not getting user input. This has the added benefit of simplifying the code
such that three essentially duplicate pieces of code are merged into one.
Add documentation of passphrase option for cryptomount as it is now usable.
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
docs/grub.texi | 8 ++++--
grub-core/disk/cryptodisk.c | 56 +++++++++++++++++++++++++++++--------
grub-core/disk/geli.c | 26 ++++-------------
grub-core/disk/luks.c | 27 +++---------------
include/grub/cryptodisk.h | 1 +
5 files changed, 60 insertions(+), 58 deletions(-)
diff --git a/docs/grub.texi b/docs/grub.texi
index 2b12b2c..44fd6dc 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -4253,9 +4253,11 @@ Alias for @code{hashsum --hash crc32 arg @dots{}}. See command @command{hashsum}
@node cryptomount
@subsection cryptomount
-@deffn Command cryptomount device|@option{-u} uuid|@option{-a}|@option{-b}
-Setup access to encrypted device. If necessary, passphrase
-is requested interactively. Option @var{device} configures specific grub device
+@deffn Command cryptomount [@option{-p} password] device|@option{-u} uuid|@option{-a}|@option{-b}
+Setup access to encrypted device. If @option{-p} is not given, a passphrase
+is requested interactively. Otherwise, the given @var{password} will be used and
+no passphrase will be requested interactively.
+Option @var{device} configures specific grub device
(@pxref{Naming convention}); option @option{-u} @var{uuid} configures device
with specified @var{uuid}; option @option{-a} configures all detected encrypted
devices; option @option{-b} configures all geli containers that have boot flag set.
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index f01b027..3b2ded1 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -825,9 +825,11 @@ grub_cryptodisk_scan_device_real (const char *name,
grub_disk_t source,
grub_cryptomount_args_t cargs)
{
- grub_err_t err;
+ grub_err_t ret = GRUB_ERR_NONE;
grub_cryptodisk_t dev;
grub_cryptodisk_dev_t cr;
+ int askpass = 0;
+ char *part = NULL;
dev = grub_cryptodisk_get_by_source_disk (source);
@@ -841,21 +843,53 @@ grub_cryptodisk_scan_device_real (const char *name,
return NULL;
if (!dev)
continue;
-
- err = cr->recover_key (source, dev, cargs);
- if (err)
- {
- cryptodisk_close (dev);
- return NULL;
- }
+
+ if (!cargs->key_len)
+ {
+ /* Get the passphrase from the user, if no key data. */
+ askpass = 1;
+ if (source->partition != NULL)
+ part = grub_partition_get_name (source->partition);
+ grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
+ source->partition != NULL ? "," : "",
+ part != NULL ? part : "",
+ dev->uuid);
+ grub_free (part);
+
+ cargs->key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE);
+ if (cargs->key_data == NULL)
+ return NULL;
+
+ if (!grub_password_get ((char *) cargs->key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE))
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied");
+ goto error;
+ }
+ cargs->key_len = grub_strlen ((char *) cargs->key_data);
+ }
+
+ ret = cr->recover_key (source, dev, cargs);
+ if (ret != GRUB_ERR_NONE)
+ goto error;
grub_cryptodisk_insert (dev, name, source);
- return dev;
+ goto cleanup;
}
-
grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk module can handle this device");
- return NULL;
+ goto cleanup;
+
+ error:
+ cryptodisk_close (dev);
+ dev = NULL;
+
+ cleanup:
+ if (askpass)
+ {
+ cargs->key_len = 0;
+ grub_free (cargs->key_data);
+ }
+ return dev;
}
#ifdef GRUB_UTIL
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
index 48d9be9..248c42a 100644
--- a/grub-core/disk/geli.c
+++ b/grub-core/disk/geli.c
@@ -135,8 +135,6 @@ const char *algorithms[] = {
[0x16] = "aes"
};
-#define MAX_PASSPHRASE 256
-
static gcry_err_code_t
geli_rekey (struct grub_cryptodisk *dev, grub_uint64_t zoneno)
{
@@ -406,17 +404,14 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_cryptomount_args_t
grub_uint8_t verify_key[GRUB_CRYPTO_MAX_MDLEN];
grub_uint8_t zero[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE];
grub_uint8_t geli_cipher_key[64];
- char passphrase[MAX_PASSPHRASE] = "";
unsigned i;
gcry_err_code_t gcry_err;
struct grub_geli_phdr header;
- char *tmp;
grub_disk_addr_t sector;
grub_err_t err;
- /* Keyfiles are not implemented yet */
- if (cargs->key_data != NULL || cargs->key_len)
- return GRUB_ERR_NOT_IMPLEMENTED_YET;
+ if (cargs->key_data == NULL || cargs->key_len == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no key data");
if (dev->cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
return grub_error (GRUB_ERR_BUG, "cipher block is too long");
@@ -438,23 +433,12 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_cryptomount_args_t
grub_puts_ (N_("Attempting to decrypt master key..."));
- /* Get the passphrase from the user. */
- tmp = NULL;
- if (source->partition)
- tmp = grub_partition_get_name (source->partition);
- grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
- source->partition ? "," : "", tmp ? : "",
- dev->uuid);
- grub_free (tmp);
- if (!grub_password_get (passphrase, MAX_PASSPHRASE))
- return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
-
/* Calculate the PBKDF2 of the user supplied passphrase. */
if (grub_le_to_cpu32 (header.niter) != 0)
{
grub_uint8_t pbkdf_key[64];
- gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase,
- grub_strlen (passphrase),
+ gcry_err = grub_crypto_pbkdf2 (dev->hash, cargs->key_data,
+ cargs->key_len,
header.salt,
sizeof (header.salt),
grub_le_to_cpu32 (header.niter),
@@ -477,7 +461,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_cryptomount_args_t
return grub_crypto_gcry_error (GPG_ERR_OUT_OF_MEMORY);
grub_crypto_hmac_write (hnd, header.salt, sizeof (header.salt));
- grub_crypto_hmac_write (hnd, passphrase, grub_strlen (passphrase));
+ grub_crypto_hmac_write (hnd, cargs->key_data, cargs->key_len);
gcry_err = grub_crypto_hmac_fini (hnd, geomkey);
if (gcry_err)
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 86bf951..8b39f52 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -29,8 +29,6 @@
GRUB_MOD_LICENSE ("GPLv3+");
-#define MAX_PASSPHRASE 256
-
#define LUKS_KEY_ENABLED 0x00AC71F3
/* On disk LUKS header */
@@ -315,17 +313,14 @@ luks_recover_key (grub_disk_t source,
struct grub_luks_phdr header;
grub_size_t keysize;
grub_uint8_t *split_key = NULL;
- char passphrase[MAX_PASSPHRASE] = "";
grub_uint8_t candidate_digest[sizeof (header.mkDigest)];
unsigned i;
grub_size_t length;
grub_err_t err;
grub_size_t max_stripes = 1;
- char *tmp;
- /* Keyfiles are not implemented yet */
- if (cargs->key_data != NULL || cargs->key_len)
- return GRUB_ERR_NOT_IMPLEMENTED_YET;
+ if (cargs->key_data == NULL || cargs->key_len == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no key data");
err = grub_disk_read (source, 0, 0, sizeof (header), &header);
if (err)
@@ -345,20 +340,6 @@ luks_recover_key (grub_disk_t source,
if (!split_key)
return grub_errno;
- /* Get the passphrase from the user. */
- tmp = NULL;
- if (source->partition)
- tmp = grub_partition_get_name (source->partition);
- grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
- source->partition ? "," : "", tmp ? : "",
- dev->uuid);
- grub_free (tmp);
- if (!grub_password_get (passphrase, MAX_PASSPHRASE))
- {
- grub_free (split_key);
- return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
- }
-
/* Try to recover master key from each active keyslot. */
for (i = 0; i < ARRAY_SIZE (header.keyblock); i++)
{
@@ -373,8 +354,8 @@ luks_recover_key (grub_disk_t source,
grub_dprintf ("luks", "Trying keyslot %d\n", i);
/* Calculate the PBKDF2 of the user supplied passphrase. */
- gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase,
- grub_strlen (passphrase),
+ gcry_err = grub_crypto_pbkdf2 (dev->hash, cargs->key_data,
+ cargs->key_len,
header.keyblock[i].passwordSalt,
sizeof (header.keyblock[i].passwordSalt),
grub_be_to_cpu32 (header.keyblock[i].
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index a41b426..55d5c26 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -53,6 +53,7 @@ typedef enum
#define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE - 3)
#define GRUB_CRYPTODISK_GF_BYTES (1U << GRUB_CRYPTODISK_GF_LOG_BYTES)
#define GRUB_CRYPTODISK_MAX_KEYLEN 128
+#define GRUB_CRYPTODISK_MAX_PASSPHRASE 256
struct grub_cryptodisk;
--
2.33.0

View File

@ -0,0 +1,214 @@
From 4fcf56249bd68eeb0ba2ad722dcfded0045de688 Mon Sep 17 00:00:00 2001
From: Glenn Washburn <development@efficientek.com>
Date: Thu, 9 Dec 2021 11:14:57 -0600
Subject: [PATCH 07/30] cryptodisk: Move global variables into
grub_cryptomount_args struct
Note that cargs.search_uuid does not need to be initialized in various parts
of the cryptomount argument parsing, just once when cargs is declared with
a struct initializer. The previous code used a global variable which would
retain the value across cryptomount invocations.
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/disk/cryptodisk.c | 24 +++++++++---------------
grub-core/disk/geli.c | 9 ++++-----
grub-core/disk/luks.c | 9 ++++-----
include/grub/cryptodisk.h | 9 +++++++--
4 files changed, 24 insertions(+), 27 deletions(-)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 3b2ded1..6613b27 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -808,9 +808,6 @@ grub_util_cryptodisk_get_uuid (grub_disk_t disk)
#endif
-static int check_boot;
-static char *search_uuid;
-
static void
cryptodisk_close (grub_cryptodisk_t dev)
{
@@ -838,7 +835,7 @@ grub_cryptodisk_scan_device_real (const char *name,
FOR_CRYPTODISK_DEVS (cr)
{
- dev = cr->scan (source, search_uuid, check_boot);
+ dev = cr->scan (source, cargs);
if (grub_errno)
return NULL;
if (!dev)
@@ -901,6 +898,7 @@ grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat)
grub_cryptodisk_t dev;
grub_cryptodisk_dev_t cr;
grub_disk_t source;
+ struct grub_cryptomount_args cargs = {0};
/* Try to open disk. */
source = grub_disk_open (sourcedev);
@@ -917,7 +915,7 @@ grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat)
FOR_CRYPTODISK_DEVS (cr)
{
- dev = cr->scan (source, search_uuid, check_boot);
+ dev = cr->scan (source, &cargs);
if (grub_errno)
return grub_errno;
if (!dev)
@@ -960,7 +958,7 @@ grub_cryptodisk_scan_device (const char *name,
dev = grub_cryptodisk_scan_device_real (name, source, cargs);
if (dev)
{
- ret = (search_uuid != NULL && grub_strcasecmp (search_uuid, dev->uuid) == 0);
+ ret = (cargs->search_uuid != NULL && grub_strcasecmp (cargs->search_uuid, dev->uuid) == 0);
goto cleanup;
}
@@ -971,7 +969,7 @@ grub_cryptodisk_scan_device (const char *name,
if (grub_errno == GRUB_ERR_BAD_MODULE)
grub_error_pop ();
- if (search_uuid != NULL)
+ if (cargs->search_uuid != NULL)
/* Push error onto stack to save for cryptomount. */
grub_error_push ();
else
@@ -1013,10 +1011,9 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
return GRUB_ERR_NONE;
}
- check_boot = state[2].set;
- search_uuid = args[0];
+ cargs.check_boot = state[2].set;
+ cargs.search_uuid = args[0];
found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
- search_uuid = NULL;
if (found_uuid)
return GRUB_ERR_NONE;
@@ -1034,10 +1031,8 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
}
else if (state[1].set || (argc == 0 && state[2].set)) /* -a|-b */
{
- search_uuid = NULL;
- check_boot = state[2].set;
+ cargs.check_boot = state[2].set;
grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
- search_uuid = NULL;
return GRUB_ERR_NONE;
}
else
@@ -1048,8 +1043,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
char *disklast = NULL;
grub_size_t len;
- search_uuid = NULL;
- check_boot = state[2].set;
+ cargs.check_boot = state[2].set;
diskname = args[0];
len = grub_strlen (diskname);
if (len && diskname[0] == '(' && diskname[len - 1] == ')')
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
index 248c42a..6e02451 100644
--- a/grub-core/disk/geli.c
+++ b/grub-core/disk/geli.c
@@ -240,8 +240,7 @@ grub_util_get_geli_uuid (const char *dev)
#endif
static grub_cryptodisk_t
-configure_ciphers (grub_disk_t disk, const char *check_uuid,
- int boot_only)
+configure_ciphers (grub_disk_t disk, grub_cryptomount_args_t cargs)
{
grub_cryptodisk_t newdev;
struct grub_geli_phdr header;
@@ -289,7 +288,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
return NULL;
}
- if (boot_only && !(grub_le_to_cpu32 (header.flags) & GRUB_GELI_FLAGS_BOOT))
+ if (cargs->check_boot && !(grub_le_to_cpu32 (header.flags) & GRUB_GELI_FLAGS_BOOT))
{
grub_dprintf ("geli", "not a boot volume\n");
return NULL;
@@ -302,9 +301,9 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
return NULL;
}
- if (check_uuid && grub_strcasecmp (check_uuid, uuid) != 0)
+ if (cargs->search_uuid != NULL && grub_strcasecmp (cargs->search_uuid, uuid) != 0)
{
- grub_dprintf ("geli", "%s != %s\n", uuid, check_uuid);
+ grub_dprintf ("geli", "%s != %s\n", uuid, cargs->search_uuid);
return NULL;
}
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 8b39f52..298606f 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -63,8 +63,7 @@ gcry_err_code_t AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src,
grub_size_t blocknumbers);
static grub_cryptodisk_t
-configure_ciphers (grub_disk_t disk, const char *check_uuid,
- int check_boot)
+configure_ciphers (grub_disk_t disk, grub_cryptomount_args_t cargs)
{
grub_cryptodisk_t newdev;
const char *iptr;
@@ -84,7 +83,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
int benbi_log = 0;
grub_err_t err;
- if (check_boot)
+ if (cargs->check_boot)
return NULL;
/* Read the LUKS header. */
@@ -110,9 +109,9 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
}
*optr = 0;
- if (check_uuid && grub_strcasecmp (check_uuid, uuid) != 0)
+ if (cargs->search_uuid != NULL && grub_strcasecmp (cargs->search_uuid, uuid) != 0)
{
- grub_dprintf ("luks", "%s != %s\n", uuid, check_uuid);
+ grub_dprintf ("luks", "%s != %s\n", uuid, cargs->search_uuid);
return NULL;
}
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index 55d5c26..33224a5 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -63,7 +63,13 @@ typedef gcry_err_code_t
struct grub_cryptomount_args
{
+ /* scan: Flag to indicate that only bootable volumes should be decrypted */
+ grub_uint32_t check_boot : 1;
+ /* scan: Only volumes matching this UUID should be decrpyted */
+ char *search_uuid;
+ /* recover_key: Key data used to decrypt voume */
grub_uint8_t *key_data;
+ /* recover_key: Length of key_data */
grub_size_t key_len;
};
typedef struct grub_cryptomount_args *grub_cryptomount_args_t;
@@ -114,8 +120,7 @@ struct grub_cryptodisk_dev
struct grub_cryptodisk_dev *next;
struct grub_cryptodisk_dev **prev;
- grub_cryptodisk_t (*scan) (grub_disk_t disk, const char *check_uuid,
- int boot_only);
+ grub_cryptodisk_t (*scan) (grub_disk_t disk, grub_cryptomount_args_t cargs);
grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev, grub_cryptomount_args_t cargs);
};
typedef struct grub_cryptodisk_dev *grub_cryptodisk_dev_t;
--
2.33.0

View File

@ -0,0 +1,39 @@
From ea9aa4d566591710b3eae8f0ce286b1040424e5f Mon Sep 17 00:00:00 2001
From: Glenn Washburn <development@efficientek.com>
Date: Thu, 9 Dec 2021 11:14:58 -0600
Subject: [PATCH 08/30] cryptodisk: Improve handling of partition name in
cryptomount password prompt
Call grub_partition_get_name() unconditionally to initialize the part
variable. Then part will only be NULL when grub_partition_get_name() errors.
Note that when source->partition is NULL, then grub_partition_get_name()
returns an allocated empty string. So no comma or partition will be printed,
as desired.
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/disk/cryptodisk.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 6613b27..9a69e24 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -845,11 +845,10 @@ grub_cryptodisk_scan_device_real (const char *name,
{
/* Get the passphrase from the user, if no key data. */
askpass = 1;
- if (source->partition != NULL)
- part = grub_partition_get_name (source->partition);
+ part = grub_partition_get_name (source->partition);
grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
source->partition != NULL ? "," : "",
- part != NULL ? part : "",
+ part != NULL ? part : N_("UNKNOWN"),
dev->uuid);
grub_free (part);
--
2.33.0

View File

@ -0,0 +1,75 @@
From 155b53904177961d3d44032c87c0eb4b288d2271 Mon Sep 17 00:00:00 2001
From: Glenn Washburn <development@efficientek.com>
Date: Sat, 1 Jan 2022 15:48:25 -0600
Subject: [PATCH 09/30] cryptodisk: Fix Coverity use after free bug
The Coverity output is:
*** CID 366905: Memory - illegal accesses (USE_AFTER_FREE)
/grub-core/disk/cryptodisk.c: 1064 in grub_cryptodisk_scan_device_real()
1058 cleanup:
1059 if (askpass)
1060 {
1061 cargs->key_len = 0;
1062 grub_free (cargs->key_data);
1063 }
>>> CID 366905: Memory - illegal accesses (USE_AFTER_FREE)
>>> Using freed pointer "dev".
1064 return dev;
1065 }
1066
1067 #ifdef GRUB_UTIL
1068 #include <grub/util/misc.h>
1069 grub_err_t
Here the "dev" variable can point to a freed cryptodisk device if the
function grub_cryptodisk_insert() fails. This can happen only on a OOM
condition, but when this happens grub_cryptodisk_insert() calls grub_free on
the passed device. Since grub_cryptodisk_scan_device_real() assumes that
grub_cryptodisk_insert() is always successful, it will return the device,
though the device was freed.
Change grub_cryptodisk_insert() to not free the passed device on failure.
Then on grub_cryptodisk_insert() failure, free the device pointer. This is
done by going to the label "error", which will call cryptodisk_close() to
free the device and set the device pointer to NULL, so that a pointer to
freed memory is not returned.
Fixes: CID 366905
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/disk/cryptodisk.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 9a69e24..b8a43a8 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -713,10 +713,7 @@ grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
{
newdev->source = grub_strdup (name);
if (!newdev->source)
- {
- grub_free (newdev);
- return grub_errno;
- }
+ return grub_errno;
newdev->id = last_cryptodisk_id++;
newdev->source_id = source->id;
@@ -868,7 +865,9 @@ grub_cryptodisk_scan_device_real (const char *name,
if (ret != GRUB_ERR_NONE)
goto error;
- grub_cryptodisk_insert (dev, name, source);
+ ret = grub_cryptodisk_insert (dev, name, source);
+ if (ret != GRUB_ERR_NONE)
+ goto error;
goto cleanup;
}
--
2.33.0

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,313 @@
From 97f2cb18dccf7022701baf6b622d0c7a48928a05 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 29 Aug 2024 13:27:30 +0800
Subject: [PATCH 06/30] disk/cryptodisk: Require authentication after TPM
unlock for CLI access
The GRUB may use TPM to verify the integrity of boot components and the
result can determine whether a previously sealed key can be released. If
everything checks out, showing nothing has been tampered with, the key
is released and GRUB unlocks the encrypted root partition for the next
stage of booting.
However, the liberal Command Line Interface (CLI) can be misused by
anyone in this case to access files in the encrypted partition one way
or another. Despite efforts to keep the CLI secure by preventing utility
command output from leaking file content, many techniques in the wild
could still be used to exploit the CLI, enabling attacks or learning
methods to attack. It's nearly impossible to account for all scenarios
where a hack could be applied.
Therefore, to mitigate potential misuse of the CLI after the root device
has been successfully unlocked via TPM, the user should be required to
authenticate using the LUKS password. This added layer of security
ensures that only authorized users can access the CLI reducing the risk
of exploitation or unauthorized access to the encrypted partition.
Fixes: CVE-2024-49504
Signed-off-by: Michael Chang <mchang@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/disk/cryptodisk.c | 86 +++++++++++++++++++++++++++++++++++
grub-core/kern/main.c | 13 ++++++
grub-core/normal/auth.c | 30 ++++++++++++
grub-core/normal/main.c | 4 ++
grub-core/normal/menu_entry.c | 4 ++
include/grub/auth.h | 1 +
include/grub/cryptodisk.h | 3 ++
include/grub/misc.h | 9 ++++
8 files changed, 150 insertions(+)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index b8a43a8..a8f235c 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -869,6 +869,9 @@ grub_cryptodisk_scan_device_real (const char *name,
if (ret != GRUB_ERR_NONE)
goto error;
+#ifndef GRUB_UTIL
+ grub_cli_set_auth_needed ();
+#endif
goto cleanup;
}
grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk module can handle this device");
@@ -1196,6 +1199,89 @@ luks_script_get (grub_size_t *sz)
return ret;
}
+#ifdef GRUB_MACHINE_EFI
+grub_err_t
+grub_cryptodisk_challenge_password (void)
+{
+ grub_cryptodisk_t cr_dev;
+
+ for (cr_dev = cryptodisk_list; cr_dev != NULL; cr_dev = cr_dev->next)
+ {
+ grub_cryptodisk_dev_t cr;
+ grub_disk_t source = NULL;
+ grub_err_t ret = GRUB_ERR_NONE;
+ grub_cryptodisk_t dev = NULL;
+ char *part = NULL;
+ struct grub_cryptomount_args cargs = {0};
+
+ cargs.check_boot = 0;
+ cargs.search_uuid = cr_dev->uuid;
+
+ source = grub_disk_open (cr_dev->source);
+
+ if (source == NULL)
+ {
+ ret = grub_errno;
+ goto error_out;
+ }
+
+ FOR_CRYPTODISK_DEVS (cr)
+ {
+ dev = cr->scan (source, &cargs);
+ if (grub_errno)
+ {
+ ret = grub_errno;
+ goto error_out;
+ }
+ if (dev == NULL)
+ continue;
+ break;
+ }
+
+ if (dev == NULL)
+ {
+ ret = grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk module can handle this device");
+ goto error_out;
+ }
+
+ part = grub_partition_get_name (source->partition);
+ grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
+ source->partition != NULL ? "," : "",
+ part != NULL ? part : N_("UNKNOWN"), cr_dev->uuid);
+ grub_free (part);
+
+ cargs.key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE);
+ if (cargs.key_data == NULL)
+ {
+ ret = grub_errno;
+ goto error_out;
+ }
+
+ if (!grub_password_get ((char *) cargs.key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE))
+ {
+ ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied");
+ goto error_out;
+ }
+ cargs.key_len = grub_strlen ((char *) cargs.key_data);
+ ret = cr->recover_key (source, dev, &cargs);
+
+ error_out:
+ grub_disk_close (source);
+ if (dev != NULL)
+ cryptodisk_close (dev);
+ if (cargs.key_data)
+ {
+ grub_memset (cargs.key_data, 0, cargs.key_len);
+ grub_free (cargs.key_data);
+ }
+
+ return ret;
+ }
+
+ return GRUB_ERR_NONE;
+}
+#endif /* GRUB_MACHINE_EFI */
+
struct grub_procfs_entry luks_script =
{
.name = "luks_script",
diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
index 0285e95..438a15c 100644
--- a/grub-core/kern/main.c
+++ b/grub-core/kern/main.c
@@ -35,6 +35,8 @@
#include <grub/machine/memory.h>
#endif
+static bool cli_need_auth = false;
+
grub_addr_t
grub_modules_get_end (void)
{
@@ -245,6 +247,17 @@ grub_load_normal_mode (void)
grub_command_execute ("normal", 0, 0);
}
+bool
+grub_is_cli_need_auth (void)
+{
+ return cli_need_auth;
+}
+
+void grub_cli_set_auth_needed (void)
+{
+ cli_need_auth = true;
+}
+
static void
reclaim_module_space (void)
{
diff --git a/grub-core/normal/auth.c b/grub-core/normal/auth.c
index c35ce97..29d8a75 100644
--- a/grub-core/normal/auth.c
+++ b/grub-core/normal/auth.c
@@ -25,6 +25,10 @@
#include <grub/time.h>
#include <grub/i18n.h>
+#ifdef GRUB_MACHINE_EFI
+#include <grub/cryptodisk.h>
+#endif
+
struct grub_auth_user
{
struct grub_auth_user *next;
@@ -200,6 +204,32 @@ grub_username_get (char buf[], unsigned buf_size)
return (key != GRUB_TERM_ESC);
}
+grub_err_t
+grub_auth_check_cli_access (void)
+{
+ if (grub_is_cli_need_auth () == true)
+ {
+#ifdef GRUB_MACHINE_EFI
+ static bool authenticated = false;
+
+ if (authenticated == false)
+ {
+ grub_err_t ret;
+
+ ret = grub_cryptodisk_challenge_password ();
+ if (ret == GRUB_ERR_NONE)
+ authenticated = true;
+ return ret;
+ }
+ return GRUB_ERR_NONE;
+#else
+ return GRUB_ACCESS_DENIED;
+#endif
+ }
+
+ return GRUB_ERR_NONE;
+}
+
grub_err_t
grub_auth_check_authentication (const char *userlist)
{
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index 7a2dd3b..6d706db 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -502,9 +502,13 @@ grub_cmdline_run (int nested, int force_auth)
}
while (err && force_auth);
+ if (err == GRUB_ERR_NONE)
+ err = grub_auth_check_cli_access ();
+
if (err)
{
grub_print_error ();
+ grub_wait_after_message ();
grub_errno = GRUB_ERR_NONE;
return;
}
diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c
index de64a36..572dd12 100644
--- a/grub-core/normal/menu_entry.c
+++ b/grub-core/normal/menu_entry.c
@@ -1252,9 +1252,13 @@ grub_menu_entry_run (grub_menu_entry_t entry)
err = grub_auth_check_authentication (NULL);
+ if (err == GRUB_ERR_NONE)
+ err = grub_auth_check_cli_access ();
+
if (err)
{
grub_print_error ();
+ grub_wait_after_message ();
grub_errno = GRUB_ERR_NONE;
return;
}
diff --git a/include/grub/auth.h b/include/grub/auth.h
index 7473344..21d5190 100644
--- a/include/grub/auth.h
+++ b/include/grub/auth.h
@@ -33,5 +33,6 @@ grub_err_t grub_auth_unregister_authentication (const char *user);
grub_err_t grub_auth_authenticate (const char *user);
grub_err_t grub_auth_deauthenticate (const char *user);
grub_err_t grub_auth_check_authentication (const char *userlist);
+grub_err_t grub_auth_check_cli_access (void);
#endif /* ! GRUB_AUTH_HEADER */
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index 33224a5..412bd12 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -169,4 +169,7 @@ grub_util_get_geli_uuid (const char *dev);
grub_cryptodisk_t grub_cryptodisk_get_by_uuid (const char *uuid);
grub_cryptodisk_t grub_cryptodisk_get_by_source_disk (grub_disk_t disk);
+#ifdef GRUB_MACHINE_EFI
+grub_err_t grub_cryptodisk_challenge_password (void);
+#endif
#endif
diff --git a/include/grub/misc.h b/include/grub/misc.h
index c801243..b121388 100644
--- a/include/grub/misc.h
+++ b/include/grub/misc.h
@@ -423,6 +423,13 @@ grub_puts (const char *s)
return 1; /* Cannot fail. */
}
+#ifndef __cplusplus
+#ifndef GRUB_POSIX_BOOL_DEFINED
+typedef enum { false = 0, true = 1 } bool;
+#define GRUB_POSIX_BOOL_DEFINED 1
+#endif
+#endif
+
int EXPORT_FUNC(grub_puts_) (const char *s);
int EXPORT_FUNC(grub_debug_enabled) (const char *condition);
void EXPORT_FUNC(grub_real_dprintf) (const char *file,
@@ -443,6 +450,8 @@ void EXPORT_FUNC(grub_exit) (int rc) __attribute__ ((noreturn));
grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n,
grub_uint64_t d,
grub_uint64_t *r);
+extern bool EXPORT_FUNC(grub_is_cli_need_auth) (void);
+extern void EXPORT_FUNC(grub_cli_set_auth_needed) (void);
/* Must match softdiv group in gentpl.py. */
#if !defined(GRUB_MACHINE_EMU) && (defined(__arm__) || defined(__ia64__) || \
--
2.33.0

View File

@ -0,0 +1,84 @@
From f21928173f423e66b0fcea9f34e87938d9aa2b0e Mon Sep 17 00:00:00 2001
From: B Horn <b@horn.uk>
Date: Fri, 15 Nov 2024 13:12:09 +0000
Subject: [PATCH 16/30] net: Fix OOB write in grub_net_search_config_file()
The function included a call to grub_strcpy() which copied data from an
environment variable to a buffer allocated in grub_cmd_normal(). The
grub_cmd_normal() didn't consider the length of the environment variable.
So, the copy operation could exceed the allocation and lead to an OOB
write. Fix the issue by replacing grub_strcpy() with grub_strlcpy() and
pass the underlying buffers size to the grub_net_search_config_file().
Fixes: CVE-2025-0624
Reported-by: B Horn <b@horn.uk>
Signed-off-by: B Horn <b@horn.uk>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/net/net.c | 7 ++++---
grub-core/normal/main.c | 2 +-
include/grub/net.h | 2 +-
3 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
index d19583e..b8c113f 100644
--- a/grub-core/net/net.c
+++ b/grub-core/net/net.c
@@ -1906,9 +1906,9 @@ grub_net_restore_hw (void)
}
grub_err_t
-grub_net_search_configfile (char *config)
+grub_net_search_configfile (char *config, grub_size_t config_buf_len)
{
- grub_size_t config_len;
+ grub_size_t config_len, suffix_len;
char *suffix;
auto int search_through (grub_size_t num_tries, grub_size_t slice_size);
@@ -1945,6 +1945,7 @@ grub_net_search_configfile (char *config)
config_len = grub_strlen (config);
config[config_len] = '-';
suffix = config + config_len + 1;
+ suffix_len = config_buf_len - (config_len + 1);
struct grub_net_network_level_interface *inf;
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
@@ -1970,7 +1971,7 @@ grub_net_search_configfile (char *config)
if (client_uuid)
{
- grub_strcpy (suffix, client_uuid);
+ grub_strlcpy (suffix, client_uuid, suffix_len);
if (search_through (1, 0) == 0) return GRUB_ERR_NONE;
}
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index 6d706db..b6198bd 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -359,7 +359,7 @@ grub_try_normal (const char *variable)
return GRUB_ERR_FILE_NOT_FOUND;
grub_snprintf (config, config_len, "%s/grub.cfg", prefix);
- err = grub_net_search_configfile (config);
+ err = grub_net_search_configfile (config, config_len);
}
if (err != GRUB_ERR_NONE)
diff --git a/include/grub/net.h b/include/grub/net.h
index 5a01747..388b301 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -666,6 +666,6 @@ extern char *grub_net_default_server;
#define VLANTAG_IDENTIFIER 0x8100
grub_err_t
-grub_net_search_configfile (char *config);
+grub_net_search_configfile (char *config, grub_size_t config_buf_len);
#endif /* ! GRUB_NET_HEADER */
--
2.33.0

View File

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

View File

@ -0,0 +1,49 @@
From 5b8d7595ea33530cef3c9f39bdb0bc0b851f42d9 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 31 May 2024 15:14:23 +0800
Subject: [PATCH 18/30] fs/ext2: Fix out-of-bounds read for inline extents
When inline extents are used, i.e. the extent tree depth equals zero,
a maximum of four entries can fit into the inode's data block. If the
extent header states a number of entries greater than four the current
ext2 implementation causes an out-of-bounds read. Fix this issue by
capping the number of extents to four when reading inline extents.
Reported-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Michael Chang <mchang@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/ext2.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c
index 848bf93..a15baea 100644
--- a/grub-core/fs/ext2.c
+++ b/grub-core/fs/ext2.c
@@ -473,6 +473,8 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
struct grub_ext4_extent *ext;
int i;
grub_disk_addr_t ret;
+ grub_uint16_t nent;
+ const grub_uint16_t max_inline_ext = sizeof (inode->blocks) / sizeof (*ext) - 1; /* Minus 1 extent header. */
leaf = grub_ext4_find_leaf (data, (struct grub_ext4_extent_header *) inode->blocks.dir_blocks, fileblock);
if (! leaf)
@@ -482,7 +484,13 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
}
ext = (struct grub_ext4_extent *) (leaf + 1);
- for (i = 0; i < grub_le_to_cpu16 (leaf->entries); i++)
+
+ nent = grub_le_to_cpu16 (leaf->entries);
+
+ if (leaf->depth == 0)
+ nent = grub_min (nent, max_inline_ext);
+
+ for (i = 0; i < nent; i++)
{
if (fileblock < grub_le_to_cpu32 (ext[i].block))
break;
--
2.33.0

View File

@ -0,0 +1,66 @@
From aaac041941a6a2a6538daddc22d16d21cc8fa221 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 21 Feb 2025 09:06:12 +0800
Subject: [PATCH 19/30] fs/ext2: Rework out-of-bounds read for inline and
external exten
Previously, the number of extent entries was not properly capped based
on the actual available space. This could lead to insufficient reads for
external extents, since the computation was based solely on the inline
extent layout.
In this patch, when processing the extent header, we determine whether
the header is stored inline (i.e., at inode->blocks.dir_blocks) or in an
external extent block. We then clamp the number of entries accordingly
(using max_inline_ext for inline extents and max_external_ext for
external extent blocks).
This change ensures that only the valid number of extent entries is
processed, preventing out-of-bound reads and potential filesystem
corruption.
Fixes: 7e2f750f0a (fs/ext2: Fix out-of-bounds read for inline extents)
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/fs/ext2.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c
index a15baea..169f606 100644
--- a/grub-core/fs/ext2.c
+++ b/grub-core/fs/ext2.c
@@ -474,7 +474,10 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
int i;
grub_disk_addr_t ret;
grub_uint16_t nent;
+ /* maximum number of extent entries in the inode's inline extent area */
const grub_uint16_t max_inline_ext = sizeof (inode->blocks) / sizeof (*ext) - 1; /* Minus 1 extent header. */
+ /* maximum number of extent entries in the external extent block */
+ const grub_uint16_t max_external_ext = EXT2_BLOCK_SIZE(data) / sizeof (*ext) - 1; /* Minus 1 extent header. */
leaf = grub_ext4_find_leaf (data, (struct grub_ext4_extent_header *) inode->blocks.dir_blocks, fileblock);
if (! leaf)
@@ -487,8 +490,18 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
nent = grub_le_to_cpu16 (leaf->entries);
- if (leaf->depth == 0)
+ /*
+ * Determine the effective number of extent entries (nent) to process:
+ * If the extent header (leaf) is stored inline in the inodes block
+ * area (i.e. at inode->blocks.dir_blocks), then only max_inline_ext
+ * entries can fit.
+ * Otherwise, if the header was read from an external extent block, use
+ * the larger limit, max_external_ext, based on the full block size.
+ */
+ if (leaf == (struct grub_ext4_extent_header *) inode->blocks.dir_blocks)
nent = grub_min (nent, max_inline_ext);
+ else
+ nent = grub_min (nent, max_external_ext);
for (i = 0; i < nent; i++)
{
--
2.33.0

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,53 @@
From 3fb3783b092783379c0eb42349601cab43b934d3 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <dja@axtens.net>
Date: Sat, 23 Mar 2024 15:59:43 +1100
Subject: [PATCH 28/30] fs/bfs: Disable under lockdown
The BFS is not fuzz-clean. Don't allow it to be loaded under lockdown.
This will also disable the AFS.
Fixes: CVE-2024-45778
Fixes: CVE-2024-45779
Reported-by: Nils Langius <nils@langius.de>
Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/bfs.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/grub-core/fs/bfs.c b/grub-core/fs/bfs.c
index 47dbe20..8d704e2 100644
--- a/grub-core/fs/bfs.c
+++ b/grub-core/fs/bfs.c
@@ -30,6 +30,7 @@
#include <grub/types.h>
#include <grub/i18n.h>
#include <grub/fshelp.h>
+#include <grub/lockdown.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -1104,7 +1105,10 @@ GRUB_MOD_INIT (bfs)
{
COMPILE_TIME_ASSERT (1 << LOG_EXTENT_SIZE ==
sizeof (struct grub_bfs_extent));
- grub_fs_register (&grub_bfs_fs);
+ if (!grub_is_lockdown ())
+ {
+ grub_fs_register (&grub_bfs_fs);
+ }
}
#ifdef MODE_AFS
@@ -1113,5 +1117,6 @@ GRUB_MOD_FINI (afs)
GRUB_MOD_FINI (bfs)
#endif
{
- grub_fs_unregister (&grub_bfs_fs);
+ if (!grub_is_lockdown ())
+ grub_fs_unregister (&grub_bfs_fs);
}
--
2.33.0

View File

@ -0,0 +1,372 @@
From ddf6d15756e2296fce47ff6fb9248cbaf3c5780d Mon Sep 17 00:00:00 2001
From: Daniel Axtens <dja@axtens.net>
Date: Sat, 23 Mar 2024 16:20:45 +1100
Subject: [PATCH 29/30] fs: Disable many filesystems under lockdown
The idea is to permit the following: btrfs, cpio, exfat, ext, f2fs, fat,
hfsplus, iso9660, squash4, tar, xfs and zfs.
The JFS, ReiserFS, romfs, UDF and UFS security vulnerabilities were
reported by Jonathan Bar Or <jonathanbaror@gmail.com>.
Fixes: CVE-2025-0677
Fixes: CVE-2025-0684
Fixes: CVE-2025-0685
Fixes: CVE-2025-0686
Fixes: CVE-2025-0689
Suggested-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/affs.c | 9 +++++++--
grub-core/fs/cbfs.c | 9 +++++++--
grub-core/fs/jfs.c | 9 +++++++--
grub-core/fs/minix.c | 9 +++++++--
grub-core/fs/nilfs2.c | 9 +++++++--
grub-core/fs/ntfs.c | 9 +++++++--
grub-core/fs/reiserfs.c | 9 +++++++--
grub-core/fs/romfs.c | 9 +++++++--
grub-core/fs/sfs.c | 9 +++++++--
grub-core/fs/udf.c | 9 +++++++--
grub-core/fs/ufs.c | 9 +++++++--
11 files changed, 77 insertions(+), 22 deletions(-)
diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c
index 230e26a..7fbd136 100644
--- a/grub-core/fs/affs.c
+++ b/grub-core/fs/affs.c
@@ -26,6 +26,7 @@
#include <grub/types.h>
#include <grub/fshelp.h>
#include <grub/charset.h>
+#include <grub/lockdown.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -699,11 +700,15 @@ static struct grub_fs grub_affs_fs =
GRUB_MOD_INIT(affs)
{
- grub_fs_register (&grub_affs_fs);
+ if (!grub_is_lockdown ())
+ {
+ grub_fs_register (&grub_affs_fs);
+ }
my_mod = mod;
}
GRUB_MOD_FINI(affs)
{
- grub_fs_unregister (&grub_affs_fs);
+ if (!grub_is_lockdown ())
+ grub_fs_unregister (&grub_affs_fs);
}
diff --git a/grub-core/fs/cbfs.c b/grub-core/fs/cbfs.c
index 857bea9..09952ec 100644
--- a/grub-core/fs/cbfs.c
+++ b/grub-core/fs/cbfs.c
@@ -26,6 +26,7 @@
#include <grub/dl.h>
#include <grub/i18n.h>
#include <grub/cbfs_core.h>
+#include <grub/lockdown.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -390,12 +391,16 @@ GRUB_MOD_INIT (cbfs)
#if (defined (__i386__) || defined (__x86_64__)) && !defined (GRUB_UTIL) && !defined (GRUB_MACHINE_EMU) && !defined (GRUB_MACHINE_XEN)
init_cbfsdisk ();
#endif
- grub_fs_register (&grub_cbfs_fs);
+ if (!grub_is_lockdown ())
+ {
+ grub_fs_register (&grub_cbfs_fs);
+ }
}
GRUB_MOD_FINI (cbfs)
{
- grub_fs_unregister (&grub_cbfs_fs);
+ if (!grub_is_lockdown ())
+ grub_fs_unregister (&grub_cbfs_fs);
#if (defined (__i386__) || defined (__x86_64__)) && !defined (GRUB_UTIL) && !defined (GRUB_MACHINE_EMU) && !defined (GRUB_MACHINE_XEN)
fini_cbfsdisk ();
#endif
diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c
index 6f7c439..c0bbab8 100644
--- a/grub-core/fs/jfs.c
+++ b/grub-core/fs/jfs.c
@@ -26,6 +26,7 @@
#include <grub/types.h>
#include <grub/charset.h>
#include <grub/i18n.h>
+#include <grub/lockdown.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -963,11 +964,15 @@ static struct grub_fs grub_jfs_fs =
GRUB_MOD_INIT(jfs)
{
- grub_fs_register (&grub_jfs_fs);
+ if (!grub_is_lockdown ())
+ {
+ grub_fs_register (&grub_jfs_fs);
+ }
my_mod = mod;
}
GRUB_MOD_FINI(jfs)
{
- grub_fs_unregister (&grub_jfs_fs);
+ if (!grub_is_lockdown ())
+ grub_fs_unregister (&grub_jfs_fs);
}
diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c
index 3cd18c8..7588835 100644
--- a/grub-core/fs/minix.c
+++ b/grub-core/fs/minix.c
@@ -25,6 +25,7 @@
#include <grub/dl.h>
#include <grub/types.h>
#include <grub/i18n.h>
+#include <grub/lockdown.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -732,7 +733,10 @@ GRUB_MOD_INIT(minix)
#endif
#endif
{
- grub_fs_register (&grub_minix_fs);
+ if (!grub_is_lockdown ())
+ {
+ grub_fs_register (&grub_minix_fs);
+ }
my_mod = mod;
}
@@ -754,5 +758,6 @@ GRUB_MOD_FINI(minix)
#endif
#endif
{
- grub_fs_unregister (&grub_minix_fs);
+ if (!grub_is_lockdown ())
+ grub_fs_unregister (&grub_minix_fs);
}
diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c
index aaba002..056b897 100644
--- a/grub-core/fs/nilfs2.c
+++ b/grub-core/fs/nilfs2.c
@@ -34,6 +34,7 @@
#include <grub/dl.h>
#include <grub/types.h>
#include <grub/fshelp.h>
+#include <grub/lockdown.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -1231,11 +1232,15 @@ GRUB_MOD_INIT (nilfs2)
grub_nilfs2_dat_entry));
COMPILE_TIME_ASSERT (1 << LOG_INODE_SIZE
== sizeof (struct grub_nilfs2_inode));
- grub_fs_register (&grub_nilfs2_fs);
+ if (!grub_is_lockdown ())
+ {
+ grub_fs_register (&grub_nilfs2_fs);
+ }
my_mod = mod;
}
GRUB_MOD_FINI (nilfs2)
{
- grub_fs_unregister (&grub_nilfs2_fs);
+ if (!grub_is_lockdown ())
+ grub_fs_unregister (&grub_nilfs2_fs);
}
diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
index deb058a..5b342da 100644
--- a/grub-core/fs/ntfs.c
+++ b/grub-core/fs/ntfs.c
@@ -27,6 +27,7 @@
#include <grub/fshelp.h>
#include <grub/ntfs.h>
#include <grub/charset.h>
+#include <grub/lockdown.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -1316,11 +1317,15 @@ static struct grub_fs grub_ntfs_fs =
GRUB_MOD_INIT (ntfs)
{
- grub_fs_register (&grub_ntfs_fs);
+ if (!grub_is_lockdown ())
+ {
+ grub_fs_register (&grub_ntfs_fs);
+ }
my_mod = mod;
}
GRUB_MOD_FINI (ntfs)
{
- grub_fs_unregister (&grub_ntfs_fs);
+ if (!grub_is_lockdown ())
+ grub_fs_unregister (&grub_ntfs_fs);
}
diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c
index af6a226..76cb231 100644
--- a/grub-core/fs/reiserfs.c
+++ b/grub-core/fs/reiserfs.c
@@ -39,6 +39,7 @@
#include <grub/types.h>
#include <grub/fshelp.h>
#include <grub/i18n.h>
+#include <grub/lockdown.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -1417,11 +1418,15 @@ static struct grub_fs grub_reiserfs_fs =
GRUB_MOD_INIT(reiserfs)
{
- grub_fs_register (&grub_reiserfs_fs);
+ if (!grub_is_lockdown ())
+ {
+ grub_fs_register (&grub_reiserfs_fs);
+ }
my_mod = mod;
}
GRUB_MOD_FINI(reiserfs)
{
- grub_fs_unregister (&grub_reiserfs_fs);
+ if (!grub_is_lockdown ())
+ grub_fs_unregister (&grub_reiserfs_fs);
}
diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c
index d97b8fb..d174449 100644
--- a/grub-core/fs/romfs.c
+++ b/grub-core/fs/romfs.c
@@ -23,6 +23,7 @@
#include <grub/disk.h>
#include <grub/fs.h>
#include <grub/fshelp.h>
+#include <grub/lockdown.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -475,10 +476,14 @@ static struct grub_fs grub_romfs_fs =
GRUB_MOD_INIT(romfs)
{
- grub_fs_register (&grub_romfs_fs);
+ if (!grub_is_lockdown ())
+ {
+ grub_fs_register (&grub_romfs_fs);
+ }
}
GRUB_MOD_FINI(romfs)
{
- grub_fs_unregister (&grub_romfs_fs);
+ if (!grub_is_lockdown ())
+ grub_fs_unregister (&grub_romfs_fs);
}
diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c
index 983e880..f64bdd2 100644
--- a/grub-core/fs/sfs.c
+++ b/grub-core/fs/sfs.c
@@ -26,6 +26,7 @@
#include <grub/types.h>
#include <grub/fshelp.h>
#include <grub/charset.h>
+#include <grub/lockdown.h>
#include <grub/safemath.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -779,11 +780,15 @@ static struct grub_fs grub_sfs_fs =
GRUB_MOD_INIT(sfs)
{
- grub_fs_register (&grub_sfs_fs);
+ if (!grub_is_lockdown ())
+ {
+ grub_fs_register (&grub_sfs_fs);
+ }
my_mod = mod;
}
GRUB_MOD_FINI(sfs)
{
- grub_fs_unregister (&grub_sfs_fs);
+ if (!grub_is_lockdown ())
+ grub_fs_unregister (&grub_sfs_fs);
}
diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c
index 2ac5c1d..f89c6b0 100644
--- a/grub-core/fs/udf.c
+++ b/grub-core/fs/udf.c
@@ -27,6 +27,7 @@
#include <grub/fshelp.h>
#include <grub/charset.h>
#include <grub/datetime.h>
+#include <grub/lockdown.h>
#include <grub/udf.h>
#include <grub/safemath.h>
@@ -1382,11 +1383,15 @@ static struct grub_fs grub_udf_fs = {
GRUB_MOD_INIT (udf)
{
- grub_fs_register (&grub_udf_fs);
+ if (!grub_is_lockdown ())
+ {
+ grub_fs_register (&grub_udf_fs);
+ }
my_mod = mod;
}
GRUB_MOD_FINI (udf)
{
- grub_fs_unregister (&grub_udf_fs);
+ if (!grub_is_lockdown ())
+ grub_fs_unregister (&grub_udf_fs);
}
diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c
index ea02a68..e110c2f 100644
--- a/grub-core/fs/ufs.c
+++ b/grub-core/fs/ufs.c
@@ -25,6 +25,7 @@
#include <grub/dl.h>
#include <grub/types.h>
#include <grub/i18n.h>
+#include <grub/lockdown.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -899,7 +900,10 @@ GRUB_MOD_INIT(ufs1)
#endif
#endif
{
- grub_fs_register (&grub_ufs_fs);
+ if (!grub_is_lockdown ())
+ {
+ grub_fs_register (&grub_ufs_fs);
+ }
my_mod = mod;
}
@@ -913,6 +917,7 @@ GRUB_MOD_FINI(ufs1)
#endif
#endif
{
- grub_fs_unregister (&grub_ufs_fs);
+ if (!grub_is_lockdown ())
+ grub_fs_unregister (&grub_ufs_fs);
}
--
2.33.0

View File

@ -0,0 +1,85 @@
From 071a0b83c7b085c78546f131794750df71709c12 Mon Sep 17 00:00:00 2001
From: Lidong Chen <lidong.chen@oracle.com>
Date: Tue, 21 Jan 2025 19:02:37 +0000
Subject: [PATCH 30/30] fs: Prevent overflows when allocating memory for arrays
Use grub_calloc() when allocating memory for arrays to ensure proper
overflow checks are in place.
The HFS+ and squash4 security vulnerabilities were reported by
Jonathan Bar Or <jonathanbaror@gmail.com>.
Fixes: CVE-2025-0678
Fixes: CVE-2025-1125
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/fs/btrfs.c | 4 ++--
grub-core/fs/hfspluscomp.c | 9 +++++++--
grub-core/fs/squash4.c | 8 ++++----
3 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
index cf3647a..6c2ee1b 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -1323,8 +1323,8 @@ grub_btrfs_mount (grub_device_t dev)
}
data->n_devices_allocated = 16;
- data->devices_attached = grub_malloc (sizeof (data->devices_attached[0])
- * data->n_devices_allocated);
+ data->devices_attached = grub_calloc (data->n_devices_allocated,
+ sizeof (data->devices_attached[0]));
if (!data->devices_attached)
{
grub_free (data);
diff --git a/grub-core/fs/hfspluscomp.c b/grub-core/fs/hfspluscomp.c
index d76f3f1..4965ef1 100644
--- a/grub-core/fs/hfspluscomp.c
+++ b/grub-core/fs/hfspluscomp.c
@@ -244,14 +244,19 @@ hfsplus_open_compressed_real (struct grub_hfsplus_file *node)
return 0;
}
node->compress_index_size = grub_le_to_cpu32 (index_size);
- node->compress_index = grub_malloc (node->compress_index_size
- * sizeof (node->compress_index[0]));
+ node->compress_index = grub_calloc (node->compress_index_size,
+ sizeof (node->compress_index[0]));
if (!node->compress_index)
{
node->compressed = 0;
grub_free (attr_node);
return grub_errno;
}
+
+ /*
+ * The node->compress_index_size * sizeof (node->compress_index[0]) is safe here
+ * due to relevant checks done in grub_calloc() above.
+ */
if (grub_hfsplus_read_file (node, 0, 0,
0x104 + sizeof (index_size),
node->compress_index_size
diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c
index 8295b88..9f8555f 100644
--- a/grub-core/fs/squash4.c
+++ b/grub-core/fs/squash4.c
@@ -816,10 +816,10 @@ direct_read (struct grub_squash_data *data,
break;
}
total_blocks = ((total_size + data->blksz - 1) >> data->log2_blksz);
- ino->block_sizes = grub_malloc (total_blocks
- * sizeof (ino->block_sizes[0]));
- ino->cumulated_block_sizes = grub_malloc (total_blocks
- * sizeof (ino->cumulated_block_sizes[0]));
+ ino->block_sizes = grub_calloc (total_blocks,
+ sizeof (ino->block_sizes[0]));
+ ino->cumulated_block_sizes = grub_calloc (total_blocks,
+ sizeof (ino->cumulated_block_sizes[0]));
if (!ino->block_sizes || !ino->cumulated_block_sizes)
{
grub_free (ino->block_sizes);
--
2.33.0

View File

@ -464,4 +464,33 @@ Patch0463: backport-commands-acpi-Fix-calculation-of-ACPI-tables-address.patch
Patch0464: backport-CVE-2024-1048-grub-set-bootflag-Conservative-partial-fix.patch
Patch0465: backport-CVE-2024-1048-grub-set-bootflag-More-complete-fix.patch
Patch0466: backport-CVE-2024-1048-grub-set-bootflag-Exit-calmly-when-not.patch
Patch0467: backport-0001-cryptodisk-Refactor-to-discard-have_it-global.patch
Patch0468: backport-0002-cryptodisk-Return-failure-in-cryptomount-when-no-cry.patch
Patch0469: backport-0003-cryptodisk-Improve-error-messaging-in-cryptomount-in.patch
Patch0470: backport-0004-cryptodisk-Improve-cryptomount-u-error-message.patch
Patch0471: backport-0005-cryptodisk-Add-infrastructure-to-pass-data-from-cryp.patch
Patch0472: backport-0006-cryptodisk-Refactor-password-input-out-of-crypto-dev.patch
Patch0473: backport-0007-cryptodisk-Move-global-variables-into-grub_cryptomou.patch
Patch0474: backport-0008-cryptodisk-Improve-handling-of-partition-name-in-cry.patch
Patch0475: backport-0009-cryptodisk-Fix-Coverity-use-after-free-bug.patch
Patch0476: backport-0010-misc-Implement-grub_strlcpy.patch
Patch0477: backport-0011-fs-ufs-Fix-a-heap-OOB-write.patch
Patch0478: backport-0012-fs-hfs-Fix-stack-OOB-write-with-grub_strcpy.patch
Patch0479: backport-0013-fs-tar-Integer-overflow-leads-to-heap-OOB-write.patch
Patch0480: backport-0014-fs-hfsplus-Set-a-grub_errno-if-mount-fails.patch
Patch0481: backport-0015-disk-cryptodisk-Require-authentication-after-TPM-unl.patch
Patch0482: backport-0016-net-Fix-OOB-write-in-grub_net_search_config_file.patch
Patch0483: backport-0017-video-readers-jpeg-Do-not-permit-duplicate-SOF0-mark.patch
Patch0484: backport-0018-fs-ext2-Fix-out-of-bounds-read-for-inline-extents.patch
Patch0485: backport-0019-fs-ext2-Rework-out-of-bounds-read-for-inline-and-ext.patch
Patch0486: backport-0020-commands-extcmd-Missing-check-for-failed-allocation.patch
Patch0487: backport-0021-commands-pgp-Unregister-the-check_signatures-hooks-o.patch
Patch0488: backport-0022-normal-Remove-variables-hooks-on-module-unload.patch
Patch0489: backport-0023-gettext-Remove-variables-hooks-on-module-unload.patch
Patch0490: backport-0024-gettext-Integer-overflow-leads-to-heap-OOB-write-or-.patch
Patch0491: backport-0025-gettext-Integer-overflow-leads-to-heap-OOB-write.patch
Patch0492: backport-0026-commands-read-Fix-an-integer-overflow-when-supplying.patch
Patch0493: backport-0027-commands-minicmd-Block-the-dump-command-in-lockdown-.patch
Patch0494: backport-0028-fs-bfs-Disable-under-lockdown.patch
Patch0495: backport-0029-fs-Disable-many-filesystems-under-lockdown.patch
Patch0496: backport-0030-fs-Prevent-overflows-when-allocating-memory-for-arra.patch

View File

@ -8,7 +8,7 @@
Name: grub2
Epoch: 1
Version: 2.04
Release: 39
Release: 40
Summary: Bootloader with support for Linux, Multiboot and more
License: GPLv3+
URL: http://www.gnu.org/software/grub/
@ -442,6 +442,15 @@ rm -r /boot/grub2.tmp/ || :
%{_datadir}/man/man*
%changelog
* Sat Feb 22 2025 zhangqiumiao <zhangqiumiao1@huawei.com> - 1:2.04-40
- Type:CVE
- CVE:CVE-2024-45781,CVE-2024-45782,CVE-2024-56737,CVE-2024-45780,CVE-2024-45783,CVE-2024-49504,CVE-2025-0624,CVE-20
24-45774,CVE-2024-45775,CVE-2025-0622,CVE-2025-0622,CVE-2025-0622,CVE-2024-45776,CVE-2024-45777,CVE-2025-0690,CVE-20
25-1118,CVE-2024-45778,CVE-2024-45779,CVE-2025-0677,CVE-2025-0684,CVE-2025-0685,CVE-2025-0686,CVE-2025-0689,CVE-2025
-0678,CVE-2025-1125
- SUG:NA
- DESC:fix the vulnerabilities announced on February 18th, 2025
* Tue Jun 25 2024 zhangqiumiao <zhangqiumiao1@huawei.com> - 1:2.04-39
- Type:bugfix
- CVE:NA