Blame SOURCES/0289-font-Harden-grub_font_blit_glyph-and-grub_font_blit_.patch

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