nalika / rpms / grub2

Forked from rpms/grub2 2 years ago
Clone

Blame SOURCES/0287-fbutil-Fix-integer-overflow.patch

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