A simplified reproducer and debug printk() patch shown below reported that vc_font.height is increased to 9 via ioctl(VT_RESIZEX) after it was once decreased from 16 to 2 via ioctl(PIO_FONT). Since vc_resize() with v.v_rows == 0 preserves current vc->vc_rows value, this reproducer is bypassing if (v.v_clin) { int rows = v.v_vlin / v.v_clin; if (v.v_rows != rows) { if (v.v_rows) /* Parameters don't add up */ return -EINVAL; v.v_rows = rows; } } check by setting v.v_vlin == 1 and v.v_clin == 9. If v.v_vcol > 0 and v.v_vcol != vc->vc_cols (though this reproducer is passing v.v_vcol == 0), tty_do_resize() from vc_do_resize() from vc_resize() can make "struct tty_struct"->winsize.ws_ypixel = 1 despite "struct tty_struct"->winsize.vc->vc_rows = vc->vc_rows (which is usually larger than 1). Does such winsize (a row has 1 / vc->vc_rows pixel) make sense? Since I don't know the meaning of "struct vt_consize"->v_clin (which is commented with "/* number of pixel rows per character */" but does it mean font size ?), I don't know why we can assign that value to vcp->vc_font.height via if (v.v_clin) vcp->vc_font.height = v.v_clin; in vt_resizex(). While ioctl(PIO_FONT) needs to pass vc->vc_sw->con_font_set() check in con_font_set(), ioctl(VT_RESIZEX) does not pass it in vt_resizex()... Since this problem does not happen if I remove if (v.v_clin) vcp->vc_font.height = v.v_clin; from vt_resizex(), I guess that some variables are getting confused by change of vc->vc_font.height ... #define VT_RESIZE 0x5609 /* set kernel's idea of screensize */ #define VT_RESIZEX 0x560A /* set kernel's idea of screensize + more */ Hmm, what comes to the "+ more" part? Who is using VT_RESIZEX ? If nobody is using VT_RESIZEX, better to make VT_RESIZEX == VT_RESIZE ? ---------- #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/ioctl.h> #include <linux/kd.h> #include <linux/vt.h> int main(int argc, char *argv[]) { int fd = open("/dev/tty1", 3); static char fontdata[8192] = { 2, 3 }; struct vt_consize v_c = { 0, 0, 1, 9, 0, 0 }; ioctl(fd, PIO_FONT, fontdata); ioctl(fd, VT_RESIZEX, &v_c); return 0; } ---------- ---------- diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index a4e520bdd521..df6b7abd1068 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -769,64 +769,70 @@ static int vt_resizex(struct vc_data *vc, struct vt_consize __user *cs) { struct vt_consize v; int i; + int ret = 0; if (copy_from_user(&v, cs, sizeof(struct vt_consize))) return -EFAULT; - /* FIXME: Should check the copies properly */ - if (!v.v_vlin) - v.v_vlin = vc->vc_scan_lines; + console_lock(); + for (i = 0; i < MAX_NR_CONSOLES; i++) { + struct vc_data *vcp = vc_cons[i].d; - if (v.v_clin) { - int rows = v.v_vlin / v.v_clin; - if (v.v_rows != rows) { - if (v.v_rows) /* Parameters don't add up */ - return -EINVAL; - v.v_rows = rows; + if (!vcp) + continue; + if (v.v_clin) { + int rows = (v.v_vlin ? v.v_vlin : vcp->vc_scan_lines) / v.v_clin; + if (v.v_rows != rows) { + if (v.v_rows) { /* Parameters don't add up */ + ret = -EINVAL; + break; + } + v.v_rows = rows; + } } - } - - if (v.v_vcol && v.v_ccol) { - int cols = v.v_vcol / v.v_ccol; - if (v.v_cols != cols) { - if (v.v_cols) - return -EINVAL; - v.v_cols = cols; + if (v.v_vcol && v.v_ccol) { + int cols = v.v_vcol / v.v_ccol; + if (v.v_cols != cols) { + if (v.v_cols) { + ret = -EINVAL; + break; + } + v.v_cols = cols; + } + } + if (v.v_clin > 32) { + ret = -EINVAL; + break; } } + printk(KERN_INFO "vc=%px v.v_rows=%hu v.v_cols=%hu v.v_vlin=%hu v.v_clin=%u v.v_vcol=%hu v.v_ccol=%hu ret=%d\n", vc, v.v_rows, v.v_cols, v.v_vlin, v.v_clin, v.v_vcol, v.v_ccol, ret); + for (i = 0; !ret && i < MAX_NR_CONSOLES; i++) { + unsigned int save_scan_lines; + unsigned int save_font_height; + struct vc_data *vcp = vc_cons[i].d; - if (v.v_clin > 32) - return -EINVAL; - - for (i = 0; i < MAX_NR_CONSOLES; i++) { - struct vc_data *vcp; - - if (!vc_cons[i].d) + if (!vcp) continue; - console_lock(); - vcp = vc_cons[i].d; - if (vcp) { - int ret; - int save_scan_lines = vcp->vc_scan_lines; - int save_font_height = vcp->vc_font.height; - - if (v.v_vlin) - vcp->vc_scan_lines = v.v_vlin; - if (v.v_clin) - vcp->vc_font.height = v.v_clin; - vcp->vc_resize_user = 1; - ret = vc_resize(vcp, v.v_cols, v.v_rows); - if (ret) { - vcp->vc_scan_lines = save_scan_lines; - vcp->vc_font.height = save_font_height; - console_unlock(); - return ret; - } + save_scan_lines = vcp->vc_scan_lines; + save_font_height = vcp->vc_font.height; + if (v.v_vlin) + vcp->vc_scan_lines = v.v_vlin; + if (v.v_clin) + vcp->vc_font.height = v.v_clin; + printk(KERN_INFO "vcp=%px before: ->vc_rows=%u ->vc_cols=%u ->vc_scan_lines=%u save_scan_lines=%u ->vc_font.height=%u save_font_height=%u\n", + vcp, vcp->vc_rows, vcp->vc_cols, vcp->vc_scan_lines, save_scan_lines, vcp->vc_font.height, save_font_height); + vcp->vc_resize_user = 1; + ret = vc_resize(vcp, v.v_cols, v.v_rows); + printk(KERN_INFO "vcp=%px after: ->vc_rows=%u ->vc_cols=%u ->vc_scan_lines=%u save_scan_lines=%u ->vc_font.height=%u save_font_height=%u ret=%d\n", + vcp, vcp->vc_rows, vcp->vc_cols, vcp->vc_scan_lines, save_scan_lines, vcp->vc_font.height, save_font_height, ret); + if (ret) { + vcp->vc_scan_lines = save_scan_lines; + vcp->vc_font.height = save_font_height; } - console_unlock(); } + console_unlock(); - return 0; + return ret; } /* diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c index 9725ecd1255b..c1b9f43ff657 100644 --- a/drivers/video/fbdev/core/bitblit.c +++ b/drivers/video/fbdev/core/bitblit.c @@ -181,6 +181,8 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info, dst = fb_get_buffer_offset(info, &info->pixmap, size); image.data = dst; + printk(KERN_DEBUG "%s: width=%u cellsize=%u count=%d maxcnt=%u scan_align=%u buf_align=%u image.width=%u image.height=%u pitch=%u\n", + __func__, width, cellsize, count, maxcnt, scan_align, buf_align, image.width, image.height, pitch); if (!mod) bit_putcs_aligned(vc, info, s, attribute, cnt, pitch, width, cellsize, &image, buf, dst); ---------- ---------- [ 297.298013] [ T2823] bit_putcs: width=1 cellsize=16 count=80 maxcnt=512 scan_align=0 buf_align=0 image.width=640 image.height=16 pitch=80 [ 297.312092] [ T2823] bit_putcs: width=1 cellsize=16 count=80 maxcnt=512 scan_align=0 buf_align=0 image.width=640 image.height=16 pitch=80 [ 297.324735] [ T2823] bit_putcs: width=1 cellsize=16 count=80 maxcnt=512 scan_align=0 buf_align=0 image.width=640 image.height=16 pitch=80 [ 297.337634] [ T2823] bit_putcs: width=1 cellsize=16 count=80 maxcnt=512 scan_align=0 buf_align=0 image.width=640 image.height=16 pitch=80 [ 297.350185] [ T2823] bit_putcs: width=1 cellsize=16 count=80 maxcnt=512 scan_align=0 buf_align=0 image.width=640 image.height=16 pitch=80 [ 297.361861] [ T2823] bit_putcs: width=1 cellsize=16 count=80 maxcnt=512 scan_align=0 buf_align=0 image.width=640 image.height=16 pitch=80 [ 297.474116] [ T2823] bit_putcs: width=1 cellsize=16 count=28 maxcnt=512 scan_align=0 buf_align=0 image.width=224 image.height=16 pitch=28 [ 297.481866] [ T2823] bit_putcs: width=1 cellsize=16 count=4 maxcnt=512 scan_align=0 buf_align=0 image.width=32 image.height=16 pitch=4 [ 297.483529] [ T2823] bit_putcs: width=1 cellsize=16 count=1 maxcnt=512 scan_align=0 buf_align=0 image.width=8 image.height=16 pitch=1 [ 297.484792] [ T2823] bit_putcs: width=1 cellsize=16 count=7 maxcnt=512 scan_align=0 buf_align=0 image.width=56 image.height=16 pitch=7 [ 357.373828] [ T2940] bit_putcs: width=1 cellsize=2 count=80 maxcnt=4096 scan_align=0 buf_align=0 image.width=640 image.height=2 pitch=80 [ 357.375232] [ T2940] bit_putcs: width=1 cellsize=2 count=80 maxcnt=4096 scan_align=0 buf_align=0 image.width=640 image.height=2 pitch=80 [ 357.376821] [ T2940] bit_putcs: width=1 cellsize=2 count=80 maxcnt=4096 scan_align=0 buf_align=0 image.width=640 image.height=2 pitch=80 [ 357.378256] [ T2940] bit_putcs: width=1 cellsize=2 count=80 maxcnt=4096 scan_align=0 buf_align=0 image.width=640 image.height=2 pitch=80 [ 357.379684] [ T2940] bit_putcs: width=1 cellsize=2 count=80 maxcnt=4096 scan_align=0 buf_align=0 image.width=640 image.height=2 pitch=80 (...snipped...) [ 357.720089] [ T2940] bit_putcs: width=1 cellsize=2 count=80 maxcnt=4096 scan_align=0 buf_align=0 image.width=640 image.height=2 pitch=80 [ 357.721519] [ T2940] bit_putcs: width=1 cellsize=2 count=80 maxcnt=4096 scan_align=0 buf_align=0 image.width=640 image.height=2 pitch=80 [ 357.722962] [ T2940] bit_putcs: width=1 cellsize=2 count=80 maxcnt=4096 scan_align=0 buf_align=0 image.width=640 image.height=2 pitch=80 [ 357.724390] [ T2940] bit_putcs: width=1 cellsize=2 count=80 maxcnt=4096 scan_align=0 buf_align=0 image.width=640 image.height=2 pitch=80 [ 357.725834] [ T2940] bit_putcs: width=1 cellsize=2 count=80 maxcnt=4096 scan_align=0 buf_align=0 image.width=640 image.height=2 pitch=80 [ 357.727876] [ T2940] vc=ffff8880d69b6000 v.v_rows=0 v.v_cols=0 v.v_vlin=1 v.v_clin=9 v.v_vcol=0 v.v_ccol=0 ret=0 [ 357.727933] [ T2940] vcp=ffff8880d69b6000 before: ->vc_rows=240 ->vc_cols=80 ->vc_scan_lines=1 save_scan_lines=400 ->vc_font.height=9 save_font_height=2 [ 357.727994] [ T2940] vcp=ffff8880d69b6000 after: ->vc_rows=240 ->vc_cols=80 ->vc_scan_lines=1 save_scan_lines=400 ->vc_font.height=9 save_font_height=2 ret=0 [ 357.728050] [ T2940] vcp=ffff8880d46d9000 before: ->vc_rows=30 ->vc_cols=80 ->vc_scan_lines=1 save_scan_lines=0 ->vc_font.height=9 save_font_height=16 [ 357.728110] [ T2940] vcp=ffff8880d46d9000 after: ->vc_rows=30 ->vc_cols=80 ->vc_scan_lines=1 save_scan_lines=0 ->vc_font.height=9 save_font_height=16 ret=0 [ 357.728167] [ T2940] vcp=ffff8880d40a8000 before: ->vc_rows=30 ->vc_cols=80 ->vc_scan_lines=1 save_scan_lines=0 ->vc_font.height=9 save_font_height=16 [ 357.728227] [ T2940] vcp=ffff8880d40a8000 after: ->vc_rows=30 ->vc_cols=80 ->vc_scan_lines=1 save_scan_lines=0 ->vc_font.height=9 save_font_height=16 ret=0 [ 357.728283] [ T2940] vcp=ffff8880d46fb000 before: ->vc_rows=30 ->vc_cols=80 ->vc_scan_lines=1 save_scan_lines=0 ->vc_font.height=9 save_font_height=16 [ 357.728344] [ T2940] vcp=ffff8880d46fb000 after: ->vc_rows=30 ->vc_cols=80 ->vc_scan_lines=1 save_scan_lines=0 ->vc_font.height=9 save_font_height=16 ret=0 [ 357.728400] [ T2940] vcp=ffff8880d46f9000 before: ->vc_rows=30 ->vc_cols=80 ->vc_scan_lines=1 save_scan_lines=0 ->vc_font.height=9 save_font_height=16 [ 357.728460] [ T2940] vcp=ffff8880d46f9000 after: ->vc_rows=30 ->vc_cols=80 ->vc_scan_lines=1 save_scan_lines=0 ->vc_font.height=9 save_font_height=16 ret=0 [ 357.728516] [ T2940] vcp=ffff8880ce2d1000 before: ->vc_rows=30 ->vc_cols=80 ->vc_scan_lines=1 save_scan_lines=0 ->vc_font.height=9 save_font_height=16 [ 357.728616] [ T2940] vcp=ffff8880ce2d1000 after: ->vc_rows=30 ->vc_cols=80 ->vc_scan_lines=1 save_scan_lines=0 ->vc_font.height=9 save_font_height=16 ret=0 [ 357.743762] [ C0] bit_putcs: width=1 cellsize=9 count=68 maxcnt=910 scan_align=0 buf_align=0 image.width=544 image.height=9 pitch=68 [ 357.743783] [ C0] ================================================================== [ 357.743803] [ C0] BUG: KASAN: slab-out-of-bounds in bit_putcs+0x6a0/0x980 [ 357.743822] [ C0] Read of size 1 at addr ffff8880d46ff343 by task a.out/2940 [ 357.743830] [ C0] [ 357.743848] [ C0] CPU: 0 PID: 2940 Comm: a.out Not tainted 5.9.0-rc6+ #635 [ 357.743871] [ C0] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 [ 357.743880] [ C0] Call Trace: [ 357.743891] [ C0] dump_stack+0x161/0x1c3 [ 357.743902] [ C0] ? bit_putcs+0x6a0/0x980 [ 357.743914] [ C0] ? bit_putcs+0x6a0/0x980 [ 357.743932] [ C0] print_address_description.constprop.0.cold+0xd3/0x4c5 [ 357.743944] [ C0] ? log_store.cold+0x16/0x16 [ 357.743956] [ C0] ? vprintk_func+0xe2/0x155 [ 357.743968] [ C0] ? bit_putcs+0x6a0/0x980 [ 357.743979] [ C0] ? bit_putcs+0x6a0/0x980 [ 357.743992] [ C0] kasan_report.cold+0x1f/0x42 [ 357.744003] [ C0] ? bit_putcs+0x6a0/0x980 [ 357.744014] [ C0] bit_putcs+0x6a0/0x980 [ 357.744026] [ C0] ? bit_clear+0x2f0/0x2f0 [ 357.744038] [ C0] ? find_held_lock+0x85/0xa0 [ 357.744052] [ C0] ? raw_notifier_call_chain+0x31/0x40 [ 357.744067] [ C0] ? fb_get_color_depth.part.0+0x57/0xe0 [ 357.744082] [ C0] ? __sanitizer_cov_trace_switch+0x49/0x80 [ 357.744093] [ C0] fbcon_putcs+0x1d8/0x1e0 [ 357.744105] [ C0] ? bit_clear+0x2f0/0x2f0 [ 357.744118] [ C0] vt_console_print+0x72d/0x870 [ 357.744130] [ C0] ? fb_flashcursor+0x230/0x230 [ 357.744144] [ C0] ? screen_glyph_unicode+0x140/0x140 [ 357.744157] [ C0] ? rwlock_bug.part.0+0x50/0x50 [ 357.744171] [ C0] ? screen_glyph_unicode+0x140/0x140 [ 357.744183] [ C0] console_unlock+0x92c/0xb30 [ 357.744195] [ C0] vt_ioctl.cold+0x182/0x3a2 [ 357.744210] [ C0] ? complete_change_console+0x1e0/0x1e0 [ 357.744222] [ C0] ? find_held_lock+0x85/0xa0 [ 357.744237] [ C0] ? debug_check_no_obj_freed+0x18d/0x276 [ 357.744249] [ C0] ? lock_downgrade+0x3e0/0x3e0 [ 357.744261] [ C0] ? find_held_lock+0x85/0xa0 [ 357.744274] [ C0] ? lock_is_held_type+0xbf/0xf0 [ 357.744285] [ C0] ? putname+0xa7/0xc0 [ 357.744296] [ C0] ? putname+0xa7/0xc0 [ 357.744306] [ C0] ? putname+0xa7/0xc0 [ 357.744322] [ C0] ? __sanitizer_cov_trace_switch+0x49/0x80 [ 357.744336] [ C0] ? complete_change_console+0x1e0/0x1e0 [ 357.744361] [ C0] ? tty_ioctl+0x7c4/0xec0 [ 357.744373] [ C0] tty_ioctl+0x7c4/0xec0 [ 357.744387] [ C0] ? kmem_cache_free.part.0+0x1b0/0x1e0 [ 357.744399] [ C0] ? tty_vhangup+0x30/0x30 [ 357.744414] [ C0] ? __sanitizer_cov_trace_switch+0x49/0x80 [ 357.744426] [ C0] ? do_vfs_ioctl+0x224/0xc50 [ 357.744439] [ C0] ? ioctl_file_clone+0x140/0x140 [ 357.744452] [ C0] ? file_open_root+0x420/0x420 [ 357.744467] [ C0] ? check_preemption_disabled+0x50/0x130 [ 357.744479] [ C0] ? lock_is_held_type+0xbf/0xf0 [ 357.744495] [ C0] ? syscall_enter_from_user_mode+0x1c/0x60 [ 357.744509] [ C0] ? rcu_read_lock_sched_held+0xa0/0xd0 [ 357.744521] [ C0] ? mark_held_locks+0x24/0x90 [ 357.744533] [ C0] ? tty_vhangup+0x30/0x30 [ 357.744545] [ C0] __x64_sys_ioctl+0xec/0x140 [ 357.744557] [ C0] do_syscall_64+0x31/0x70 [ 357.744572] [ C0] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 357.744583] [ C0] RIP: 0033:0x7f9b8316150b [ 357.744632] [ C0] Code: 0f 1e fa 48 8b 05 85 39 0d 00 64 c7 00 26 00 00 00 48 c7 c0 ff ff ff ff c3 66 0f 1f 44 00 00 f3 0f 1e fa b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 55 39 0d 00 f7 d8 64 89 01 48 [ 357.744647] [ C0] RSP: 002b:00007ffe190139b8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 [ 357.744680] [ C0] RAX: ffffffffffffffda RBX: 000055dc2ea7b220 RCX: 00007f9b8316150b [ 357.744701] [ C0] RDX: 00007ffe190139cc RSI: 000000000000560a RDI: 0000000000000003 [ 357.744721] [ C0] RBP: 0000000000000003 R08: 0000000000000000 R09: 00007f9b83257d50 [ 357.744741] [ C0] R10: 0000000000000000 R11: 0000000000000246 R12: 000055dc2ea7b130 [ 357.744762] [ C0] R13: 00007ffe19013ad0 R14: 0000000000000000 R15: 0000000000000000 [ 357.744769] [ C0] [ 357.744781] [ C0] Allocated by task 2940: [ 357.744793] [ C0] kasan_save_stack+0x1f/0x40 [ 357.744808] [ C0] __kasan_kmalloc.constprop.0+0xbf/0xd0 [ 357.744819] [ C0] __kmalloc+0x57d/0x9d0 [ 357.744831] [ C0] fbcon_set_font+0x1a6/0x4a0 [ 357.744843] [ C0] con_font_op+0x8e2/0xac0 [ 357.744854] [ C0] vt_ioctl+0x1186/0x21a0 [ 357.744866] [ C0] tty_ioctl+0x7c4/0xec0 [ 357.744878] [ C0] __x64_sys_ioctl+0xec/0x140 [ 357.744889] [ C0] do_syscall_64+0x31/0x70 [ 357.744905] [ C0] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 357.744912] [ C0] [ 357.744932] [ C0] The buggy address belongs to the object at ffff8880d46ff000 [ 357.744949] [ C0] which belongs to the cache kmalloc-1k of size 1024 [ 357.744967] [ C0] The buggy address is located 835 bytes inside of [ 357.744985] [ C0] 1024-byte region [ffff8880d46ff000, ffff8880d46ff400) [ 357.745000] [ C0] The buggy address belongs to the page: [ 357.745027] [ C0] page:00000000878ccadc refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0xd46ff [ 357.745040] [ C0] flags: 0xfffe0000000200(slab) [ 357.745063] [ C0] raw: 00fffe0000000200 ffffea00032a0808 ffffea00035ae308 ffff8880d6840700 [ 357.745086] [ C0] raw: 0000000000000000 ffff8880d46ff000 0000000100000002 ffff8880cbe8b281 [ 357.745103] [ C0] page dumped because: kasan: bad access detected [ 357.745117] [ C0] page->mem_cgroup:ffff8880cbe8b281 [ 357.745125] [ C0] [ 357.745140] [ C0] Memory state around the buggy address: [ 357.745162] [ C0] ffff8880d46ff200: 00 00 fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 357.745186] [ C0] ffff8880d46ff280: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 357.745208] [ C0] >ffff8880d46ff300: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 357.745224] [ C0] ^ [ 357.745246] [ C0] ffff8880d46ff380: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 357.745267] [ C0] ffff8880d46ff400: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 357.745288] [ C0] ================================================================== [ 357.745305] [ C0] Disabling lock debugging due to kernel taint [ 357.745349] [ C0] bit_putcs: width=1 cellsize=9 count=46 maxcnt=910 scan_align=0 buf_align=0 image.width=368 image.height=9 pitch=46 [ 357.759878] [ C0] bit_putcs: width=1 cellsize=9 count=80 maxcnt=910 scan_align=0 buf_align=0 image.width=640 image.height=9 pitch=80 [ 357.759910] [ C0] bit_putcs: width=1 cellsize=9 count=74 maxcnt=910 scan_align=0 buf_align=0 image.width=592 image.height=9 pitch=74 [ 357.775006] [ C0] bit_putcs: width=1 cellsize=9 count=80 maxcnt=910 scan_align=0 buf_align=0 image.width=640 image.height=9 pitch=80 ---------- _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel