Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fbdev: bitblit: bound-check glyph index in bit_putcs*

bit_putcs_aligned()/unaligned() derived the glyph pointer from the
character value masked by 0xff/0x1ff, which may exceed the actual font's
glyph count and read past the end of the built-in font array.
Clamp the index to the actual glyph count before computing the address.

This fixes a global out-of-bounds read reported by syzbot.

Reported-by: syzbot+793cf822d213be1a74f2@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=793cf822d213be1a74f2
Tested-by: syzbot+793cf822d213be1a74f2@syzkaller.appspotmail.com
Signed-off-by: Junjie Cao <junjie.cao@intel.com>
Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
Signed-off-by: Helge Deller <deller@gmx.de>
Cc: stable@vger.kernel.org

authored by

Junjie Cao and committed by
Helge Deller
18c4ef4e 5f566c0a

+12 -4
+12 -4
drivers/video/fbdev/core/bitblit.c
··· 79 79 struct fb_image *image, u8 *buf, u8 *dst) 80 80 { 81 81 u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; 82 + unsigned int charcnt = vc->vc_font.charcount; 82 83 u32 idx = vc->vc_font.width >> 3; 83 84 u8 *src; 84 85 85 86 while (cnt--) { 86 - src = vc->vc_font.data + (scr_readw(s++)& 87 - charmask)*cellsize; 87 + u16 ch = scr_readw(s++) & charmask; 88 + 89 + if (ch >= charcnt) 90 + ch = 0; 91 + src = vc->vc_font.data + (unsigned int)ch * cellsize; 88 92 89 93 if (attr) { 90 94 update_attr(buf, src, attr, vc); ··· 116 112 u8 *dst) 117 113 { 118 114 u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; 115 + unsigned int charcnt = vc->vc_font.charcount; 119 116 u32 shift_low = 0, mod = vc->vc_font.width % 8; 120 117 u32 shift_high = 8; 121 118 u32 idx = vc->vc_font.width >> 3; 122 119 u8 *src; 123 120 124 121 while (cnt--) { 125 - src = vc->vc_font.data + (scr_readw(s++)& 126 - charmask)*cellsize; 122 + u16 ch = scr_readw(s++) & charmask; 123 + 124 + if (ch >= charcnt) 125 + ch = 0; 126 + src = vc->vc_font.data + (unsigned int)ch * cellsize; 127 127 128 128 if (attr) { 129 129 update_attr(buf, src, attr, vc);