import grub2-2.06-46.el9_1.3

c9 imports/c9/grub2-2.06-46.el9_1.3
CentOS Sources 2 years ago committed by MSVSphere Packaging Team
parent 6d28912ce4
commit 56fecf0c2a

@ -0,0 +1,37 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Tue, 11 Oct 2022 17:00:50 -0400
Subject: [PATCH] x86-efi: Fix an incorrect array size in kernel allocation
In 81a6ebf62bbe166ddc968463df2e8bd481bf697c ("efi: split allocation
policy for kernel vs initrd memories."), I introduced a split in the
kernel allocator to allow for different dynamic policies for the kernel
and the initrd allocations.
Unfortunately, that change increased the size of the policy data used to
make decisions, but did not change the size of the temporary storage we
use to back it up and restore. This results in some of .data getting
clobbered at runtime, and hilarity ensues.
This patch makes the size of the backup storage be based on the size of
the initial policy data.
Signed-off-by: Peter Jones <pjones@redhat.com>
(cherry picked from commit 37747b22342499a798ca3a8895770cd93b6e1258)
---
grub-core/loader/i386/efi/linux.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
index f23b3f7b01..18aadc3e07 100644
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -93,7 +93,7 @@ static struct allocation_choice max_addresses[] =
{ INITRD_MEM, GRUB_EFI_MAX_ALLOCATION_ADDRESS, GRUB_EFI_ALLOCATE_MAX_ADDRESS },
{ NO_MEM, 0, 0 }
};
-static struct allocation_choice saved_addresses[4];
+static struct allocation_choice saved_addresses[sizeof(max_addresses) / sizeof(max_addresses[0])];
#define save_addresses() grub_memcpy(saved_addresses, max_addresses, sizeof(max_addresses))
#define restore_addresses() grub_memcpy(max_addresses, saved_addresses, sizeof(max_addresses))

@ -0,0 +1,43 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lu Ken <ken.lu@intel.com>
Date: Wed, 13 Jul 2022 10:06:10 +0800
Subject: [PATCH] commands/efi/tpm: Refine the status of log event
1. Use macro GRUB_ERR_NONE instead of hard code 0.
2. Keep lowercase of the first char for the status string of log event.
Signed-off-by: Lu Ken <ken.lu@intel.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
(cherry picked from commit 922898573e37135f5dedc16f3e15a1d1d4c53f8a)
(cherry picked from commit a326f1247c4d3a1d1079eacbe7e58b35b9a287e2)
---
grub-core/commands/efi/tpm.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c
index a97d85368a..7acf510499 100644
--- a/grub-core/commands/efi/tpm.c
+++ b/grub-core/commands/efi/tpm.c
@@ -135,17 +135,17 @@ grub_efi_log_event_status (grub_efi_status_t status)
switch (status)
{
case GRUB_EFI_SUCCESS:
- return 0;
+ return GRUB_ERR_NONE;
case GRUB_EFI_DEVICE_ERROR:
- return grub_error (GRUB_ERR_IO, N_("Command failed"));
+ return grub_error (GRUB_ERR_IO, N_("command failed"));
case GRUB_EFI_INVALID_PARAMETER:
- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid parameter"));
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid parameter"));
case GRUB_EFI_BUFFER_TOO_SMALL:
- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Output buffer too small"));
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("output buffer too small"));
case GRUB_EFI_NOT_FOUND:
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("TPM unavailable"));
default:
- return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("Unknown TPM error"));
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("unknown TPM error"));
}
}

@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lu Ken <ken.lu@intel.com>
Date: Wed, 13 Jul 2022 10:06:11 +0800
Subject: [PATCH] commands/efi/tpm: Use grub_strcpy() instead of grub_memcpy()
The event description is a string, so using grub_strcpy() is cleaner than
using grub_memcpy().
Signed-off-by: Lu Ken <ken.lu@intel.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
(cherry picked from commit ef8679b645a63eb9eb191bb9539d7d25a9d6ff3b)
(cherry picked from commit 6d0d478585c435cce50d4025d2301dc0413bc5c0)
---
grub-core/commands/efi/tpm.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c
index 7acf510499..bb59599721 100644
--- a/grub-core/commands/efi/tpm.c
+++ b/grub-core/commands/efi/tpm.c
@@ -175,7 +175,7 @@ grub_tpm1_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf,
event->PCRIndex = pcr;
event->EventType = EV_IPL;
event->EventSize = grub_strlen (description) + 1;
- grub_memcpy (event->Event, description, event->EventSize);
+ grub_strcpy ((char *) event->Event, description);
algorithm = TCG_ALG_SHA;
status = efi_call_7 (tpm->log_extend_event, tpm, (grub_addr_t) buf, (grub_uint64_t) size,
@@ -212,7 +212,7 @@ grub_tpm2_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf,
event->Header.EventType = EV_IPL;
event->Size =
sizeof (*event) - sizeof (event->Event) + grub_strlen (description) + 1;
- grub_memcpy (event->Event, description, grub_strlen (description) + 1);
+ grub_strcpy ((char *) event->Event, description);
status = efi_call_5 (tpm->hash_log_extend_event, tpm, 0, (grub_addr_t) buf,
(grub_uint64_t) size, event);

@ -0,0 +1,259 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lu Ken <ken.lu@intel.com>
Date: Wed, 13 Jul 2022 10:06:12 +0800
Subject: [PATCH] efi/tpm: Add EFI_CC_MEASUREMENT_PROTOCOL support
The EFI_CC_MEASUREMENT_PROTOCOL abstracts the measurement for virtual firmware
in confidential computing environment. It is similar to the EFI_TCG2_PROTOCOL.
It was proposed by Intel and ARM and approved by UEFI organization.
It is defined in Intel GHCI specification: https://cdrdv2.intel.com/v1/dl/getContent/726790 .
The EDKII header file is available at https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/CcMeasurement.h .
Signed-off-by: Lu Ken <ken.lu@intel.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
(cherry picked from commit 4c76565b6cb885b7e144dc27f3612066844e2d19)
(cherry picked from commit cad2fc1ff659390a228efb474a72f7ed7ab21697)
---
grub-core/commands/efi/tpm.c | 48 ++++++++++++++
include/grub/efi/cc.h | 151 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 199 insertions(+)
create mode 100644 include/grub/efi/cc.h
diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c
index bb59599721..ae09c1bf8b 100644
--- a/grub-core/commands/efi/tpm.c
+++ b/grub-core/commands/efi/tpm.c
@@ -22,6 +22,7 @@
#include <grub/i18n.h>
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
+#include <grub/efi/cc.h>
#include <grub/efi/tpm.h>
#include <grub/mm.h>
#include <grub/tpm.h>
@@ -31,6 +32,7 @@ typedef TCG_PCR_EVENT grub_tpm_event_t;
static grub_efi_guid_t tpm_guid = EFI_TPM_GUID;
static grub_efi_guid_t tpm2_guid = EFI_TPM2_GUID;
+static grub_efi_guid_t cc_measurement_guid = GRUB_EFI_CC_MEASUREMENT_PROTOCOL_GUID;
static grub_efi_handle_t *grub_tpm_handle;
static grub_uint8_t grub_tpm_version;
@@ -221,6 +223,50 @@ grub_tpm2_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf,
return grub_efi_log_event_status (status);
}
+static void
+grub_cc_log_event (unsigned char *buf, grub_size_t size, grub_uint8_t pcr,
+ const char *description)
+{
+ grub_efi_cc_event_t *event;
+ grub_efi_status_t status;
+ grub_efi_cc_protocol_t *cc;
+ grub_efi_cc_mr_index_t mr;
+
+ cc = grub_efi_locate_protocol (&cc_measurement_guid, NULL);
+ if (cc == NULL)
+ return;
+
+ status = efi_call_3 (cc->map_pcr_to_mr_index, cc, pcr, &mr);
+ if (status != GRUB_EFI_SUCCESS)
+ {
+ grub_efi_log_event_status (status);
+ return;
+ }
+
+ event = grub_zalloc (sizeof (grub_efi_cc_event_t) +
+ grub_strlen (description) + 1);
+ if (event == NULL)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate CC event buffer"));
+ return;
+ }
+
+ event->Header.HeaderSize = sizeof (grub_efi_cc_event_header_t);
+ event->Header.HeaderVersion = GRUB_EFI_CC_EVENT_HEADER_VERSION;
+ event->Header.MrIndex = mr;
+ event->Header.EventType = EV_IPL;
+ event->Size = sizeof (*event) + grub_strlen (description) + 1;
+ grub_strcpy ((char *) event->Event, description);
+
+ status = efi_call_5 (cc->hash_log_extend_event, cc, 0,
+ (grub_efi_physical_address_t)(grub_addr_t) buf,
+ (grub_efi_uint64_t) size, event);
+ grub_free (event);
+
+ if (status != GRUB_EFI_SUCCESS)
+ grub_efi_log_event_status (status);
+}
+
grub_err_t
grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr,
const char *description)
@@ -228,6 +274,8 @@ grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr,
grub_efi_handle_t tpm_handle;
grub_efi_uint8_t protocol_version;
+ grub_cc_log_event(buf, size, pcr, description);
+
if (!grub_tpm_handle_find (&tpm_handle, &protocol_version))
return 0;
diff --git a/include/grub/efi/cc.h b/include/grub/efi/cc.h
new file mode 100644
index 0000000000..8960306890
--- /dev/null
+++ b/include/grub/efi/cc.h
@@ -0,0 +1,151 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2022 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_EFI_CC_H
+#define GRUB_EFI_CC_H 1
+
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+#include <grub/err.h>
+
+#define GRUB_EFI_CC_MEASUREMENT_PROTOCOL_GUID \
+ { 0x96751a3d, 0x72f4, 0x41a6, \
+ { 0xa7, 0x94, 0xed, 0x5d, 0x0e, 0x67, 0xae, 0x6b } \
+ };
+
+struct grub_efi_cc_version
+{
+ grub_efi_uint8_t Major;
+ grub_efi_uint8_t Minor;
+};
+typedef struct grub_efi_cc_version grub_efi_cc_version_t;
+
+/* EFI_CC Type/SubType definition. */
+#define GRUB_EFI_CC_TYPE_NONE 0
+#define GRUB_EFI_CC_TYPE_SEV 1
+#define GRUB_EFI_CC_TYPE_TDX 2
+
+struct grub_efi_cc_type
+{
+ grub_efi_uint8_t Type;
+ grub_efi_uint8_t SubType;
+};
+typedef struct grub_efi_cc_type grub_efi_cc_type_t;
+
+typedef grub_efi_uint32_t grub_efi_cc_event_log_bitmap_t;
+typedef grub_efi_uint32_t grub_efi_cc_event_log_format_t;
+typedef grub_efi_uint32_t grub_efi_cc_event_algorithm_bitmap_t;
+typedef grub_efi_uint32_t grub_efi_cc_mr_index_t;
+
+/* Intel TDX measure register index. */
+#define GRUB_TDX_MR_INDEX_MRTD 0
+#define GRUB_TDX_MR_INDEX_RTMR0 1
+#define GRUB_TDX_MR_INDEX_RTMR1 2
+#define GRUB_TDX_MR_INDEX_RTMR2 3
+#define GRUB_TDX_MR_INDEX_RTMR3 4
+
+#define GRUB_EFI_CC_EVENT_LOG_FORMAT_TCG_2 0x00000002
+#define GRUB_EFI_CC_BOOT_HASH_ALG_SHA384 0x00000004
+#define GRUB_EFI_CC_EVENT_HEADER_VERSION 1
+
+struct grub_efi_cc_event_header
+{
+ /* Size of the event header itself (sizeof(EFI_TD_EVENT_HEADER)). */
+ grub_efi_uint32_t HeaderSize;
+
+ /*
+ * Header version. For this version of this specification,
+ * the value shall be 1.
+ */
+ grub_efi_uint16_t HeaderVersion;
+
+ /* Index of the MR that shall be extended. */
+ grub_efi_cc_mr_index_t MrIndex;
+
+ /* Type of the event that shall be extended (and optionally logged). */
+ grub_efi_uint32_t EventType;
+} GRUB_PACKED;
+typedef struct grub_efi_cc_event_header grub_efi_cc_event_header_t;
+
+struct grub_efi_cc_event
+{
+ /* Total size of the event including the Size component, the header and the Event data. */
+ grub_efi_uint32_t Size;
+ grub_efi_cc_event_header_t Header;
+ grub_efi_uint8_t Event[0];
+} GRUB_PACKED;
+typedef struct grub_efi_cc_event grub_efi_cc_event_t;
+
+struct grub_efi_cc_boot_service_capability
+{
+ /* Allocated size of the structure. */
+ grub_efi_uint8_t Size;
+
+ /*
+ * Version of the grub_efi_cc_boot_service_capability_t structure itself.
+ * For this version of the protocol, the Major version shall be set to 1
+ * and the Minor version shall be set to 1.
+ */
+ grub_efi_cc_version_t StructureVersion;
+
+ /*
+ * Version of the EFI TD protocol.
+ * For this version of the protocol, the Major version shall be set to 1
+ * and the Minor version shall be set to 1.
+ */
+ grub_efi_cc_version_t ProtocolVersion;
+
+ /* Supported hash algorithms. */
+ grub_efi_cc_event_algorithm_bitmap_t HashAlgorithmBitmap;
+
+ /* Bitmap of supported event log formats. */
+ grub_efi_cc_event_log_bitmap_t SupportedEventLogs;
+
+ /* Indicates the CC type. */
+ grub_efi_cc_type_t CcType;
+};
+typedef struct grub_efi_cc_boot_service_capability grub_efi_cc_boot_service_capability_t;
+
+struct grub_efi_cc_protocol
+{
+ grub_efi_status_t
+ (*get_capability) (struct grub_efi_cc_protocol *this,
+ grub_efi_cc_boot_service_capability_t *ProtocolCapability);
+
+ grub_efi_status_t
+ (*get_event_log) (struct grub_efi_cc_protocol *this,
+ grub_efi_cc_event_log_format_t EventLogFormat,
+ grub_efi_physical_address_t *EventLogLocation,
+ grub_efi_physical_address_t *EventLogLastEntry,
+ grub_efi_boolean_t *EventLogTruncated);
+
+ grub_efi_status_t
+ (*hash_log_extend_event) (struct grub_efi_cc_protocol *this,
+ grub_efi_uint64_t Flags,
+ grub_efi_physical_address_t DataToHash,
+ grub_efi_uint64_t DataToHashLen,
+ grub_efi_cc_event_t *EfiCcEvent);
+
+ grub_efi_status_t
+ (*map_pcr_to_mr_index) (struct grub_efi_cc_protocol *this,
+ grub_efi_uint32_t PcrIndex,
+ grub_efi_cc_mr_index_t *MrIndex);
+};
+typedef struct grub_efi_cc_protocol grub_efi_cc_protocol_t;
+
+#endif

@ -0,0 +1,32 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zhang Boyang <zhangboyang.id@gmail.com>
Date: Wed, 3 Aug 2022 19:45:33 +0800
Subject: [PATCH] font: Reject glyphs exceeds font->max_glyph_width or
font->max_glyph_height
Check glyph's width and height against limits specified in font's
metadata. Reject the glyph (and font) if such limits are exceeded.
Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
(cherry picked from commit 5760fcfd466cc757540ea0d591bad6a08caeaa16)
(cherry picked from commit 3b410ef4bb95e607cadeba2193fa90ae9bddb98d)
---
grub-core/font/font.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/grub-core/font/font.c b/grub-core/font/font.c
index d09bb38d89..2f09a4a55b 100644
--- a/grub-core/font/font.c
+++ b/grub-core/font/font.c
@@ -760,7 +760,9 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code)
|| read_be_uint16 (font->file, &height) != 0
|| read_be_int16 (font->file, &xoff) != 0
|| read_be_int16 (font->file, &yoff) != 0
- || read_be_int16 (font->file, &dwidth) != 0)
+ || read_be_int16 (font->file, &dwidth) != 0
+ || width > font->max_char_width
+ || height > font->max_char_height)
{
remove_font (font);
return 0;

@ -0,0 +1,111 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zhang Boyang <zhangboyang.id@gmail.com>
Date: Fri, 5 Aug 2022 00:51:20 +0800
Subject: [PATCH] font: Fix size overflow in grub_font_get_glyph_internal()
The length of memory allocation and file read may overflow. This patch
fixes the problem by using safemath macros.
There is a lot of code repetition like "(x * y + 7) / 8". It is unsafe
if overflow happens. This patch introduces grub_video_bitmap_calc_1bpp_bufsz().
It is safe replacement for such code. It has safemath-like prototype.
This patch also introduces grub_cast(value, pointer), it casts value to
typeof(*pointer) then store the value to *pointer. It returns true when
overflow occurs or false if there is no overflow. The semantics of arguments
and return value are designed to be consistent with other safemath macros.
Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
(cherry picked from commit 941d10ad6f1dcbd12fb613002249e29ba035f985)
(cherry picked from commit 6bca9693878bdf61dd62b8c784862a48e75f569a)
---
grub-core/font/font.c | 17 +++++++++++++----
include/grub/bitmap.h | 18 ++++++++++++++++++
include/grub/safemath.h | 2 ++
3 files changed, 33 insertions(+), 4 deletions(-)
diff --git a/grub-core/font/font.c b/grub-core/font/font.c
index 2f09a4a55b..6a3fbebbd8 100644
--- a/grub-core/font/font.c
+++ b/grub-core/font/font.c
@@ -739,7 +739,8 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code)
grub_int16_t xoff;
grub_int16_t yoff;
grub_int16_t dwidth;
- int len;
+ grub_ssize_t len;
+ grub_size_t sz;
if (index_entry->glyph)
/* Return cached glyph. */
@@ -768,9 +769,17 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code)
return 0;
}
- len = (width * height + 7) / 8;
- glyph = grub_malloc (sizeof (struct grub_font_glyph) + len);
- if (!glyph)
+ /* Calculate real struct size of current glyph. */
+ if (grub_video_bitmap_calc_1bpp_bufsz (width, height, &len) ||
+ grub_add (sizeof (struct grub_font_glyph), len, &sz))
+ {
+ remove_font (font);
+ return 0;
+ }
+
+ /* Allocate and initialize the glyph struct. */
+ glyph = grub_malloc (sz);
+ if (glyph == NULL)
{
remove_font (font);
return 0;
diff --git a/include/grub/bitmap.h b/include/grub/bitmap.h
index 5728f8ca3a..0d9603f619 100644
--- a/include/grub/bitmap.h
+++ b/include/grub/bitmap.h
@@ -23,6 +23,7 @@
#include <grub/symbol.h>
#include <grub/types.h>
#include <grub/video.h>
+#include <grub/safemath.h>
struct grub_video_bitmap
{
@@ -79,6 +80,23 @@ grub_video_bitmap_get_height (struct grub_video_bitmap *bitmap)
return bitmap->mode_info.height;
}
+/*
+ * Calculate and store the size of data buffer of 1bit bitmap in result.
+ * Equivalent to "*result = (width * height + 7) / 8" if no overflow occurs.
+ * Return true when overflow occurs or false if there is no overflow.
+ * This function is intentionally implemented as a macro instead of
+ * an inline function. Although a bit awkward, it preserves data types for
+ * safemath macros and reduces macro side effects as much as possible.
+ *
+ * XXX: Will report false overflow if width * height > UINT64_MAX.
+ */
+#define grub_video_bitmap_calc_1bpp_bufsz(width, height, result) \
+({ \
+ grub_uint64_t _bitmap_pixels; \
+ grub_mul ((width), (height), &_bitmap_pixels) ? 1 : \
+ grub_cast (_bitmap_pixels / GRUB_CHAR_BIT + !!(_bitmap_pixels % GRUB_CHAR_BIT), (result)); \
+})
+
void EXPORT_FUNC (grub_video_bitmap_get_mode_info) (struct grub_video_bitmap *bitmap,
struct grub_video_mode_info *mode_info);
diff --git a/include/grub/safemath.h b/include/grub/safemath.h
index c17b89bba1..bb0f826de1 100644
--- a/include/grub/safemath.h
+++ b/include/grub/safemath.h
@@ -30,6 +30,8 @@
#define grub_sub(a, b, res) __builtin_sub_overflow(a, b, res)
#define grub_mul(a, b, res) __builtin_mul_overflow(a, b, res)
+#define grub_cast(a, res) grub_add ((a), 0, (res))
+
#else
#error gcc 5.1 or newer or clang 3.8 or newer is required
#endif

@ -0,0 +1,80 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zhang Boyang <zhangboyang.id@gmail.com>
Date: Fri, 5 Aug 2022 01:58:27 +0800
Subject: [PATCH] font: Fix several integer overflows in
grub_font_construct_glyph()
This patch fixes several integer overflows in grub_font_construct_glyph().
Glyphs of invalid size, zero or leading to an overflow, are rejected.
The inconsistency between "glyph" and "max_glyph_size" when grub_malloc()
returns NULL is fixed too.
Fixes: CVE-2022-2601
Reported-by: Zhang Boyang <zhangboyang.id@gmail.com>
Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
(cherry picked from commit b1805f251b31a9d3cfae5c3572ddfa630145dbbf)
(cherry picked from commit b91eb9bd6c724339b7d7bb4765b9d36f1ee88b84)
---
grub-core/font/font.c | 29 +++++++++++++++++------------
1 file changed, 17 insertions(+), 12 deletions(-)
diff --git a/grub-core/font/font.c b/grub-core/font/font.c
index 6a3fbebbd8..1fa181d4ca 100644
--- a/grub-core/font/font.c
+++ b/grub-core/font/font.c
@@ -1517,6 +1517,7 @@ grub_font_construct_glyph (grub_font_t hinted_font,
struct grub_video_signed_rect bounds;
static struct grub_font_glyph *glyph = 0;
static grub_size_t max_glyph_size = 0;
+ grub_size_t cur_glyph_size;
ensure_comb_space (glyph_id);
@@ -1533,29 +1534,33 @@ grub_font_construct_glyph (grub_font_t hinted_font,
if (!glyph_id->ncomb && !glyph_id->attributes)
return main_glyph;
- if (max_glyph_size < sizeof (*glyph) + (bounds.width * bounds.height + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT)
+ if (grub_video_bitmap_calc_1bpp_bufsz (bounds.width, bounds.height, &cur_glyph_size) ||
+ grub_add (sizeof (*glyph), cur_glyph_size, &cur_glyph_size))
+ return main_glyph;
+
+ if (max_glyph_size < cur_glyph_size)
{
grub_free (glyph);
- max_glyph_size = (sizeof (*glyph) + (bounds.width * bounds.height + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT) * 2;
- if (max_glyph_size < 8)
- max_glyph_size = 8;
- glyph = grub_malloc (max_glyph_size);
+ if (grub_mul (cur_glyph_size, 2, &max_glyph_size))
+ max_glyph_size = 0;
+ glyph = max_glyph_size > 0 ? grub_malloc (max_glyph_size) : NULL;
}
if (!glyph)
{
+ max_glyph_size = 0;
grub_errno = GRUB_ERR_NONE;
return main_glyph;
}
- grub_memset (glyph, 0, sizeof (*glyph)
- + (bounds.width * bounds.height
- + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT);
+ grub_memset (glyph, 0, cur_glyph_size);
glyph->font = main_glyph->font;
- glyph->width = bounds.width;
- glyph->height = bounds.height;
- glyph->offset_x = bounds.x;
- glyph->offset_y = bounds.y;
+ if (bounds.width == 0 || bounds.height == 0 ||
+ grub_cast (bounds.width, &glyph->width) ||
+ grub_cast (bounds.height, &glyph->height) ||
+ grub_cast (bounds.x, &glyph->offset_x) ||
+ grub_cast (bounds.y, &glyph->offset_y))
+ return main_glyph;
if (glyph_id->attributes & GRUB_UNICODE_GLYPH_ATTRIBUTE_MIRROR)
grub_font_blit_glyph_mirror (glyph, main_glyph,

@ -0,0 +1,41 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zhang Boyang <zhangboyang.id@gmail.com>
Date: Fri, 5 Aug 2022 02:13:29 +0800
Subject: [PATCH] font: Remove grub_font_dup_glyph()
Remove grub_font_dup_glyph() since nobody is using it since 2013, and
I'm too lazy to fix the integer overflow problem in it.
Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
(cherry picked from commit 25ad31c19c331aaa2dbd9bd2b2e2655de5766a9d)
(cherry picked from commit ad950e1e033318bb50222ed268a6dcfb97389035)
---
grub-core/font/font.c | 14 --------------
1 file changed, 14 deletions(-)
diff --git a/grub-core/font/font.c b/grub-core/font/font.c
index 1fa181d4ca..a115a63b0c 100644
--- a/grub-core/font/font.c
+++ b/grub-core/font/font.c
@@ -1055,20 +1055,6 @@ grub_font_get_glyph_with_fallback (grub_font_t font, grub_uint32_t code)
return best_glyph;
}
-#if 0
-static struct grub_font_glyph *
-grub_font_dup_glyph (struct grub_font_glyph *glyph)
-{
- static struct grub_font_glyph *ret;
- ret = grub_malloc (sizeof (*ret) + (glyph->width * glyph->height + 7) / 8);
- if (!ret)
- return NULL;
- grub_memcpy (ret, glyph, sizeof (*ret)
- + (glyph->width * glyph->height + 7) / 8);
- return ret;
-}
-#endif
-
/* FIXME: suboptimal. */
static void
grub_font_blit_glyph (struct grub_font_glyph *target,

@ -0,0 +1,47 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zhang Boyang <zhangboyang.id@gmail.com>
Date: Fri, 5 Aug 2022 02:27:05 +0800
Subject: [PATCH] font: Fix integer overflow in ensure_comb_space()
In fact it can't overflow at all because glyph_id->ncomb is only 8-bit
wide. But let's keep safe if somebody changes the width of glyph_id->ncomb
in the future. This patch also fixes the inconsistency between
render_max_comb_glyphs and render_combining_glyphs when grub_malloc()
returns NULL.
Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
(cherry picked from commit b2740b7e4a03bb8331d48b54b119afea76bb9d5f)
(cherry picked from commit f66ea1e60c347408e92b6695d5105c7e0f24d568)
---
grub-core/font/font.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/grub-core/font/font.c b/grub-core/font/font.c
index a115a63b0c..d0e6340404 100644
--- a/grub-core/font/font.c
+++ b/grub-core/font/font.c
@@ -1468,14 +1468,18 @@ ensure_comb_space (const struct grub_unicode_glyph *glyph_id)
if (glyph_id->ncomb <= render_max_comb_glyphs)
return;
- render_max_comb_glyphs = 2 * glyph_id->ncomb;
- if (render_max_comb_glyphs < 8)
+ if (grub_mul (glyph_id->ncomb, 2, &render_max_comb_glyphs))
+ render_max_comb_glyphs = 0;
+ if (render_max_comb_glyphs > 0 && render_max_comb_glyphs < 8)
render_max_comb_glyphs = 8;
grub_free (render_combining_glyphs);
- render_combining_glyphs = grub_malloc (render_max_comb_glyphs
- * sizeof (render_combining_glyphs[0]));
+ render_combining_glyphs = (render_max_comb_glyphs > 0) ?
+ grub_calloc (render_max_comb_glyphs, sizeof (render_combining_glyphs[0])) : NULL;
if (!render_combining_glyphs)
- grub_errno = 0;
+ {
+ render_max_comb_glyphs = 0;
+ grub_errno = GRUB_ERR_NONE;
+ }
}
int

@ -0,0 +1,64 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zhang Boyang <zhangboyang.id@gmail.com>
Date: Mon, 15 Aug 2022 02:04:58 +0800
Subject: [PATCH] font: Fix integer overflow in BMP index
The BMP index (font->bmp_idx) is designed as a reverse lookup table of
char entries (font->char_index), in order to speed up lookups for BMP
chars (i.e. code < 0x10000). The values in BMP index are the subscripts
of the corresponding char entries, stored in grub_uint16_t, while 0xffff
means not found.
This patch fixes the problem of large subscript truncated to grub_uint16_t,
leading BMP index to return wrong char entry or report false miss. The
code now checks for bounds and uses BMP index as a hint, and fallbacks
to binary-search if necessary.
On the occasion add a comment about BMP index is initialized to 0xffff.
Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
(cherry picked from commit afda8b60ba0712abe01ae1e64c5f7a067a0e6492)
(cherry picked from commit 6d90568929e11739b56f09ebbce9185ca9c23519)
---
grub-core/font/font.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/grub-core/font/font.c b/grub-core/font/font.c
index d0e6340404..b208a28717 100644
--- a/grub-core/font/font.c
+++ b/grub-core/font/font.c
@@ -300,6 +300,8 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct
font->bmp_idx = grub_malloc (0x10000 * sizeof (grub_uint16_t));
if (!font->bmp_idx)
return 1;
+
+ /* Init the BMP index array to 0xffff. */
grub_memset (font->bmp_idx, 0xff, 0x10000 * sizeof (grub_uint16_t));
@@ -328,7 +330,7 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct
return 1;
}
- if (entry->code < 0x10000)
+ if (entry->code < 0x10000 && i < 0xffff)
font->bmp_idx[entry->code] = i;
last_code = entry->code;
@@ -696,9 +698,12 @@ find_glyph (const grub_font_t font, grub_uint32_t code)
/* Use BMP index if possible. */
if (code < 0x10000 && font->bmp_idx)
{
- if (font->bmp_idx[code] == 0xffff)
- return 0;
- return &table[font->bmp_idx[code]];
+ if (font->bmp_idx[code] < 0xffff)
+ return &table[font->bmp_idx[code]];
+ /*
+ * When we are here then lookup in BMP index result in miss,
+ * fallthough to binary-search.
+ */
}
/* Do a binary search in `char_index', which is ordered by code point. */

@ -0,0 +1,84 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zhang Boyang <zhangboyang.id@gmail.com>
Date: Sun, 14 Aug 2022 18:09:38 +0800
Subject: [PATCH] font: Fix integer underflow in binary search of char index
If search target is less than all entries in font->index then "hi"
variable is set to -1, which translates to SIZE_MAX and leads to errors.
This patch fixes the problem by replacing the entire binary search code
with the libstdc++'s std::lower_bound() implementation.
Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
(cherry picked from commit c140a086838e7c9af87842036f891b8393a8c4bc)
(cherry picked from commit e110997335b1744464ea232d57a7d86e16ca8dee)
---
grub-core/font/font.c | 40 ++++++++++++++++++++++------------------
1 file changed, 22 insertions(+), 18 deletions(-)
diff --git a/grub-core/font/font.c b/grub-core/font/font.c
index b208a28717..193dfec045 100644
--- a/grub-core/font/font.c
+++ b/grub-core/font/font.c
@@ -688,12 +688,12 @@ read_be_int16 (grub_file_t file, grub_int16_t * value)
static inline struct char_index_entry *
find_glyph (const grub_font_t font, grub_uint32_t code)
{
- struct char_index_entry *table;
- grub_size_t lo;
- grub_size_t hi;
- grub_size_t mid;
+ struct char_index_entry *table, *first, *end;
+ grub_size_t len;
table = font->char_index;
+ if (table == NULL)
+ return NULL;
/* Use BMP index if possible. */
if (code < 0x10000 && font->bmp_idx)
@@ -706,25 +706,29 @@ find_glyph (const grub_font_t font, grub_uint32_t code)
*/
}
- /* Do a binary search in `char_index', which is ordered by code point. */
- lo = 0;
- hi = font->num_chars - 1;
+ /*
+ * Do a binary search in char_index which is ordered by code point.
+ * The code below is the same as libstdc++'s std::lower_bound().
+ */
+ first = table;
+ len = font->num_chars;
+ end = first + len;
- if (!table)
- return 0;
-
- while (lo <= hi)
+ while (len > 0)
{
- mid = lo + (hi - lo) / 2;
- if (code < table[mid].code)
- hi = mid - 1;
- else if (code > table[mid].code)
- lo = mid + 1;
+ grub_size_t half = len >> 1;
+ struct char_index_entry *middle = first + half;
+
+ if (middle->code < code)
+ {
+ first = middle + 1;
+ len = len - half - 1;
+ }
else
- return &table[mid];
+ len = half;
}
- return 0;
+ return (first < end && first->code == code) ? first : NULL;
}
/* Get a glyph for the Unicode character CODE in FONT. The glyph is loaded

@ -0,0 +1,53 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zhang Boyang <zhangboyang.id@gmail.com>
Date: Sun, 14 Aug 2022 15:51:54 +0800
Subject: [PATCH] kern/efi/sb: Enforce verification of font files
As a mitigation and hardening measure enforce verification of font
files. Then only trusted font files can be load. This will reduce the
attack surface at cost of losing the ability of end-users to customize
fonts if e.g. UEFI Secure Boot is enabled. Vendors can always customize
fonts because they have ability to pack fonts into their GRUB bundles.
This goal is achieved by:
* Removing GRUB_FILE_TYPE_FONT from shim lock verifier's
skip-verification list.
* Adding GRUB_FILE_TYPE_FONT to lockdown verifier's defer-auth list,
so font files must be verified by a verifier before they can be loaded.
Suggested-by: Daniel Kiper <daniel.kiper@oracle.com>
Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
(cherry picked from commit 630deb8c0d8b02b670ced4b7030414bcf17aa080)
(cherry picked from commit 37257e0ee45b9029b62f4046c983481d063b821d)
---
grub-core/kern/efi/sb.c | 1 -
grub-core/kern/lockdown.c | 1 +
2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c
index 89c4bb3fd1..db42c2539f 100644
--- a/grub-core/kern/efi/sb.c
+++ b/grub-core/kern/efi/sb.c
@@ -145,7 +145,6 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)),
case GRUB_FILE_TYPE_PRINT_BLOCKLIST:
case GRUB_FILE_TYPE_TESTLOAD:
case GRUB_FILE_TYPE_GET_SIZE:
- case GRUB_FILE_TYPE_FONT:
case GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY:
case GRUB_FILE_TYPE_CAT:
case GRUB_FILE_TYPE_HEXCAT:
diff --git a/grub-core/kern/lockdown.c b/grub-core/kern/lockdown.c
index 0bc70fd42d..af6d493cd3 100644
--- a/grub-core/kern/lockdown.c
+++ b/grub-core/kern/lockdown.c
@@ -51,6 +51,7 @@ lockdown_verifier_init (grub_file_t io __attribute__ ((unused)),
case GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE:
case GRUB_FILE_TYPE_ACPI_TABLE:
case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE:
+ case GRUB_FILE_TYPE_FONT:
*flags = GRUB_VERIFY_FLAGS_DEFER_AUTH;
/* Fall through. */

@ -0,0 +1,84 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zhang Boyang <zhangboyang.id@gmail.com>
Date: Tue, 6 Sep 2022 03:03:21 +0800
Subject: [PATCH] fbutil: Fix integer overflow
Expressions like u64 = u32 * u32 are unsafe because their products are
truncated to u32 even if left hand side is u64. This patch fixes all
problems like that one in fbutil.
To get right result not only left hand side have to be u64 but it's also
necessary to cast at least one of the operands of all leaf operators of
right hand side to u64, e.g. u64 = u32 * u32 + u32 * u32 should be
u64 = (u64)u32 * u32 + (u64)u32 * u32.
For 1-bit bitmaps grub_uint64_t have to be used. It's safe because any
combination of values in (grub_uint64_t)u32 * u32 + u32 expression will
not overflow grub_uint64_t.
Other expressions like ptr + u32 * u32 + u32 * u32 are also vulnerable.
They should be ptr + (grub_addr_t)u32 * u32 + (grub_addr_t)u32 * u32.
This patch also adds a comment to grub_video_fb_get_video_ptr() which
says it's arguments must be valid and no sanity check is performed
(like its siblings in grub-core/video/fb/fbutil.c).
Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
(cherry picked from commit 50a11a81bc842c58962244a2dc86bbd31a426e12)
(cherry picked from commit 8fa75d647362c938c4cc302cf5945b31fb92c078)
---
grub-core/video/fb/fbutil.c | 4 ++--
include/grub/fbutil.h | 13 +++++++++----
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/grub-core/video/fb/fbutil.c b/grub-core/video/fb/fbutil.c
index b98bb51fe8..25ef39f47d 100644
--- a/grub-core/video/fb/fbutil.c
+++ b/grub-core/video/fb/fbutil.c
@@ -67,7 +67,7 @@ get_pixel (struct grub_video_fbblit_info *source,
case 1:
if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED)
{
- int bit_index = y * source->mode_info->width + x;
+ grub_uint64_t bit_index = (grub_uint64_t) y * source->mode_info->width + x;
grub_uint8_t *ptr = source->data + bit_index / 8;
int bit_pos = 7 - bit_index % 8;
color = (*ptr >> bit_pos) & 0x01;
@@ -138,7 +138,7 @@ set_pixel (struct grub_video_fbblit_info *source,
case 1:
if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED)
{
- int bit_index = y * source->mode_info->width + x;
+ grub_uint64_t bit_index = (grub_uint64_t) y * source->mode_info->width + x;
grub_uint8_t *ptr = source->data + bit_index / 8;
int bit_pos = 7 - bit_index % 8;
*ptr = (*ptr & ~(1 << bit_pos)) | ((color & 0x01) << bit_pos);
diff --git a/include/grub/fbutil.h b/include/grub/fbutil.h
index 4205eb917f..78a1ab3b45 100644
--- a/include/grub/fbutil.h
+++ b/include/grub/fbutil.h
@@ -31,14 +31,19 @@ struct grub_video_fbblit_info
grub_uint8_t *data;
};
-/* Don't use for 1-bit bitmaps, addressing needs to be done at the bit level
- and it doesn't make sense, in general, to ask for a pointer
- to a particular pixel's data. */
+/*
+ * Don't use for 1-bit bitmaps, addressing needs to be done at the bit level
+ * and it doesn't make sense, in general, to ask for a pointer
+ * to a particular pixel's data.
+ *
+ * This function assumes that bounds checking has been done in previous phase
+ * and they are opted out in here.
+ */
static inline void *
grub_video_fb_get_video_ptr (struct grub_video_fbblit_info *source,
unsigned int x, unsigned int y)
{
- return source->data + y * source->mode_info->pitch + x * source->mode_info->bytes_per_pixel;
+ return source->data + (grub_addr_t) y * source->mode_info->pitch + (grub_addr_t) x * source->mode_info->bytes_per_pixel;
}
/* Advance pointer by VAL bytes. If there is no unaligned access available,

@ -0,0 +1,90 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zhang Boyang <zhangboyang.id@gmail.com>
Date: Mon, 24 Oct 2022 08:05:35 +0800
Subject: [PATCH] font: Fix an integer underflow in blit_comb()
The expression (ctx.bounds.height - combining_glyphs[i]->height) / 2 may
evaluate to a very big invalid value even if both ctx.bounds.height and
combining_glyphs[i]->height are small integers. For example, if
ctx.bounds.height is 10 and combining_glyphs[i]->height is 12, this
expression evaluates to 2147483647 (expected -1). This is because
coordinates are allowed to be negative but ctx.bounds.height is an
unsigned int. So, the subtraction operates on unsigned ints and
underflows to a very big value. The division makes things even worse.
The quotient is still an invalid value even if converted back to int.
This patch fixes the problem by casting ctx.bounds.height to int. As
a result the subtraction will operate on int and grub_uint16_t which
will be promoted to an int. So, the underflow will no longer happen. Other
uses of ctx.bounds.height (and ctx.bounds.width) are also casted to int,
to ensure coordinates are always calculated on signed integers.
Fixes: CVE-2022-3775
Reported-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
(cherry picked from commit 6d2668dea3774ed74c4cd1eadd146f1b846bc3d4)
(cherry picked from commit 05e532fb707bbf79aa4e1efbde4d208d7da89d6b)
---
grub-core/font/font.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/grub-core/font/font.c b/grub-core/font/font.c
index 193dfec045..12a5f0d08c 100644
--- a/grub-core/font/font.c
+++ b/grub-core/font/font.c
@@ -1203,12 +1203,12 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
ctx.bounds.height = main_glyph->height;
above_rightx = main_glyph->offset_x + main_glyph->width;
- above_righty = ctx.bounds.y + ctx.bounds.height;
+ above_righty = ctx.bounds.y + (int) ctx.bounds.height;
above_leftx = main_glyph->offset_x;
- above_lefty = ctx.bounds.y + ctx.bounds.height;
+ above_lefty = ctx.bounds.y + (int) ctx.bounds.height;
- below_rightx = ctx.bounds.x + ctx.bounds.width;
+ below_rightx = ctx.bounds.x + (int) ctx.bounds.width;
below_righty = ctx.bounds.y;
comb = grub_unicode_get_comb (glyph_id);
@@ -1221,7 +1221,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
if (!combining_glyphs[i])
continue;
- targetx = (ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x;
+ targetx = ((int) ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x;
/* CGJ is to avoid diacritics reordering. */
if (comb[i].code
== GRUB_UNICODE_COMBINING_GRAPHEME_JOINER)
@@ -1231,8 +1231,8 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
case GRUB_UNICODE_COMB_OVERLAY:
do_blit (combining_glyphs[i],
targetx,
- (ctx.bounds.height - combining_glyphs[i]->height) / 2
- - (ctx.bounds.height + ctx.bounds.y), &ctx);
+ ((int) ctx.bounds.height - combining_glyphs[i]->height) / 2
+ - ((int) ctx.bounds.height + ctx.bounds.y), &ctx);
if (min_devwidth < combining_glyphs[i]->width)
min_devwidth = combining_glyphs[i]->width;
break;
@@ -1305,7 +1305,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
/* Fallthrough. */
case GRUB_UNICODE_STACK_ATTACHED_ABOVE:
do_blit (combining_glyphs[i], targetx,
- -(ctx.bounds.height + ctx.bounds.y + space
+ -((int) ctx.bounds.height + ctx.bounds.y + space
+ combining_glyphs[i]->height), &ctx);
if (min_devwidth < combining_glyphs[i]->width)
min_devwidth = combining_glyphs[i]->width;
@@ -1313,7 +1313,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
case GRUB_UNICODE_COMB_HEBREW_DAGESH:
do_blit (combining_glyphs[i], targetx,
- -(ctx.bounds.height / 2 + ctx.bounds.y
+ -((int) ctx.bounds.height / 2 + ctx.bounds.y
+ combining_glyphs[i]->height / 2), &ctx);
if (min_devwidth < combining_glyphs[i]->width)
min_devwidth = combining_glyphs[i]->width;

@ -0,0 +1,74 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zhang Boyang <zhangboyang.id@gmail.com>
Date: Mon, 24 Oct 2022 07:15:41 +0800
Subject: [PATCH] font: Harden grub_font_blit_glyph() and
grub_font_blit_glyph_mirror()
As a mitigation and hardening measure add sanity checks to
grub_font_blit_glyph() and grub_font_blit_glyph_mirror(). This patch
makes these two functions do nothing if target blitting area isn't fully
contained in target bitmap. Therefore, if complex calculations in caller
overflows and malicious coordinates are given, we are still safe because
any coordinates which result in out-of-bound-write are rejected. However,
this patch only checks for invalid coordinates, and doesn't provide any
protection against invalid source glyph or destination glyph, e.g.
mismatch between glyph size and buffer size.
This hardening measure is designed to mitigate possible overflows in
blit_comb(). If overflow occurs, it may return invalid bounding box
during dry run and call grub_font_blit_glyph() with malicious
coordinates during actual blitting. However, we are still safe because
the scratch glyph itself is valid, although its size makes no sense, and
any invalid coordinates are rejected.
It would be better to call grub_fatal() if illegal parameter is detected.
However, doing this may end up in a dangerous recursion because grub_fatal()
would print messages to the screen and we are in the progress of drawing
characters on the screen.
Reported-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
(cherry picked from commit fcd7aa0c278f7cf3fb9f93f1a3966e1792339eb6)
(cherry picked from commit 1d37ec63a1c76a14fdf70f548eada92667b42ddb)
---
grub-core/font/font.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/grub-core/font/font.c b/grub-core/font/font.c
index 12a5f0d08c..29fbb94294 100644
--- a/grub-core/font/font.c
+++ b/grub-core/font/font.c
@@ -1069,8 +1069,15 @@ static void
grub_font_blit_glyph (struct grub_font_glyph *target,
struct grub_font_glyph *src, unsigned dx, unsigned dy)
{
+ grub_uint16_t max_x, max_y;
unsigned src_bit, tgt_bit, src_byte, tgt_byte;
unsigned i, j;
+
+ /* Harden against out-of-bound writes. */
+ if ((grub_add (dx, src->width, &max_x) || max_x > target->width) ||
+ (grub_add (dy, src->height, &max_y) || max_y > target->height))
+ return;
+
for (i = 0; i < src->height; i++)
{
src_bit = (src->width * i) % 8;
@@ -1102,9 +1109,16 @@ grub_font_blit_glyph_mirror (struct grub_font_glyph *target,
struct grub_font_glyph *src,
unsigned dx, unsigned dy)
{
+ grub_uint16_t max_x, max_y;
unsigned tgt_bit, src_byte, tgt_byte;
signed src_bit;
unsigned i, j;
+
+ /* Harden against out-of-bound writes. */
+ if ((grub_add (dx, src->width, &max_x) || max_x > target->width) ||
+ (grub_add (dy, src->height, &max_y) || max_y > target->height))
+ return;
+
for (i = 0; i < src->height; i++)
{
src_bit = (src->width * i + src->width - 1) % 8;

@ -0,0 +1,35 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zhang Boyang <zhangboyang.id@gmail.com>
Date: Fri, 28 Oct 2022 17:29:16 +0800
Subject: [PATCH] font: Assign null_font to glyphs in ascii_font_glyph[]
The calculations in blit_comb() need information from glyph's font, e.g.
grub_font_get_xheight(main_glyph->font). However, main_glyph->font is
NULL if main_glyph comes from ascii_font_glyph[]. Therefore
grub_font_get_*() crashes because of NULL pointer.
There is already a solution, the null_font. So, assign it to those glyphs
in ascii_font_glyph[].
Reported-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
(cherry picked from commit dd539d695482069d28b40f2d3821f710cdcf6ee6)
(cherry picked from commit 87526376857eaceae474c9797e3cee5b50597332)
---
grub-core/font/font.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/font/font.c b/grub-core/font/font.c
index 29fbb94294..e6616e610c 100644
--- a/grub-core/font/font.c
+++ b/grub-core/font/font.c
@@ -137,7 +137,7 @@ ascii_glyph_lookup (grub_uint32_t code)
ascii_font_glyph[current]->offset_x = 0;
ascii_font_glyph[current]->offset_y = -2;
ascii_font_glyph[current]->device_width = 8;
- ascii_font_glyph[current]->font = NULL;
+ ascii_font_glyph[current]->font = &null_font;
grub_memcpy (ascii_font_glyph[current]->bitmap,
&ascii_bitmaps[current * ASCII_BITMAP_SIZE],

@ -0,0 +1,54 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zhang Boyang <zhangboyang.id@gmail.com>
Date: Fri, 28 Oct 2022 21:31:39 +0800
Subject: [PATCH] normal/charset: Fix an integer overflow in
grub_unicode_aglomerate_comb()
The out->ncomb is a bit-field of 8 bits. So, the max possible value is 255.
However, code in grub_unicode_aglomerate_comb() doesn't check for an
overflow when incrementing out->ncomb. If out->ncomb is already 255,
after incrementing it will get 0 instead of 256, and cause illegal
memory access in subsequent processing.
This patch introduces GRUB_UNICODE_NCOMB_MAX to represent the max
acceptable value of ncomb. The code now checks for this limit and
ignores additional combining characters when limit is reached.
Reported-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
(cherry picked from commit da90d62316a3b105d2fbd7334d6521936bd6dcf6)
(cherry picked from commit 26fafec86000b5322837722a115279ef03922ca6)
---
grub-core/normal/charset.c | 3 +++
include/grub/unicode.h | 2 ++
2 files changed, 5 insertions(+)
diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c
index 7a5a7c153c..c243ca6dae 100644
--- a/grub-core/normal/charset.c
+++ b/grub-core/normal/charset.c
@@ -472,6 +472,9 @@ grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen,
if (!haveout)
continue;
+ if (out->ncomb == GRUB_UNICODE_NCOMB_MAX)
+ continue;
+
if (comb_type == GRUB_UNICODE_COMB_MC
|| comb_type == GRUB_UNICODE_COMB_ME
|| comb_type == GRUB_UNICODE_COMB_MN)
diff --git a/include/grub/unicode.h b/include/grub/unicode.h
index 4de986a857..c4f6fca043 100644
--- a/include/grub/unicode.h
+++ b/include/grub/unicode.h
@@ -147,7 +147,9 @@ struct grub_unicode_glyph
grub_uint8_t bidi_level:6; /* minimum: 6 */
enum grub_bidi_type bidi_type:5; /* minimum: :5 */
+#define GRUB_UNICODE_NCOMB_MAX ((1 << 8) - 1)
unsigned ncomb:8;
+
/* Hint by unicode subsystem how wide this character usually is.
Real width is determined by font. Set only in UTF-8 stream. */
int estimated_width:8;

Binary file not shown.

Binary file not shown.

@ -287,3 +287,20 @@ Patch0286: 0286-ieee1275-implement-vec5-for-cas-negotiation.patch
Patch0287: 0287-squish-don-t-dup-rhgb-quiet-check-mtimes.patch Patch0287: 0287-squish-don-t-dup-rhgb-quiet-check-mtimes.patch
Patch0288: 0288-squish-give-up-on-rhgb-quiet.patch Patch0288: 0288-squish-give-up-on-rhgb-quiet.patch
Patch0289: 0289-squish-BLS-only-write-etc-kernel-cmdline-if-writable.patch Patch0289: 0289-squish-BLS-only-write-etc-kernel-cmdline-if-writable.patch
Patch0290: 0290-x86-efi-Fix-an-incorrect-array-size-in-kernel-alloca.patch
Patch0291: 0291-commands-efi-tpm-Refine-the-status-of-log-event.patch
Patch0292: 0292-commands-efi-tpm-Use-grub_strcpy-instead-of-grub_mem.patch
Patch0293: 0293-efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch
Patch0294: 0294-font-Reject-glyphs-exceeds-font-max_glyph_width-or-f.patch
Patch0295: 0295-font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch
Patch0296: 0296-font-Fix-several-integer-overflows-in-grub_font_cons.patch
Patch0297: 0297-font-Remove-grub_font_dup_glyph.patch
Patch0298: 0298-font-Fix-integer-overflow-in-ensure_comb_space.patch
Patch0299: 0299-font-Fix-integer-overflow-in-BMP-index.patch
Patch0300: 0300-font-Fix-integer-underflow-in-binary-search-of-char-.patch
Patch0301: 0301-kern-efi-sb-Enforce-verification-of-font-files.patch
Patch0302: 0302-fbutil-Fix-integer-overflow.patch
Patch0303: 0303-font-Fix-an-integer-underflow-in-blit_comb.patch
Patch0304: 0304-font-Harden-grub_font_blit_glyph-and-grub_font_blit_.patch
Patch0305: 0305-font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch
Patch0306: 0306-normal-charset-Fix-an-integer-overflow-in-grub_unico.patch

@ -1,3 +1,3 @@
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
grub,2,Free Software Foundation,grub,@@VERSION@@,https//www.gnu.org/software/grub/ grub,3,Free Software Foundation,grub,@@VERSION@@,https//www.gnu.org/software/grub/
grub.rh,2,Red Hat,grub2,@@VERSION_RELEASE@@,mailto:secalert@redhat.com grub.rh,2,Red Hat,grub2,@@VERSION_RELEASE@@,mailto:secalert@redhat.com

@ -14,7 +14,7 @@
Name: grub2 Name: grub2
Epoch: 1 Epoch: 1
Version: 2.06 Version: 2.06
Release: 46%{?dist} Release: 46%{?dist}.3
Summary: Bootloader with support for Linux, Multiboot and more Summary: Bootloader with support for Linux, Multiboot and more
License: GPLv3+ License: GPLv3+
URL: http://www.gnu.org/software/grub/ URL: http://www.gnu.org/software/grub/
@ -32,14 +32,21 @@ Source9: strtoull_test.c
Source10: 20-grub.install Source10: 20-grub.install
Source11: grub.patches Source11: grub.patches
Source12: sbat.csv.in Source12: sbat.csv.in
Source13: 701-ca.cer
Source14: 701-cer.cer
%include %{SOURCE1} %include %{SOURCE1}
%ifarch x86_64 aarch64 ppc64le %ifarch x86_64 aarch64
%define sb_ca %{_datadir}/pki/sb-certs/secureboot-ca-%{_arch}.cer %define sb_ca %{_datadir}/pki/sb-certs/secureboot-ca-%{_arch}.cer
%define sb_cer %{_datadir}/pki/sb-certs/secureboot-grub2-%{_arch}.cer %define sb_cer %{_datadir}/pki/sb-certs/secureboot-grub2-%{_arch}.cer
%endif %endif
%ifarch ppc64le
%define sb_ca %{SOURCE13}
%define sb_cer %{SOURCE14}
%endif
%if 0%{?centos} %if 0%{?centos}
%ifarch x86_64 aarch64 ppc64le %ifarch x86_64 aarch64 ppc64le
@ -532,6 +539,14 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg
%endif %endif
%changelog %changelog
* Fri Nov 11 2022 Robbie Harwood <rharwood@redhat.com> - 2.06-46.el9_1.3
- Give up on redhat-sb-certs
- Resolves: CVE-2022-2601
* Thu Nov 03 2022 Robbie Harwood <rharwood@redhat.com> - 2.06-46.el9_1.2
- CVE update (actually 2.06-49)
- Resolves: CVE-2022-2601
* Thu Aug 25 2022 Robbie Harwood <rharwood@redhat.com> - 2.06-46 * Thu Aug 25 2022 Robbie Harwood <rharwood@redhat.com> - 2.06-46
- Sync /etc/kernel/cmdline generation with 2.06-52.fc38 - Sync /etc/kernel/cmdline generation with 2.06-52.fc38
- Resolves: #1969362 - Resolves: #1969362

Loading…
Cancel
Save