|
|
5975ab |
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
a4d572 |
From: Chris Coulson <chris.coulson@canonical.com>
|
|
|
a4d572 |
Date: Wed, 22 Jul 2020 17:06:04 +0100
|
|
|
5975ab |
Subject: [PATCH] Fix a regression caused by "efi: fix some malformed device
|
|
|
5975ab |
path arithmetic errors"
|
|
|
a4d572 |
|
|
|
a4d572 |
This commit introduced a bogus check inside copy_file_path to
|
|
|
a4d572 |
determine whether the destination grub_efi_file_path_device_path_t
|
|
|
a4d572 |
was valid before anything was copied to it. Depending on the
|
|
|
a4d572 |
contents of the heap buffer, this check could fail which would
|
|
|
a4d572 |
result in copy_file_path returning early.
|
|
|
a4d572 |
|
|
|
a4d572 |
Without any error propagated to the caller, make_file_path would
|
|
|
a4d572 |
then try to advance the invalid device path node with
|
|
|
a4d572 |
GRUB_EFI_NEXT_DEVICE_PATH, which would also fail, returning a NULL
|
|
|
a4d572 |
pointer that would subsequently be dereferenced.
|
|
|
a4d572 |
|
|
|
a4d572 |
Remove the bogus check, and also propagate errors from copy_file_path.
|
|
|
a4d572 |
---
|
|
|
a4d572 |
grub-core/loader/efi/chainloader.c | 26 ++++++++++++++------------
|
|
|
a4d572 |
1 file changed, 14 insertions(+), 12 deletions(-)
|
|
|
a4d572 |
|
|
|
a4d572 |
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
|
|
|
a4d572 |
index c2411b6dab2..8b99cf23e9d 100644
|
|
|
a4d572 |
--- a/grub-core/loader/efi/chainloader.c
|
|
|
a4d572 |
+++ b/grub-core/loader/efi/chainloader.c
|
|
|
a4d572 |
@@ -115,7 +115,7 @@ grub_chainloader_boot (void)
|
|
|
a4d572 |
return grub_errno;
|
|
|
a4d572 |
}
|
|
|
a4d572 |
|
|
|
a4d572 |
-static void
|
|
|
a4d572 |
+static grub_err_t
|
|
|
a4d572 |
copy_file_path (grub_efi_file_path_device_path_t *fp,
|
|
|
a4d572 |
const char *str, grub_efi_uint16_t len)
|
|
|
a4d572 |
{
|
|
|
a4d572 |
@@ -125,15 +125,9 @@ copy_file_path (grub_efi_file_path_device_path_t *fp,
|
|
|
a4d572 |
fp->header.type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE;
|
|
|
a4d572 |
fp->header.subtype = GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE;
|
|
|
a4d572 |
|
|
|
a4d572 |
- if (!GRUB_EFI_DEVICE_PATH_VALID ((grub_efi_device_path_t *)fp))
|
|
|
a4d572 |
- {
|
|
|
a4d572 |
- grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI Device Path is invalid");
|
|
|
a4d572 |
- return;
|
|
|
a4d572 |
- }
|
|
|
a4d572 |
-
|
|
|
a4d572 |
path_name = grub_calloc (len, GRUB_MAX_UTF16_PER_UTF8 * sizeof (*path_name));
|
|
|
a4d572 |
if (!path_name)
|
|
|
a4d572 |
- return;
|
|
|
a4d572 |
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "failed to allocate path buffer");
|
|
|
a4d572 |
|
|
|
a4d572 |
size = grub_utf8_to_utf16 (path_name, len * GRUB_MAX_UTF16_PER_UTF8,
|
|
|
a4d572 |
(const grub_uint8_t *) str, len, 0);
|
|
|
a4d572 |
@@ -145,6 +139,8 @@ copy_file_path (grub_efi_file_path_device_path_t *fp,
|
|
|
a4d572 |
/* File Path is NULL terminated */
|
|
|
a4d572 |
fp->path_name[size++] = '\0';
|
|
|
a4d572 |
fp->header.length = size * sizeof (grub_efi_char16_t) + sizeof (*fp);
|
|
|
a4d572 |
+ grub_free (path_name);
|
|
|
a4d572 |
+ return GRUB_ERR_NONE;
|
|
|
a4d572 |
}
|
|
|
a4d572 |
|
|
|
a4d572 |
static grub_efi_device_path_t *
|
|
|
a4d572 |
@@ -202,13 +198,19 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
|
|
|
a4d572 |
/* Fill the file path for the directory. */
|
|
|
a4d572 |
d = (grub_efi_device_path_t *) ((char *) file_path
|
|
|
a4d572 |
+ ((char *) d - (char *) dp));
|
|
|
a4d572 |
- copy_file_path ((grub_efi_file_path_device_path_t *) d,
|
|
|
a4d572 |
- dir_start, dir_end - dir_start);
|
|
|
a4d572 |
+ if (copy_file_path ((grub_efi_file_path_device_path_t *) d,
|
|
|
a4d572 |
+ dir_start, dir_end - dir_start) != GRUB_ERR_NONE)
|
|
|
a4d572 |
+ {
|
|
|
a4d572 |
+ fail:
|
|
|
a4d572 |
+ grub_free (file_path);
|
|
|
a4d572 |
+ return 0;
|
|
|
a4d572 |
+ }
|
|
|
a4d572 |
|
|
|
a4d572 |
/* Fill the file path for the file. */
|
|
|
a4d572 |
d = GRUB_EFI_NEXT_DEVICE_PATH (d);
|
|
|
a4d572 |
- copy_file_path ((grub_efi_file_path_device_path_t *) d,
|
|
|
a4d572 |
- dir_end + 1, grub_strlen (dir_end + 1));
|
|
|
a4d572 |
+ if (copy_file_path ((grub_efi_file_path_device_path_t *) d,
|
|
|
a4d572 |
+ dir_end + 1, grub_strlen (dir_end + 1)) != GRUB_ERR_NONE)
|
|
|
a4d572 |
+ goto fail;
|
|
|
a4d572 |
|
|
|
a4d572 |
/* Fill the end of device path nodes. */
|
|
|
a4d572 |
d = GRUB_EFI_NEXT_DEVICE_PATH (d);
|