Blame SOURCES/kvm-vmstate_xhci_event-bug-compat-with-RHEL-7.0-RHEL-onl.patch

91048c
From a0a7c88ceec2443192ec27242b176b66f82dd74a Mon Sep 17 00:00:00 2001
91048c
From: Laszlo Ersek <lersek@redhat.com>
91048c
Date: Mon, 1 Sep 2014 13:36:53 +0200
91048c
Subject: [PATCH 2/6] vmstate_xhci_event: bug compat with RHEL-7.0 (RHEL only)
91048c
91048c
Message-id: <1409578613-11909-3-git-send-email-lersek@redhat.com>
91048c
Patchwork-id: 60782
91048c
O-Subject: [PATCH RHEL-7.0.z/RHEL-7.1.0 qemu-kvm 2/2] vmstate_xhci_event: bug compat with RHEL-7.0 (RHEL only)
91048c
Bugzilla: 1145055
91048c
RH-Acked-by: Dr. David Alan Gilbert (git) <dgilbert@redhat.com>
91048c
RH-Acked-by: Amit Shah <amit.shah@redhat.com>
91048c
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
91048c
91048c
The "vmstate_xhci_event.fields" member is a pointer to an array of
91048c
VMStateField elements. The unnamed array (of static storage duration)
91048c
comes from a compound literal. The previous patch fixed the undefined
91048c
behavior by adding a terminator element to this array, but in RHEL-7 we
91048c
also need to look into the practical details of that undefined behavior.
91048c
91048c
In debug builds (./configure --enable-debug), the compiler places the
91048c
"vmstate_xhci_intr.fields" member's unnamed initializer array right after
91048c
the "vmstate_xhci_event.fields" member's. This leads to infinite recursion
91048c
(see the previous patch for details), but in RHEL-7 we don't ship debug
91048c
builds.
91048c
91048c
In a normal (optimized, official) build, the layout changes. The
91048c
"vmstate_xhci_event.fields" member's unterminated initializer array is
91048c
followed by the one of the "vmstate_xhci_slot.fields" member:
91048c
91048c
  (gdb) print (intptr_t)&vmstate_xhci_event.fields[7] - \
91048c
              (intptr_t)&vmstate_xhci_slot.fields[0]
91048c
  $3 = 0
91048c
91048c
where "vmstate_xhci_slot.fields" is initialized from
91048c
91048c
    .fields = (VMStateField[]) {
91048c
        VMSTATE_BOOL(enabled,   XHCISlot),
91048c
        VMSTATE_BOOL(addressed, XHCISlot),
91048c
        VMSTATE_END_OF_LIST()
91048c
    }
91048c
91048c
The elements of this array are (only relevant members quoted):
91048c
91048c
  (gdb) print vmstate_xhci_slot.fields[0].offset
91048c
  $16 = 0
91048c
  (gdb) print vmstate_xhci_slot.fields[0].size
91048c
  $17 = 1
91048c
  (gdb) print vmstate_xhci_slot.fields[1].offset
91048c
  $18 = 1
91048c
  (gdb) print vmstate_xhci_slot.fields[1].size
91048c
  $19 = 1
91048c
91048c
This means that the wire format for "vmstate_xhci_event" will include the
91048c
byte at offset 0 and the byte at offset 1 from XHCIEvent, corresponding to
91048c
part of the "XHCIEvent.type" member:
91048c
91048c
  (gdb) print vmstate_xhci_event.fields[0].name
91048c
  $23 = 0x5555558b12e7 "type"
91048c
  (gdb) print vmstate_xhci_event.fields[0].offset
91048c
  $24 = 0
91048c
  (gdb) print vmstate_xhci_event.fields[0].size
91048c
  $25 = 4
91048c
91048c
In order to accommodate these bogus bytes, coming from an unpatched source
91048c
side, we introduce two dummy XHCIEvent fields; otherwise the patched
91048c
destination would reject the migration stream.
91048c
91048c
For the reverse direction, we explicitly set the dummy bytes to the values
91048c
that they used to take in an unpatched source, so that when the unpatched
91048c
destination deserializes them into part of "XHCIEvent.type", said victim
91048c
member still receives a correct value.
91048c
91048c
The dummy fields have type uint8_t, not bool. The reason is that
91048c
assignment to bool (in xhci_event_pre_save()) would entail conversion to
91048c
bool, hence result in values 0 or 1. (See _Bool conversion rules and
91048c
<stdbool.h>.)
91048c
91048c
RHEL-only because we control the compiler version and the build flags only
91048c
in RHEL.
91048c
91048c
This is for CVE-2014-5263.
91048c
91048c
Suggested-by: Amit Shah <amit.shah@redhat.com>
91048c
Suggested-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
91048c
Suggested-by: Markus Armbruster <armbru@redhat.com>
91048c
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
91048c
91048c
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
91048c
---
91048c
 hw/usb/hcd-xhci.c |   27 ++++++++++++++++++++-------
91048c
 1 files changed, 20 insertions(+), 7 deletions(-)
91048c
91048c
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
91048c
index dbdf6b1..9f97167 100644
91048c
--- a/hw/usb/hcd-xhci.c
91048c
+++ b/hw/usb/hcd-xhci.c
91048c
@@ -420,6 +420,8 @@ typedef struct XHCIEvent {
91048c
     uint32_t flags;
91048c
     uint8_t slotid;
91048c
     uint8_t epid;
91048c
+    uint8_t cve_2014_5263_a;
91048c
+    uint8_t cve_2014_5263_b;
91048c
 } XHCIEvent;
91048c
 
91048c
 typedef struct XHCIInterrupter {
91048c
@@ -3515,17 +3517,28 @@ static const VMStateDescription vmstate_xhci_slot = {
91048c
     }
91048c
 };
91048c
 
91048c
+static void xhci_event_pre_save(void *opaque)
91048c
+{
91048c
+    XHCIEvent *s = opaque;
91048c
+
91048c
+    s->cve_2014_5263_a = ((uint8_t *)&s->type)[0];
91048c
+    s->cve_2014_5263_b = ((uint8_t *)&s->type)[1];
91048c
+}
91048c
+
91048c
 static const VMStateDescription vmstate_xhci_event = {
91048c
     .name = "xhci-event",
91048c
     .version_id = 1,
91048c
+    .pre_save = xhci_event_pre_save,
91048c
     .fields = (VMStateField[]) {
91048c
-        VMSTATE_UINT32(type,   XHCIEvent),
91048c
-        VMSTATE_UINT32(ccode,  XHCIEvent),
91048c
-        VMSTATE_UINT64(ptr,    XHCIEvent),
91048c
-        VMSTATE_UINT32(length, XHCIEvent),
91048c
-        VMSTATE_UINT32(flags,  XHCIEvent),
91048c
-        VMSTATE_UINT8(slotid,  XHCIEvent),
91048c
-        VMSTATE_UINT8(epid,    XHCIEvent),
91048c
+        VMSTATE_UINT32(type,           XHCIEvent),
91048c
+        VMSTATE_UINT32(ccode,          XHCIEvent),
91048c
+        VMSTATE_UINT64(ptr,            XHCIEvent),
91048c
+        VMSTATE_UINT32(length,         XHCIEvent),
91048c
+        VMSTATE_UINT32(flags,          XHCIEvent),
91048c
+        VMSTATE_UINT8(slotid,          XHCIEvent),
91048c
+        VMSTATE_UINT8(epid,            XHCIEvent),
91048c
+        VMSTATE_UINT8(cve_2014_5263_a, XHCIEvent),
91048c
+        VMSTATE_UINT8(cve_2014_5263_b, XHCIEvent),
91048c
         VMSTATE_END_OF_LIST()
91048c
     }
91048c
 };
91048c
-- 
91048c
1.7.1
91048c