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