[PATCH OLK-5.10 0/2] CVE-2024-26798

Shigeru Yoshida (1): fbdev: fbcon: Properly revert changes when vc_resize() failed Tetsuo Handa (1): fbdev: fbcon: release buffer when fbcon_do_set_font() failed drivers/video/fbdev/core/fbcon.c | 60 ++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 18 deletions(-) -- 2.25.1

From: Shigeru Yoshida <syoshida@redhat.com> mainline inclusion from mainline-v6.0-rc3 commit a5a923038d70d2d4a86cb4e3f32625a5ee6e7e24 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9E448 CVE: CVE-2024-26798 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... ------------------------------------------------- fbcon_do_set_font() calls vc_resize() when font size is changed. However, if if vc_resize() failed, current implementation doesn't revert changes for font size, and this causes inconsistent state. syzbot reported unable to handle page fault due to this issue [1]. syzbot's repro uses fault injection which cause failure for memory allocation, so vc_resize() failed. This patch fixes this issue by properly revert changes for font related date when vc_resize() failed. Link: https://syzkaller.appspot.com/bug?id=3443d3a1fa6d964dd7310a0cb1696d165a3e07c... [1] Reported-by: syzbot+a168dbeaaa7778273c1b@syzkaller.appspotmail.com Signed-off-by: Shigeru Yoshida <syoshida@redhat.com> Signed-off-by: Helge Deller <deller@gmx.de> CC: stable@vger.kernel.org # 5.15+ Conflicts: drivers/video/fbdev/core/fbcon.c [Fix context conflicts.] Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/video/fbdev/core/fbcon.c | 59 ++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 6d58c8a5cb44..f0eacf1968d8 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -26,7 +26,7 @@ * * Hardware cursor support added by Emmanuel Marty (core@ggi-project.org) * Smart redraw scrolling, arbitrary font width support, 512char font support - * and software scrollback added by + * and software scrollback added by * Jakub Jelinek (jj@ultra.linux.cz) * * Random hacking by Martin Mares <mj@ucw.cz> @@ -125,7 +125,7 @@ static int logo_shown = FBCON_LOGO_CANSHOW; /* console mappings */ static unsigned int first_fb_vc; static unsigned int last_fb_vc = MAX_NR_CONSOLES - 1; -static int fbcon_is_default = 1; +static int fbcon_is_default = 1; static int primary_device = -1; static int fbcon_has_console_bind; @@ -447,12 +447,12 @@ static int __init fb_console_setup(char *this_opt) strlcpy(fontname, options + 5, sizeof(fontname)); continue; } - + if (!strncmp(options, "scrollback:", 11)) { pr_warn("Ignoring scrollback size option\n"); continue; } - + if (!strncmp(options, "map:", 4)) { options += 4; if (*options) { @@ -478,7 +478,7 @@ static int __init fb_console_setup(char *this_opt) last_fb_vc = simple_strtoul(options, &options, 10) - 1; if (last_fb_vc < first_fb_vc || last_fb_vc >= MAX_NR_CONSOLES) last_fb_vc = MAX_NR_CONSOLES - 1; - fbcon_is_default = 0; + fbcon_is_default = 0; continue; } @@ -966,7 +966,7 @@ static const char *fbcon_startup(void) info = registered_fb[info_idx]; if (!info) return NULL; - + owner = info->fbops->owner; if (!try_module_get(owner)) return NULL; @@ -1429,7 +1429,7 @@ static __inline__ void ywrap_up(struct vc_data *vc, int count) struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; struct fbcon_ops *ops = info->fbcon_par; struct fbcon_display *p = &fb_display[vc->vc_num]; - + p->yscroll += count; if (p->yscroll >= p->vrows) /* Deal with wrap */ p->yscroll -= p->vrows; @@ -1448,7 +1448,7 @@ static __inline__ void ywrap_down(struct vc_data *vc, int count) struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; struct fbcon_ops *ops = info->fbcon_par; struct fbcon_display *p = &fb_display[vc->vc_num]; - + p->yscroll -= count; if (p->yscroll < 0) /* Deal with wrap */ p->yscroll += p->vrows; @@ -1515,7 +1515,7 @@ static __inline__ void ypan_down(struct vc_data *vc, int count) struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; struct fbcon_display *p = &fb_display[vc->vc_num]; struct fbcon_ops *ops = info->fbcon_par; - + p->yscroll -= count; if (p->yscroll < 0) { ops->bmove(vc, info, 0, 0, p->vrows - vc->vc_rows, @@ -1898,7 +1898,7 @@ static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx, { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; struct fbcon_display *p = &fb_display[vc->vc_num]; - + if (fbcon_is_inactive(vc, info)) return; @@ -2023,7 +2023,7 @@ static void updatescrollmode(struct fbcon_display *p, #define PITCH(w) (((w) + 7) >> 3) #define CALC_FONTSZ(h, p, c) ((h) * (p) * (c)) /* size = height * pitch * charcount */ -static int fbcon_resize(struct vc_data *vc, unsigned int width, +static int fbcon_resize(struct vc_data *vc, unsigned int width, unsigned int height, unsigned int user) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; @@ -2201,7 +2201,7 @@ static int fbcon_switch(struct vc_data *vc) ops->update_start(info); } - fbcon_set_palette(vc, color_table); + fbcon_set_palette(vc, color_table); fbcon_clear_margins(vc, 0); if (logo_shown == FBCON_LOGO_DRAW) { @@ -2371,7 +2371,7 @@ static void set_vc_hi_font(struct vc_data *vc, bool set) vc->vc_complement_mask >>= 1; vc->vc_s_complement_mask >>= 1; } - + /* ++Edmund: reorder the attribute bits */ if (vc->vc_can_do_color) { unsigned short *cp = @@ -2394,7 +2394,7 @@ static void set_vc_hi_font(struct vc_data *vc, bool set) vc->vc_complement_mask <<= 1; vc->vc_s_complement_mask <<= 1; } - + /* ++Edmund: reorder the attribute bits */ { unsigned short *cp = @@ -2429,7 +2429,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; struct fbcon_ops *ops = info->fbcon_par; struct fbcon_display *p = &fb_display[vc->vc_num]; - int resize; + int resize, ret, old_userfont, old_width, old_height, old_charcount; int cnt; char *old_data = NULL; @@ -2441,8 +2441,14 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, else cnt = 256; vc->vc_font.data = (void *)(p->fontdata = data); + old_userfont = p->userfont; if ((p->userfont = userfont)) REFCOUNT(data)++; + + old_width = vc->vc_font.width; + old_height = vc->vc_font.height; + old_charcount = vc->vc_font.charcount; + vc->vc_font.width = w; vc->vc_font.height = h; if (vc->vc_hi_font_mask && cnt == 256) @@ -2457,7 +2463,9 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); cols /= w; rows /= h; - vc_resize(vc, cols, rows); + ret = vc_resize(vc, cols, rows); + if (ret) + goto err_out; } else if (con_is_visible(vc) && vc->vc_mode == KD_TEXT) { fbcon_clear_margins(vc, 0); @@ -2467,6 +2475,21 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, if (old_data && (--REFCOUNT(old_data) == 0)) kfree(old_data - FONT_EXTRA_WORDS * sizeof(int)); return 0; + +err_out: + p->fontdata = old_data; + vc->vc_font.data = (void *)old_data; + + if (userfont) { + p->userfont = old_userfont; + REFCOUNT(data)--; + } + + vc->vc_font.width = old_width; + vc->vc_font.height = old_height; + vc->vc_font.charcount = old_charcount; + + return ret; } static int fbcon_copy_font(struct vc_data *vc, int con) @@ -2548,7 +2571,7 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, /* Check if the same font is on some other console already */ for (i = first_fb_vc; i <= last_fb_vc; i++) { struct vc_data *tmp = vc_cons[i].d; - + if (fb_display[i].userfont && fb_display[i].fontdata && FNTSUM(fb_display[i].fontdata) == csum && @@ -3485,5 +3508,5 @@ void __exit fb_console_exit(void) fbcon_exit(); do_unregister_con_driver(&fb_con); console_unlock(); -} +} #endif -- 2.25.1

From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> mainline inclusion from mainline-v6.8-rc7 commit 00d6a284fcf3fad1b7e1b5bc3cd87cbfb60ce03f category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9E448 CVE: CVE-2024-26798 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... ------------------------------------------------- syzbot is reporting memory leak at fbcon_do_set_font() [1], for commit a5a923038d70 ("fbdev: fbcon: Properly revert changes when vc_resize() failed") missed that the buffer might be newly allocated by fbcon_set_font(). Link: https://syzkaller.appspot.com/bug?extid=25bdb7b1703639abd498 [1] Reported-by: syzbot <syzbot+25bdb7b1703639abd498@syzkaller.appspotmail.com> Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Tested-by: syzbot <syzbot+25bdb7b1703639abd498@syzkaller.appspotmail.com> Fixes: a5a923038d70 ("fbdev: fbcon: Properly revert changes when vc_resize() failed") CC: stable@vger.kernel.org # 5.15+ Signed-off-by: Helge Deller <deller@gmx.de> Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/video/fbdev/core/fbcon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index f0eacf1968d8..8cd853ed6b55 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -2482,7 +2482,8 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, if (userfont) { p->userfont = old_userfont; - REFCOUNT(data)--; + if (--REFCOUNT(data) == 0) + kfree(data - FONT_EXTRA_WORDS * sizeof(int)); } vc->vc_font.width = old_width; -- 2.25.1

反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/16815 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/ELJ... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/16815 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/ELJ...
participants (2)
-
patchwork bot
-
Zeng Heng