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