CVE-2020-14364 QEMU USB Out-of-Bounds R/W Access Issue
CVE-2020-14364 QEMU USB Out-of-bounds R/W Access Issue
Vulnerability Description
QEMU (short for Quick Emulator) is a free, open source hosted virtual machine written by Fabrice Bellard et al. for hardware virtualization. It is similar to Bochs and PearPC, but it has some features that the latter two do not have, such as high speed (working with KVM) and cross-platform features. QEMU emulates CPUs through dynamic binary translation and provides a set of device models, enabling it to run a variety of unmodified guest operating systems. In virtualization and cloud computing scenarios, it is used together with KVM to run virtual machines at near-native speed.
Recently, Qihoo 360 Inc. found an out-of-bounds read/write access issue in the QEMU USB controller emulation source code hw/usb/core.c. Attackers may exploit this vulnerability to obtain the execution permission of QEMU users and perform a full QEMU VM escape. (CVE-2020-14364)
Vulnerability Analysis
- This vulnerability exists in the USB controller emulator code usb_process_one. Assigning a value to s->setup_len without verification may introduce out-of-bounds read/write risks. By default, the VM started by libvirt is configured with a USB device. The interaction between any USB controller (such as UHCI, EHCI, and XHCI) and USB device (such as USB tablets and USB mouse devices) requires the usb_process_one function in the core.c file. Therefore, theoretically, as long as VMs use USB devices, vulnerability attacks may occur. The usb_process_one function may also be introduced to the do_parameter and do_token_setup functions. That is, the array length (s->setup_len) has been set before it is checked.
- This vulnerability has a serious impact because attackers can exploit this vulnerability to read and write any address and obtain all permissions of the QEMU process to cause a VM escape for malicious attacks. What's worse, if the QEMU process is run by the root user group, attackers can obtain the full control permissions of the operating system to run any Linux system commands.
Code Analysis
static void do_token_setup(USBDevice *s, USBPacket *p)
{
int request, value, index;
if (p->iov.size != 8) {
p->status = USB_RET_STALL;
return;
}
usb_packet_copy(p, s->setup_buf, p->iov.size);
s->setup_index = 0;
p->actual_length = 0;
s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6]; // Assigns a value to s->setup_len.
if (s->setup_len > sizeof(s->data_buf)) { // Verifies the validity of setup_len.
fprintf(stderr,
"usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
s->setup_len, sizeof(s->data_buf));
p->status = USB_RET_STALL;
return;
}
static void do_parameter(USBDevice *s, USBPacket *p)
{
int i, request, value, index;
for (i = 0; i < 8; i++) {
s->setup_buf[i] = p->parameter >> (i*8);
}
s->setup_state = SETUP_STATE_PARAM;
s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6]; // Assigns a value to s->setup_len.
s->setup_index = 0;
request = (s->setup_buf[0] << 8) | s->setup_buf[1];
value = (s->setup_buf[3] << 8) | s->setup_buf[2];
index = (s->setup_buf[5] << 8) | s->setup_buf[4];
if (s->setup_len > sizeof(s->data_buf)) { // Verifies the validity of setup_len.
fprintf(stderr,
"usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
s->setup_len, sizeof(s->data_buf));
p->status = USB_RET_STALL;
return;
}
According to the code, in the do_token_setup and do_parameter functions, s->setup_len is specified before it is checked. Even the value of s->setup_len exceeds the preset buffer size, the value of the former is not changed. As a result, the contaminated data can still be read and written out of bounds.
Impact Analysis
- Impact Scope
This vulnerability exists in the source code of QEMU 1.x and later versions, including the QEMU code used by the openEuler community. - Trigger Condition
The VM must have been connected to at least one USB device. In most cases, libvirt configures a USB device for the VM by default.
Vulnerability Fixing Method
According to the repair solution provided by Qihoo 360 Inc., when setup_len is invalid, s->setup_len is cleared to discard the USB request in the buffer, and the USB status is set to SETUP_STATE_ACK to accept other requests. The patch is as follows:
Subject: [PATCH] hw/usb/core.c fix buffer overflow
Store calculated setup_len in a local variable, verify it,
and only write it to the struct (USBDevice->setup_len) in case it passed the
sanity checks.
This prevents other code (do_token_{in,out} function specifically)
from working with invalid USBDevice->setup_len values and overruning
the USBDevice->setup_buf[] buffer.
Store
Fixes: CVE-2020-14364
Signed-off-by: Gred Hoffman <kraxel@redhat.com>
---
hw/usb/core.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hw/usb/core.c b/hw/usb/core.c
index 5abd128b..12342f13 100644
--- a/hw/usb/core.c
+++ b/hw/usb/core.c
@@ -144,6 +144,8 @@ static void do_token_setup(USBDevice *s, USBPacket *p)
"usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
s->setup_len, sizeof(s->data_buf));
p->status = USB_RET_STALL;
+ s->setup_len = 0;
+ s->setup_state = SETUP_STATE_ACK;
return;
}
@@ -277,6 +279,8 @@ static void do_parameter(USBDevice *s, USBPacket *p)
"usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
s->setup_len, sizeof(s->data_buf));
p->status = USB_RET_STALL;
+ s->setup_len = 0;
+ s->setup_state = SETUP_STATE_ACK;
return;
}
--
Solution
Download the latest QEMU software package released by openEuler.
Update the QEMU software package.
- rpm -Uvh qemu-*.rpm
After the update is complete, check the release number of the QEMU software package. If the release number is greater than 17, the vulnerability is successfully fixed.
rpm -qi qemu-4.1.0
Name : qemu Epoch : 2 Version : 4.1.0 Release : 18.oe1 Architecture: aarch64 Install Date: Mon 10 Aug 2020 04:53:20 PM CST Group : Unspecified Size : 19468602 License : GPLv2 and BSD and MIT and CC-BY Signature : RSA/SHA1, Thu 09 Jul 2020 11:52:58 AM CST, Key ID d557065eb25e7f66 Source RPM : qemu-4.1.0-14.oe1.src.rpm Build Date : Thu 09 Jul 2020 11:44:23 AM CST Build Host : obs-worker-004 Packager : http://openeuler.org Vendor : http://openeuler.org URL : http://www.qemu.org
FAQs
- What measures did the openEuler community take to resolve this vulnerability?
After learning the vulnerability, related personnel in the community immediately developed a patch and integrate the patch into the related branches of the community. - How do I obtain the specific reproduction scenario of the vulnerability?
For details, see Qihoo 360 Inc.'s sharing at the 8th Internet Security Conference (“ISC 2020”).- https://isc.360.com/2020/detail.html?vid=108
- https://www.anquanke.com/post/id/215405