1*4882a593SmuzhiyunFrom fdbe7209152ad6f09a1166f64f162017f2145ba3 Mon Sep 17 00:00:00 2001 2*4882a593SmuzhiyunFrom: Zhang Boyang <zhangboyang.id@gmail.com> 3*4882a593SmuzhiyunDate: Mon, 24 Oct 2022 08:05:35 +0800 4*4882a593SmuzhiyunSubject: [PATCH] font: Fix an integer underflow in blit_comb() 5*4882a593Smuzhiyun 6*4882a593SmuzhiyunThe expression (ctx.bounds.height - combining_glyphs[i]->height) / 2 may 7*4882a593Smuzhiyunevaluate to a very big invalid value even if both ctx.bounds.height and 8*4882a593Smuzhiyuncombining_glyphs[i]->height are small integers. For example, if 9*4882a593Smuzhiyunctx.bounds.height is 10 and combining_glyphs[i]->height is 12, this 10*4882a593Smuzhiyunexpression evaluates to 2147483647 (expected -1). This is because 11*4882a593Smuzhiyuncoordinates are allowed to be negative but ctx.bounds.height is an 12*4882a593Smuzhiyununsigned int. So, the subtraction operates on unsigned ints and 13*4882a593Smuzhiyununderflows to a very big value. The division makes things even worse. 14*4882a593SmuzhiyunThe quotient is still an invalid value even if converted back to int. 15*4882a593Smuzhiyun 16*4882a593SmuzhiyunThis patch fixes the problem by casting ctx.bounds.height to int. As 17*4882a593Smuzhiyuna result the subtraction will operate on int and grub_uint16_t which 18*4882a593Smuzhiyunwill be promoted to an int. So, the underflow will no longer happen. Other 19*4882a593Smuzhiyunuses of ctx.bounds.height (and ctx.bounds.width) are also casted to int, 20*4882a593Smuzhiyunto ensure coordinates are always calculated on signed integers. 21*4882a593Smuzhiyun 22*4882a593SmuzhiyunFixes: CVE-2022-3775 23*4882a593Smuzhiyun 24*4882a593SmuzhiyunReported-by: Daniel Axtens <dja@axtens.net> 25*4882a593SmuzhiyunSigned-off-by: Zhang Boyang <zhangboyang.id@gmail.com> 26*4882a593SmuzhiyunReviewed-by: Daniel Kiper <daniel.kiper@oracle.com> 27*4882a593Smuzhiyun 28*4882a593SmuzhiyunUpstream-Status: Backport from 29*4882a593Smuzhiyun[https://git.savannah.gnu.org/cgit/grub.git/commit/?id=992c06191babc1e109caf40d6a07ec6fdef427af] 30*4882a593SmuzhiyunCVE: CVE-2022-3775 31*4882a593Smuzhiyun 32*4882a593SmuzhiyunSigned-off-by: Xiangyu Chen <xiangyu.chen@windriver.com> 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun--- 35*4882a593Smuzhiyun grub-core/font/font.c | 16 ++++++++-------- 36*4882a593Smuzhiyun 1 file changed, 8 insertions(+), 8 deletions(-) 37*4882a593Smuzhiyun 38*4882a593Smuzhiyundiff --git a/grub-core/font/font.c b/grub-core/font/font.c 39*4882a593Smuzhiyunindex 0ff5525..7b1cbde 100644 40*4882a593Smuzhiyun--- a/grub-core/font/font.c 41*4882a593Smuzhiyun+++ b/grub-core/font/font.c 42*4882a593Smuzhiyun@@ -1206,12 +1206,12 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, 43*4882a593Smuzhiyun ctx.bounds.height = main_glyph->height; 44*4882a593Smuzhiyun 45*4882a593Smuzhiyun above_rightx = main_glyph->offset_x + main_glyph->width; 46*4882a593Smuzhiyun- above_righty = ctx.bounds.y + ctx.bounds.height; 47*4882a593Smuzhiyun+ above_righty = ctx.bounds.y + (int) ctx.bounds.height; 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun above_leftx = main_glyph->offset_x; 50*4882a593Smuzhiyun- above_lefty = ctx.bounds.y + ctx.bounds.height; 51*4882a593Smuzhiyun+ above_lefty = ctx.bounds.y + (int) ctx.bounds.height; 52*4882a593Smuzhiyun 53*4882a593Smuzhiyun- below_rightx = ctx.bounds.x + ctx.bounds.width; 54*4882a593Smuzhiyun+ below_rightx = ctx.bounds.x + (int) ctx.bounds.width; 55*4882a593Smuzhiyun below_righty = ctx.bounds.y; 56*4882a593Smuzhiyun 57*4882a593Smuzhiyun comb = grub_unicode_get_comb (glyph_id); 58*4882a593Smuzhiyun@@ -1224,7 +1224,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, 59*4882a593Smuzhiyun 60*4882a593Smuzhiyun if (!combining_glyphs[i]) 61*4882a593Smuzhiyun continue; 62*4882a593Smuzhiyun- targetx = (ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x; 63*4882a593Smuzhiyun+ targetx = ((int) ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x; 64*4882a593Smuzhiyun /* CGJ is to avoid diacritics reordering. */ 65*4882a593Smuzhiyun if (comb[i].code 66*4882a593Smuzhiyun == GRUB_UNICODE_COMBINING_GRAPHEME_JOINER) 67*4882a593Smuzhiyun@@ -1234,8 +1234,8 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, 68*4882a593Smuzhiyun case GRUB_UNICODE_COMB_OVERLAY: 69*4882a593Smuzhiyun do_blit (combining_glyphs[i], 70*4882a593Smuzhiyun targetx, 71*4882a593Smuzhiyun- (ctx.bounds.height - combining_glyphs[i]->height) / 2 72*4882a593Smuzhiyun- - (ctx.bounds.height + ctx.bounds.y), &ctx); 73*4882a593Smuzhiyun+ ((int) ctx.bounds.height - combining_glyphs[i]->height) / 2 74*4882a593Smuzhiyun+ - ((int) ctx.bounds.height + ctx.bounds.y), &ctx); 75*4882a593Smuzhiyun if (min_devwidth < combining_glyphs[i]->width) 76*4882a593Smuzhiyun min_devwidth = combining_glyphs[i]->width; 77*4882a593Smuzhiyun break; 78*4882a593Smuzhiyun@@ -1308,7 +1308,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, 79*4882a593Smuzhiyun /* Fallthrough. */ 80*4882a593Smuzhiyun case GRUB_UNICODE_STACK_ATTACHED_ABOVE: 81*4882a593Smuzhiyun do_blit (combining_glyphs[i], targetx, 82*4882a593Smuzhiyun- -(ctx.bounds.height + ctx.bounds.y + space 83*4882a593Smuzhiyun+ -((int) ctx.bounds.height + ctx.bounds.y + space 84*4882a593Smuzhiyun + combining_glyphs[i]->height), &ctx); 85*4882a593Smuzhiyun if (min_devwidth < combining_glyphs[i]->width) 86*4882a593Smuzhiyun min_devwidth = combining_glyphs[i]->width; 87*4882a593Smuzhiyun@@ -1316,7 +1316,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, 88*4882a593Smuzhiyun 89*4882a593Smuzhiyun case GRUB_UNICODE_COMB_HEBREW_DAGESH: 90*4882a593Smuzhiyun do_blit (combining_glyphs[i], targetx, 91*4882a593Smuzhiyun- -(ctx.bounds.height / 2 + ctx.bounds.y 92*4882a593Smuzhiyun+ -((int) ctx.bounds.height / 2 + ctx.bounds.y 93*4882a593Smuzhiyun + combining_glyphs[i]->height / 2), &ctx); 94*4882a593Smuzhiyun if (min_devwidth < combining_glyphs[i]->width) 95*4882a593Smuzhiyun min_devwidth = combining_glyphs[i]->width; 96