nalika / rpms / grub2

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