| From af0db3c1f898144846d4c172531a199bb3ca375d Mon Sep 17 00:00:00 2001 |
| From: Sravan Kumar Gundu <sravankumarlpu@gmail.com> |
| Date: Thu, 31 Jul 2025 15:36:18 -0500 |
| Subject: fbdev: Fix vmalloc out-of-bounds write in fast_imageblit |
| |
| From: Sravan Kumar Gundu <sravankumarlpu@gmail.com> |
| |
| commit af0db3c1f898144846d4c172531a199bb3ca375d upstream. |
| |
| This issue triggers when a userspace program does an ioctl |
| FBIOPUT_CON2FBMAP by passing console number and frame buffer number. |
| Ideally this maps console to frame buffer and updates the screen if |
| console is visible. |
| |
| As part of mapping it has to do resize of console according to frame |
| buffer info. if this resize fails and returns from vc_do_resize() and |
| continues further. At this point console and new frame buffer are mapped |
| and sets display vars. Despite failure still it continue to proceed |
| updating the screen at later stages where vc_data is related to previous |
| frame buffer and frame buffer info and display vars are mapped to new |
| frame buffer and eventully leading to out-of-bounds write in |
| fast_imageblit(). This bheviour is excepted only when fg_console is |
| equal to requested console which is a visible console and updates screen |
| with invalid struct references in fbcon_putcs(). |
| |
| Reported-and-tested-by: syzbot+c4b7aa0513823e2ea880@syzkaller.appspotmail.com |
| Closes: https://syzkaller.appspot.com/bug?extid=c4b7aa0513823e2ea880 |
| Signed-off-by: Sravan Kumar Gundu <sravankumarlpu@gmail.com> |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Helge Deller <deller@gmx.de> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/video/fbdev/core/fbcon.c | 9 +++++---- |
| 1 file changed, 5 insertions(+), 4 deletions(-) |
| |
| --- a/drivers/video/fbdev/core/fbcon.c |
| +++ b/drivers/video/fbdev/core/fbcon.c |
| @@ -808,7 +808,8 @@ static void con2fb_init_display(struct v |
| fg_vc->vc_rows); |
| } |
| |
| - update_screen(vc_cons[fg_console].d); |
| + if (fg_console != unit) |
| + update_screen(vc_cons[fg_console].d); |
| } |
| |
| /** |
| @@ -1353,6 +1354,7 @@ static void fbcon_set_disp(struct fb_inf |
| struct vc_data *svc; |
| struct fbcon_ops *ops = info->fbcon_par; |
| int rows, cols; |
| + unsigned long ret = 0; |
| |
| p = &fb_display[unit]; |
| |
| @@ -1403,11 +1405,10 @@ static void fbcon_set_disp(struct fb_inf |
| rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); |
| cols /= vc->vc_font.width; |
| rows /= vc->vc_font.height; |
| - vc_resize(vc, cols, rows); |
| + ret = vc_resize(vc, cols, rows); |
| |
| - if (con_is_visible(vc)) { |
| + if (con_is_visible(vc) && !ret) |
| update_screen(vc); |
| - } |
| } |
| |
| static __inline__ void ywrap_up(struct vc_data *vc, int count) |