66 lines
2.8 KiB
Diff
66 lines
2.8 KiB
Diff
From 54c7f478f1a9d58f5609a48d461c7d495bb8301a Mon Sep 17 00:00:00 2001
|
|
From: Murad Masimov <m.masimov@mt-integration.ru>
|
|
Date: Mon, 28 Apr 2025 18:34:07 +0300
|
|
Subject: fbdev: Fix fb_set_var to prevent null-ptr-deref in
|
|
fb_videomode_to_var
|
|
|
|
If fb_add_videomode() in fb_set_var() fails to allocate memory for
|
|
fb_videomode, later it may lead to a null-ptr dereference in
|
|
fb_videomode_to_var(), as the fb_info is registered while not having the
|
|
mode in modelist that is expected to be there, i.e. the one that is
|
|
described in fb_info->var.
|
|
|
|
================================================================
|
|
general protection fault, probably for non-canonical address 0xdffffc0000000001: 0000 [#1] PREEMPT SMP KASAN NOPTI
|
|
KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f]
|
|
CPU: 1 PID: 30371 Comm: syz-executor.1 Not tainted 5.10.226-syzkaller #0
|
|
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 04/01/2014
|
|
RIP: 0010:fb_videomode_to_var+0x24/0x610 drivers/video/fbdev/core/modedb.c:901
|
|
Call Trace:
|
|
display_to_var+0x3a/0x7c0 drivers/video/fbdev/core/fbcon.c:929
|
|
fbcon_resize+0x3e2/0x8f0 drivers/video/fbdev/core/fbcon.c:2071
|
|
resize_screen drivers/tty/vt/vt.c:1176 [inline]
|
|
vc_do_resize+0x53a/0x1170 drivers/tty/vt/vt.c:1263
|
|
fbcon_modechanged+0x3ac/0x6e0 drivers/video/fbdev/core/fbcon.c:2720
|
|
fbcon_update_vcs+0x43/0x60 drivers/video/fbdev/core/fbcon.c:2776
|
|
do_fb_ioctl+0x6d2/0x740 drivers/video/fbdev/core/fbmem.c:1128
|
|
fb_ioctl+0xe7/0x150 drivers/video/fbdev/core/fbmem.c:1203
|
|
vfs_ioctl fs/ioctl.c:48 [inline]
|
|
__do_sys_ioctl fs/ioctl.c:753 [inline]
|
|
__se_sys_ioctl fs/ioctl.c:739 [inline]
|
|
__x64_sys_ioctl+0x19a/0x210 fs/ioctl.c:739
|
|
do_syscall_64+0x33/0x40 arch/x86/entry/common.c:46
|
|
entry_SYSCALL_64_after_hwframe+0x67/0xd1
|
|
================================================================
|
|
|
|
The reason is that fb_info->var is being modified in fb_set_var(), and
|
|
then fb_videomode_to_var() is called. If it fails to add the mode to
|
|
fb_info->modelist, fb_set_var() returns error, but does not restore the
|
|
old value of fb_info->var. Restore fb_info->var on failure the same way
|
|
it is done earlier in the function.
|
|
|
|
Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
|
|
|
|
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
|
|
Cc: stable@vger.kernel.org
|
|
Signed-off-by: Murad Masimov <m.masimov@mt-integration.ru>
|
|
Signed-off-by: Helge Deller <deller@gmx.de>
|
|
---
|
|
drivers/video/fbdev/core/fbmem.c | 4 +++-
|
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
|
|
|
--- a/drivers/video/fbdev/core/fbmem.c
|
|
+++ b/drivers/video/fbdev/core/fbmem.c
|
|
@@ -328,8 +328,10 @@ fb_set_var(struct fb_info *info, struct
|
|
!list_empty(&info->modelist))
|
|
ret = fb_add_videomode(&mode, &info->modelist);
|
|
|
|
- if (ret)
|
|
+ if (ret) {
|
|
+ info->var = old_var;
|
|
return ret;
|
|
+ }
|
|
|
|
event.info = info;
|
|
event.data = &mode;
|