commit:     fec667228a95981586716b7d25004c4d706943e2
Author:     Mike Frysinger <vapier <AT> gentoo <DOT> org>
AuthorDate: Mon Sep  7 05:47:32 2015 +0000
Commit:     Mike Frysinger <vapier <AT> gentoo <DOT> org>
CommitDate: Mon Sep  7 05:49:18 2015 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=fec66722

app-emulation/qemu: various fixes/updates

Sync in the updates from the 9999 ebuild:
 - updated seabios pin
 - add new targets
 - add sanity checks for targets

Add fix from upstream for blockcommit crashes #558396.

Add fix from upstream for CVE-2015-5225 #558416.

Add fix posted upstream (but not yet merged) for e1000 infinite loop #559656.

 .../qemu/files/qemu-2.4.0-CVE-2015-5225.patch      |  86 ++++++++++++++
 .../qemu/files/qemu-2.4.0-block-mirror-crash.patch | 124 +++++++++++++++++++++
 .../qemu/files/qemu-2.4.0-e1000-loop.patch         |  39 +++++++
 .../{qemu-2.4.0.ebuild => qemu-2.4.0-r1.ebuild}    |  31 +++++-
 4 files changed, 277 insertions(+), 3 deletions(-)

diff --git a/app-emulation/qemu/files/qemu-2.4.0-CVE-2015-5225.patch 
b/app-emulation/qemu/files/qemu-2.4.0-CVE-2015-5225.patch
new file mode 100644
index 0000000..de7090d
--- /dev/null
+++ b/app-emulation/qemu/files/qemu-2.4.0-CVE-2015-5225.patch
@@ -0,0 +1,86 @@
+https://bugs.gentoo.org/558416
+
+fix from upstream git
+
+From eb8934b0418b3b1d125edddc4fc334a54334a49b Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kra...@redhat.com>
+Date: Mon, 17 Aug 2015 19:56:53 +0200
+Subject: [PATCH] vnc: fix memory corruption (CVE-2015-5225)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The _cmp_bytes variable added by commit "bea60dd ui/vnc: fix potential
+memory corruption issues" can become negative.  Result is (possibly
+exploitable) memory corruption.  Reason for that is it uses the stride
+instead of bytes per scanline to apply limits.
+
+For the server surface is is actually fine.  vnc creates that itself,
+there is never any padding and thus scanline length always equals stride.
+
+For the guest surface scanline length and stride are typically identical
+too, but it doesn't has to be that way.  So add and use a new variable
+(guest_ll) for the guest scanline length.  Also rename min_stride to
+line_bytes to make more clear what it actually is.  Finally sprinkle
+in an assert() to make sure we never use a negative _cmp_bytes again.
+
+Reported-by: 范祚至(库特) <zuozhi....@alibaba-inc.com>
+Reviewed-by: P J P <ppan...@redhat.com>
+Signed-off-by: Gerd Hoffmann <kra...@redhat.com>
+---
+ ui/vnc.c | 15 ++++++++++-----
+ 1 file changed, 10 insertions(+), 5 deletions(-)
+
+diff --git a/ui/vnc.c b/ui/vnc.c
+index e26973a..caf82f5 100644
+--- a/ui/vnc.c
++++ b/ui/vnc.c
+@@ -2872,7 +2872,7 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
+                     pixman_image_get_width(vd->server));
+     int height = MIN(pixman_image_get_height(vd->guest.fb),
+                      pixman_image_get_height(vd->server));
+-    int cmp_bytes, server_stride, min_stride, guest_stride, y = 0;
++    int cmp_bytes, server_stride, line_bytes, guest_ll, guest_stride, y = 0;
+     uint8_t *guest_row0 = NULL, *server_row0;
+     VncState *vs;
+     int has_dirty = 0;
+@@ -2891,17 +2891,21 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
+      * Update server dirty map.
+      */
+     server_row0 = (uint8_t *)pixman_image_get_data(vd->server);
+-    server_stride = guest_stride = pixman_image_get_stride(vd->server);
++    server_stride = guest_stride = guest_ll =
++        pixman_image_get_stride(vd->server);
+     cmp_bytes = MIN(VNC_DIRTY_PIXELS_PER_BIT * VNC_SERVER_FB_BYTES,
+                     server_stride);
+     if (vd->guest.format != VNC_SERVER_FB_FORMAT) {
+         int width = pixman_image_get_width(vd->server);
+         tmpbuf = qemu_pixman_linebuf_create(VNC_SERVER_FB_FORMAT, width);
+     } else {
++        int guest_bpp =
++            PIXMAN_FORMAT_BPP(pixman_image_get_format(vd->guest.fb));
+         guest_row0 = (uint8_t *)pixman_image_get_data(vd->guest.fb);
+         guest_stride = pixman_image_get_stride(vd->guest.fb);
++        guest_ll = pixman_image_get_width(vd->guest.fb) * ((guest_bpp + 7) / 
8);
+     }
+-    min_stride = MIN(server_stride, guest_stride);
++    line_bytes = MIN(server_stride, guest_ll);
+ 
+     for (;;) {
+         int x;
+@@ -2932,9 +2936,10 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
+             if (!test_and_clear_bit(x, vd->guest.dirty[y])) {
+                 continue;
+             }
+-            if ((x + 1) * cmp_bytes > min_stride) {
+-                _cmp_bytes = min_stride - x * cmp_bytes;
++            if ((x + 1) * cmp_bytes > line_bytes) {
++                _cmp_bytes = line_bytes - x * cmp_bytes;
+             }
++            assert(_cmp_bytes >= 0);
+             if (memcmp(server_ptr, guest_ptr, _cmp_bytes) == 0) {
+                 continue;
+             }
+-- 
+2.5.0
+

diff --git a/app-emulation/qemu/files/qemu-2.4.0-block-mirror-crash.patch 
b/app-emulation/qemu/files/qemu-2.4.0-block-mirror-crash.patch
new file mode 100644
index 0000000..ad4051e
--- /dev/null
+++ b/app-emulation/qemu/files/qemu-2.4.0-block-mirror-crash.patch
@@ -0,0 +1,124 @@
+https://bugs.gentoo.org/558396
+
+fix from upstream git
+
+From e424aff5f307227b1c2512bbb8ece891bb895cef Mon Sep 17 00:00:00 2001
+From: Kevin Wolf <kw...@redhat.com>
+Date: Thu, 13 Aug 2015 10:41:50 +0200
+Subject: [PATCH] mirror: Fix coroutine reentrance
+
+This fixes a regression introduced by commit dcfb3beb ("mirror: Do zero
+write on target if sectors not allocated"), which was reported to cause
+aborts with the message "Co-routine re-entered recursively".
+
+The cause for this bug is the following code in mirror_iteration_done():
+
+    if (s->common.busy) {
+        qemu_coroutine_enter(s->common.co, NULL);
+    }
+
+This has always been ugly because - unlike most places that reenter - it
+doesn't have a specific yield that it pairs with, but is more
+uncontrolled.  What we really mean here is "reenter the coroutine if
+it's in one of the four explicit yields in mirror.c".
+
+This used to be equivalent with s->common.busy because neither
+mirror_run() nor mirror_iteration() call any function that could yield.
+However since commit dcfb3beb this doesn't hold true any more:
+bdrv_get_block_status_above() can yield.
+
+So what happens is that bdrv_get_block_status_above() wants to take a
+lock that is already held, so it adds itself to the queue of waiting
+coroutines and yields. Instead of being woken up by the unlock function,
+however, it gets woken up by mirror_iteration_done(), which is obviously
+wrong.
+
+In most cases the code actually happens to cope fairly well with such
+cases, but in this specific case, the unlock must already have scheduled
+the coroutine for wakeup when mirror_iteration_done() reentered it. And
+then the coroutine happened to process the scheduled restarts and tried
+to reenter itself recursively.
+
+This patch fixes the problem by pairing the reenter in
+mirror_iteration_done() with specific yields instead of abusing
+s->common.busy.
+
+Cc: qemu-sta...@nongnu.org
+Signed-off-by: Kevin Wolf <kw...@redhat.com>
+Reviewed-by: Paolo Bonzini <pbonz...@redhat.com>
+Reviewed-by: Stefan Hajnoczi <stefa...@redhat.com>
+Reviewed-by: Jeff Cody <jc...@redhat.com>
+Message-id: 1439455310-11263-1-git-send-email-kw...@redhat.com
+Signed-off-by: Jeff Cody <jc...@redhat.com>
+---
+ block/mirror.c | 15 ++++++++++-----
+ 1 file changed, 10 insertions(+), 5 deletions(-)
+
+diff --git a/block/mirror.c b/block/mirror.c
+index 0841964..9474443 100644
+--- a/block/mirror.c
++++ b/block/mirror.c
+@@ -60,6 +60,7 @@ typedef struct MirrorBlockJob {
+     int sectors_in_flight;
+     int ret;
+     bool unmap;
++    bool waiting_for_io;
+ } MirrorBlockJob;
+ 
+ typedef struct MirrorOp {
+@@ -114,11 +115,7 @@ static void mirror_iteration_done(MirrorOp *op, int ret)
+     qemu_iovec_destroy(&op->qiov);
+     g_slice_free(MirrorOp, op);
+ 
+-    /* Enter coroutine when it is not sleeping.  The coroutine sleeps to
+-     * rate-limit itself.  The coroutine will eventually resume since there is
+-     * a sleep timeout so don't wake it early.
+-     */
+-    if (s->common.busy) {
++    if (s->waiting_for_io) {
+         qemu_coroutine_enter(s->common.co, NULL);
+     }
+ }
+@@ -203,7 +200,9 @@ static uint64_t coroutine_fn 
mirror_iteration(MirrorBlockJob *s)
+     /* Wait for I/O to this cluster (from a previous iteration) to be done.  
*/
+     while (test_bit(next_chunk, s->in_flight_bitmap)) {
+         trace_mirror_yield_in_flight(s, sector_num, s->in_flight);
++        s->waiting_for_io = true;
+         qemu_coroutine_yield();
++        s->waiting_for_io = false;
+     }
+ 
+     do {
+@@ -239,7 +238,9 @@ static uint64_t coroutine_fn 
mirror_iteration(MirrorBlockJob *s)
+          */
+         while (nb_chunks == 0 && s->buf_free_count < added_chunks) {
+             trace_mirror_yield_buf_busy(s, nb_chunks, s->in_flight);
++            s->waiting_for_io = true;
+             qemu_coroutine_yield();
++            s->waiting_for_io = false;
+         }
+         if (s->buf_free_count < nb_chunks + added_chunks) {
+             trace_mirror_break_buf_busy(s, nb_chunks, s->in_flight);
+@@ -337,7 +338,9 @@ static void mirror_free_init(MirrorBlockJob *s)
+ static void mirror_drain(MirrorBlockJob *s)
+ {
+     while (s->in_flight > 0) {
++        s->waiting_for_io = true;
+         qemu_coroutine_yield();
++        s->waiting_for_io = false;
+     }
+ }
+ 
+@@ -510,7 +513,9 @@ static void coroutine_fn mirror_run(void *opaque)
+             if (s->in_flight == MAX_IN_FLIGHT || s->buf_free_count == 0 ||
+                 (cnt == 0 && s->in_flight > 0)) {
+                 trace_mirror_yield(s, s->in_flight, s->buf_free_count, cnt);
++                s->waiting_for_io = true;
+                 qemu_coroutine_yield();
++                s->waiting_for_io = false;
+                 continue;
+             } else if (cnt != 0) {
+                 delay_ns = mirror_iteration(s);
+-- 
+2.5.0
+

diff --git a/app-emulation/qemu/files/qemu-2.4.0-e1000-loop.patch 
b/app-emulation/qemu/files/qemu-2.4.0-e1000-loop.patch
new file mode 100644
index 0000000..f2538a7
--- /dev/null
+++ b/app-emulation/qemu/files/qemu-2.4.0-e1000-loop.patch
@@ -0,0 +1,39 @@
+https://bugs.gentoo.org/559656
+
+https://lists.gnu.org/archive/html/qemu-devel/2015-09/msg01199.html
+
+From: Stefan Hajnoczi <stefa...@redhat.com>
+Subject: [PATCH] e1000: Avoid infinite loop in processing      transmit 
descriptor
+Newsgroups: gmane.comp.emulators.qemu
+Date: 2015-09-04 16:21:06 GMT (2 days, 12 hours and 51 minutes ago)
+From: P J P <p...@fedoraproject.org>
+
+While processing transmit descriptors, it could lead to an infinite
+loop if 'bytes' was to become zero; Add a check to avoid it.
+
+[The guest can force 'bytes' to 0 by setting the hdr_len and mss
+descriptor fields to 0.
+--Stefan]
+
+Signed-off-by: P J P <p...@fedoraproject.org>
+Signed-off-by: Stefan Hajnoczi <stefa...@redhat.com>
+---
+ hw/net/e1000.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/hw/net/e1000.c b/hw/net/e1000.c
+index 5c6bcd0..09c9e9d 100644
+--- a/hw/net/e1000.c
++++ b/hw/net/e1000.c
+@@ -740,7 +740,8 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
+                 memmove(tp->data, tp->header, tp->hdr_len);
+                 tp->size = tp->hdr_len;
+             }
+-        } while (split_size -= bytes);
++            split_size -= bytes;
++        } while (bytes && split_size);
+     } else if (!tp->tse && tp->cptse) {
+         // context descriptor TSE is not set, while data descriptor TSE is set
+         DBGOUT(TXERR, "TCP segmentation error\n");
+-- 
+2.4.3

diff --git a/app-emulation/qemu/qemu-2.4.0.ebuild 
b/app-emulation/qemu/qemu-2.4.0-r1.ebuild
similarity index 95%
rename from app-emulation/qemu/qemu-2.4.0.ebuild
rename to app-emulation/qemu/qemu-2.4.0-r1.ebuild
index 0dfa27f..13c15ad 100644
--- a/app-emulation/qemu/qemu-2.4.0.ebuild
+++ b/app-emulation/qemu/qemu-2.4.0-r1.ebuild
@@ -39,8 +39,8 @@ virtfs +vnc vte xattr xen xfs"
 COMMON_TARGETS="aarch64 alpha arm cris i386 m68k microblaze microblazeel mips
 mips64 mips64el mipsel or32 ppc ppc64 s390x sh4 sh4eb sparc sparc64 unicore32
 x86_64"
-IUSE_SOFTMMU_TARGETS="${COMMON_TARGETS} lm32 moxie ppcemb xtensa xtensaeb"
-IUSE_USER_TARGETS="${COMMON_TARGETS} armeb mipsn32 mipsn32el ppc64abi32 
sparc32plus"
+IUSE_SOFTMMU_TARGETS="${COMMON_TARGETS} lm32 moxie ppcemb tricore xtensa 
xtensaeb"
+IUSE_USER_TARGETS="${COMMON_TARGETS} armeb mipsn32 mipsn32el ppc64abi32 
ppc64le sparc32plus"
 
 use_softmmu_targets=$(printf ' qemu_softmmu_targets_%s' 
${IUSE_SOFTMMU_TARGETS})
 use_user_targets=$(printf ' qemu_user_targets_%s' ${IUSE_USER_TARGETS})
@@ -134,7 +134,7 @@ USER_LIB_DEPEND="${COMMON_LIB_DEPEND}"
 X86_FIRMWARE_DEPEND="
        >=sys-firmware/ipxe-1.0.0_p20130624
        pin-upstream-blobs? (
-               ~sys-firmware/seabios-1.7.5
+               ~sys-firmware/seabios-1.8.2
                ~sys-firmware/sgabios-0.1_pre8
                ~sys-firmware/vgabios-0.7a
        )
@@ -268,7 +268,29 @@ pkg_setup() {
        enewgroup kvm 78
 }
 
+# Sanity check to make sure target lists are kept up-to-date.
+check_targets() {
+       local var=$1 mak=$2
+       local detected sorted
+
+       pushd "${S}"/default-configs >/dev/null || die
+
+       detected=$(echo $(printf '%s\n' *-${mak}.mak | sed "s:-${mak}.mak::" | 
sort -u))
+       sorted=$(echo $(printf '%s\n' ${!var} | sort -u))
+       if [[ ${sorted} != "${detected}" ]] ; then
+               eerror "The ebuild needs to be kept in sync."
+               eerror "${var}: ${sorted}"
+               eerror "$(printf '%-*s' ${#var} configure): ${detected}"
+               die "sync ${var} to the list of targets"
+       fi
+
+       popd >/dev/null
+}
+
 src_prepare() {
+       check_targets IUSE_SOFTMMU_TARGETS softmmu
+       check_targets IUSE_USER_TARGETS linux-user
+
        # Alter target makefiles to accept CFLAGS set via flag-o
        sed -i -r \
                -e 's/^(C|OP_C|HELPER_C)FLAGS=/\1FLAGS+=/' \
@@ -278,6 +300,9 @@ src_prepare() {
        use nls || rm -f po/*.po
 
        epatch "${FILESDIR}"/qemu-1.7.0-cflags.patch
+       epatch "${FILESDIR}"/${P}-block-mirror-crash.patch #558396
+       epatch "${FILESDIR}"/${P}-CVE-2015-5225.patch #558416
+       epatch "${FILESDIR}"/${PN}-2.4.0-e1000-loop.patch #559656
        [[ -n ${BACKPORTS} ]] && \
                EPATCH_FORCE=yes EPATCH_SUFFIX="patch" 
EPATCH_SOURCE="${S}/patches" \
                        epatch

Reply via email to