qemu/usb-fix-setup_len-init-CVE-2020-14364.patch
Bruce Rogers d7b5d85f67 Accepting request 829656 from home:bfrogers:branches:Virtualization
- Fix OOB access while processing USB packets (CVE-2020-14364
  bsc#1175441)
  usb-fix-setup_len-init-CVE-2020-14364.patch
- Re-sync openSUSE and SUSE SLE qemu packages. This changes file
  is the openSUSE one with this entry providing the intervening
  SLE CVE, JIRA, and bugzilla references, which are still addressed
  in this package, and not yet called out in this changes file.
* CVE-2020-1983  CVE-2020-10761 CVE-2020-13361 CVE-2020-13362
  CVE-2020-13659 CVE-2020-13800
* bsc#1167816 bsc#1170940 boo#1171712 bsc#1172383 bsc#1172384
  bsc#1172386 bsc#1172495 bsc#1172710
* Patches dropped (SLE) (included in current release tarball):
  exec-set-map-length-to-zero-when-returni.patch
  i386-acpi-Remove-_HID-from-the-SMBus-ACP.patch
  megasas-use-unsigned-type-for-reply_queu.patch

OBS-URL: https://build.opensuse.org/request/show/829656
OBS-URL: https://build.opensuse.org/package/show/Virtualization/qemu?expand=0&rev=566
2020-08-26 01:50:23 +00:00

87 lines
3.1 KiB
Diff

From: Gerd Hoffmann <kraxel@redhat.com>
Date: Tue, 25 Aug 2020 07:36:36 +0200
Subject: usb: fix setup_len init (CVE-2020-14364)
Git-commit: 0000000000000000000000000000000000000000
References: bsc#1175441, CVE-2020-14364
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} functions specifically)
from working with invalid USBDevice->setup_len values and overrunning
the USBDevice->setup_buf[] buffer.
Fixes: CVE-2020-14364
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Tested-by: Gonglei <arei.gonglei@huawei.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
hw/usb/core.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/hw/usb/core.c b/hw/usb/core.c
index 5abd128b6bc5f5440e18b143fe41..5234dcc73fea6012f7143f307640 100644
--- a/hw/usb/core.c
+++ b/hw/usb/core.c
@@ -129,6 +129,7 @@ void usb_wakeup(USBEndpoint *ep, unsigned int stream)
static void do_token_setup(USBDevice *s, USBPacket *p)
{
int request, value, index;
+ unsigned int setup_len;
if (p->iov.size != 8) {
p->status = USB_RET_STALL;
@@ -138,14 +139,15 @@ static void do_token_setup(USBDevice *s, USBPacket *p)
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];
- if (s->setup_len > sizeof(s->data_buf)) {
+ setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6];
+ if (setup_len > sizeof(s->data_buf)) {
fprintf(stderr,
"usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
- s->setup_len, sizeof(s->data_buf));
+ setup_len, sizeof(s->data_buf));
p->status = USB_RET_STALL;
return;
}
+ s->setup_len = setup_len;
request = (s->setup_buf[0] << 8) | s->setup_buf[1];
value = (s->setup_buf[3] << 8) | s->setup_buf[2];
@@ -259,26 +261,28 @@ static void do_token_out(USBDevice *s, USBPacket *p)
static void do_parameter(USBDevice *s, USBPacket *p)
{
int i, request, value, index;
+ unsigned int setup_len;
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];
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)) {
+ setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6];
+ if (setup_len > sizeof(s->data_buf)) {
fprintf(stderr,
"usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
- s->setup_len, sizeof(s->data_buf));
+ setup_len, sizeof(s->data_buf));
p->status = USB_RET_STALL;
return;
}
+ s->setup_len = setup_len;
if (p->pid == USB_TOKEN_OUT) {
usb_packet_copy(p, s->data_buf, s->setup_len);