diff -Nru qemu-2.2+dfsg/debian/changelog qemu-2.2+dfsg/debian/changelog --- qemu-2.2+dfsg/debian/changelog 2016-05-26 13:50:06.000000000 +0000 +++ qemu-2.2+dfsg/debian/changelog 2016-05-30 16:11:47.000000000 +0000 @@ -1,3 +1,10 @@ +qemu (1:2.2+dfsg-5expubuntu9.7~cloud5) trusty-kilo; urgency=medium + + * debian/patches/aio-strengthen-memory-barriers.patch: Fix + "aio: strengthen memory barriers for bottom half scheduling" (LP: #1587039) + + -- Amad Ali Mon, 30 May 2016 17:57:00 +0000 + qemu (1:2.2+dfsg-5expubuntu9.7~cloud4) trusty-kilo; urgency=medium [ Corey Bryant ] diff -Nru qemu-2.2+dfsg/debian/patches/aio-strengthen-memory-barriers.patch qemu-2.2+dfsg/debian/patches/aio-strengthen-memory-barriers.patch --- qemu-2.2+dfsg/debian/patches/aio-strengthen-memory-barriers.patch 1970-01-01 00:00:00.000000000 +0000 +++ qemu-2.2+dfsg/debian/patches/aio-strengthen-memory-barriers.patch 2016-05-30 16:09:59.000000000 +0000 @@ -0,0 +1,139 @@ +Description: aio: strengthen memory barriers for bottom half sch + +There are two problems with memory barriers in async.c. The fix is +to use atomic_xchg in order to achieve sequential consistency between +the scheduling of a bottom half and the corresponding execution. + +First, if bh->scheduled is already 1 in qemu_bh_schedule, QEMU does +not execute a memory barrier to order any writes needed by the callback +before the read of bh->scheduled. If the other side sees req->state as +THREAD_ACTIVE, the callback is not invoked and you get deadlock. + +Second, the memory barrier in aio_bh_poll is too weak. Without this +patch, it is possible that bh->scheduled = 0 is not "published" until +after the callback has returned. Another thread wants to schedule the +bottom half, but it sees bh->scheduled = 1 and does nothing. This causes +a lost wakeup. The memory barrier should have been changed to smp_mb() +in commit 924fe12 (aio: fix qemu_bh_schedule() bh->ctx race condition, +(2014-06-03) together with qemu_bh_schedule()'s. Guess who reviewed +that patch? + +Both of these involve a store and a load, so they are reproducible on +x86_64 as well. It is however much easier on aarch64, where the +libguestfs test suite triggers the bug fairly easily. Even there the +failure can go away or appear depending on compiler optimization level, +tracing options, or even kernel debugging options. + +Paul Leveille however reported how to trigger the problem within 15 +minutes on x86_64 as well. His (untested) recipe, reproduced here +for reference, is the following: + + 1) Qcow2 (or 3) is critical a raw files alone seem to avoid the problem. + + 2) Use cache=directsync rather than the default of + cache=non to make it happen easier. + + 3) Use a server with a write-back RAID controller to allow for rapid + IO rates. + + 4) Run a random-access load that (mostly) writes chunks to various + files on the virtual block device. + + a. I use diskload.exe c:25, a Microsoft HCT load + generator, on Windows VMs. + + b. Iometer can probably be configured to generate a similar load. + + 5) Run multiple VMs in parallel, against the same storage device, + to shake the failure out sooner. + + 6) IvyBridge and Haswell processors for certain; not sure about others. + +A similar patch survived over 12 hours of testing, where an unpatched +QEMU would fail within 15 minutes. + +This bug is, most likely, also the cause of failures in the libguestfs +testsuite on AArch64. + +Thanks to Laszlo Ersek for initially reporting this bug, to Stefan +Hajnoczi for suggesting closer examination of qemu_bh_schedule, and to +Paul for providing test input and a prototype patch. + +Reported-by: Laszlo Ersek +Reported-by: Paul Leveille +Reported-by: John Snow +Signed-off-by: Paolo Bonzini +Suggested-by: Paul Leveille +Suggested-by: Stefan Hajnoczi +Signed-off-by: Paolo Bonzini +Signed-off-by: Stefan Hajnoczi + +Author: Paul Leveille +Origin: upstream, commit: e8d3b1a25f284cdf9705b7cf0412281cc9ee3a36 +Bug-Ubuntu: https://launchpad.net/bugs/1587039 +Last-Update: 2015-05-30 +--- + async.c | 28 ++++++++++++---------------- + 1 files changed, 12 insertions(+), 16 deletions(-) + +--- a/async.c ++++ b/async.c +@@ -70,12 +70,13 @@ + /* Make sure that fetching bh happens before accessing its members */ + smp_read_barrier_depends(); + next = bh->next; +- if (!bh->deleted && bh->scheduled) { +- bh->scheduled = 0; +- /* Paired with write barrier in bh schedule to ensure reading for +- * idle & callbacks coming after bh's scheduling. +- */ +- smp_rmb(); ++ /* The atomic_xchg is paired with the one in qemu_bh_schedule. The ++ * implicit memory barrier ensures that the callback sees all writes ++ * done by the scheduling thread. It also ensures that the scheduling ++ * thread sees the zero before bh->cb has run, and thus will call ++ * aio_notify again if necessary. ++ */ ++ if (!bh->deleted && atomic_xchg(&bh->scheduled, 0)) { + if (!bh->idle) + ret = 1; + bh->idle = 0; +@@ -106,33 +107,28 @@ + + void qemu_bh_schedule_idle(QEMUBH *bh) + { +- if (bh->scheduled) +- return; + bh->idle = 1; + /* Make sure that idle & any writes needed by the callback are done + * before the locations are read in the aio_bh_poll. + */ +- smp_wmb(); +- bh->scheduled = 1; ++ atomic_mb_set(&bh->scheduled, 1); + } + + void qemu_bh_schedule(QEMUBH *bh) + { + AioContext *ctx; + +- if (bh->scheduled) +- return; + ctx = bh->ctx; + bh->idle = 0; +- /* Make sure that: ++ /* The memory barrier implicit in atomic_xchg makes sure that: + * 1. idle & any writes needed by the callback are done before the + * locations are read in the aio_bh_poll. + * 2. ctx is loaded before scheduled is set and the callback has a chance + * to execute. + */ +- smp_mb(); +- bh->scheduled = 1; +- aio_notify(ctx); ++ if (atomic_xchg(&bh->scheduled, 1) == 0) { ++ aio_notify(ctx); ++ } + } + + diff -Nru qemu-2.2+dfsg/debian/patches/series qemu-2.2+dfsg/debian/patches/series --- qemu-2.2+dfsg/debian/patches/series 2016-05-26 13:57:43.000000000 +0000 +++ qemu-2.2+dfsg/debian/patches/series 2016-05-30 16:10:15.000000000 +0000 @@ -70,3 +70,4 @@ CVE-2016-4002.patch CVE-2016-4020.patch CVE-2016-4037.patch +aio-strengthen-memory-barriers.patch