0016-font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. From 1aefeca0f6304a20c1a3711cb9e89c5fdb901b6b Mon Sep 17 00:00:00 2001
  2. From: Zhang Boyang <zhangboyang.id@gmail.com>
  3. Date: Fri, 5 Aug 2022 00:51:20 +0800
  4. Subject: [PATCH] font: Fix size overflow in grub_font_get_glyph_internal()
  5. The length of memory allocation and file read may overflow. This patch
  6. fixes the problem by using safemath macros.
  7. There is a lot of code repetition like "(x * y + 7) / 8". It is unsafe
  8. if overflow happens. This patch introduces grub_video_bitmap_calc_1bpp_bufsz().
  9. It is safe replacement for such code. It has safemath-like prototype.
  10. This patch also introduces grub_cast(value, pointer), it casts value to
  11. typeof(*pointer) then store the value to *pointer. It returns true when
  12. overflow occurs or false if there is no overflow. The semantics of arguments
  13. and return value are designed to be consistent with other safemath macros.
  14. Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
  15. Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
  16. Upstream: 9c76ec09ae08155df27cd237eaea150b4f02f532
  17. [Thomas: needed to backport 768e1ef2fc159f6e14e7246e4be09363708ac39e,
  18. which fixes CVE-2022-2601]
  19. Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
  20. ---
  21. grub-core/font/font.c | 17 +++++++++++++----
  22. include/grub/bitmap.h | 18 ++++++++++++++++++
  23. include/grub/safemath.h | 2 ++
  24. 3 files changed, 33 insertions(+), 4 deletions(-)
  25. diff --git a/grub-core/font/font.c b/grub-core/font/font.c
  26. index d09bb38d8..876b5b695 100644
  27. --- a/grub-core/font/font.c
  28. +++ b/grub-core/font/font.c
  29. @@ -739,7 +739,8 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code)
  30. grub_int16_t xoff;
  31. grub_int16_t yoff;
  32. grub_int16_t dwidth;
  33. - int len;
  34. + grub_ssize_t len;
  35. + grub_size_t sz;
  36. if (index_entry->glyph)
  37. /* Return cached glyph. */
  38. @@ -766,9 +767,17 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code)
  39. return 0;
  40. }
  41. - len = (width * height + 7) / 8;
  42. - glyph = grub_malloc (sizeof (struct grub_font_glyph) + len);
  43. - if (!glyph)
  44. + /* Calculate real struct size of current glyph. */
  45. + if (grub_video_bitmap_calc_1bpp_bufsz (width, height, &len) ||
  46. + grub_add (sizeof (struct grub_font_glyph), len, &sz))
  47. + {
  48. + remove_font (font);
  49. + return 0;
  50. + }
  51. +
  52. + /* Allocate and initialize the glyph struct. */
  53. + glyph = grub_malloc (sz);
  54. + if (glyph == NULL)
  55. {
  56. remove_font (font);
  57. return 0;
  58. diff --git a/include/grub/bitmap.h b/include/grub/bitmap.h
  59. index 5728f8ca3..0d9603f61 100644
  60. --- a/include/grub/bitmap.h
  61. +++ b/include/grub/bitmap.h
  62. @@ -23,6 +23,7 @@
  63. #include <grub/symbol.h>
  64. #include <grub/types.h>
  65. #include <grub/video.h>
  66. +#include <grub/safemath.h>
  67. struct grub_video_bitmap
  68. {
  69. @@ -79,6 +80,23 @@ grub_video_bitmap_get_height (struct grub_video_bitmap *bitmap)
  70. return bitmap->mode_info.height;
  71. }
  72. +/*
  73. + * Calculate and store the size of data buffer of 1bit bitmap in result.
  74. + * Equivalent to "*result = (width * height + 7) / 8" if no overflow occurs.
  75. + * Return true when overflow occurs or false if there is no overflow.
  76. + * This function is intentionally implemented as a macro instead of
  77. + * an inline function. Although a bit awkward, it preserves data types for
  78. + * safemath macros and reduces macro side effects as much as possible.
  79. + *
  80. + * XXX: Will report false overflow if width * height > UINT64_MAX.
  81. + */
  82. +#define grub_video_bitmap_calc_1bpp_bufsz(width, height, result) \
  83. +({ \
  84. + grub_uint64_t _bitmap_pixels; \
  85. + grub_mul ((width), (height), &_bitmap_pixels) ? 1 : \
  86. + grub_cast (_bitmap_pixels / GRUB_CHAR_BIT + !!(_bitmap_pixels % GRUB_CHAR_BIT), (result)); \
  87. +})
  88. +
  89. void EXPORT_FUNC (grub_video_bitmap_get_mode_info) (struct grub_video_bitmap *bitmap,
  90. struct grub_video_mode_info *mode_info);
  91. diff --git a/include/grub/safemath.h b/include/grub/safemath.h
  92. index c17b89bba..bb0f826de 100644
  93. --- a/include/grub/safemath.h
  94. +++ b/include/grub/safemath.h
  95. @@ -30,6 +30,8 @@
  96. #define grub_sub(a, b, res) __builtin_sub_overflow(a, b, res)
  97. #define grub_mul(a, b, res) __builtin_mul_overflow(a, b, res)
  98. +#define grub_cast(a, res) grub_add ((a), 0, (res))
  99. +
  100. #else
  101. #error gcc 5.1 or newer or clang 3.8 or newer is required
  102. #endif
  103. --
  104. 2.41.0