summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2015-09-07 01:47:32 -0400
committerMike Frysinger <vapier@gentoo.org>2015-09-07 01:49:18 -0400
commitfec667228a95981586716b7d25004c4d706943e2 (patch)
tree3fa7d9f21c5ec520888e173a1dd033784ca91329
parentapp-emulation/qemu: add target sanity checks (diff)
downloadgentoo-fec667228a95981586716b7d25004c4d706943e2.tar.gz
gentoo-fec667228a95981586716b7d25004c4d706943e2.tar.bz2
gentoo-fec667228a95981586716b7d25004c4d706943e2.zip
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.
-rw-r--r--app-emulation/qemu/files/qemu-2.4.0-CVE-2015-5225.patch86
-rw-r--r--app-emulation/qemu/files/qemu-2.4.0-block-mirror-crash.patch124
-rw-r--r--app-emulation/qemu/files/qemu-2.4.0-e1000-loop.patch39
-rw-r--r--app-emulation/qemu/qemu-2.4.0-r1.ebuild (renamed from app-emulation/qemu/qemu-2.4.0.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 000000000000..de7090d01a4d
--- /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 <kraxel@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.fzz@alibaba-inc.com>
+Reviewed-by: P J P <ppandit@redhat.com>
+Signed-off-by: Gerd Hoffmann <kraxel@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 000000000000..ad4051e22c94
--- /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 <kwolf@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-stable@nongnu.org
+Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
+Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
+Reviewed-by: Jeff Cody <jcody@redhat.com>
+Message-id: 1439455310-11263-1-git-send-email-kwolf@redhat.com
+Signed-off-by: Jeff Cody <jcody@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 000000000000..f2538a723d15
--- /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 <stefanha@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 <pjp@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 <pjp@fedoraproject.org>
+Signed-off-by: Stefan Hajnoczi <stefanha@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
index 0dfa27f069fb..13c15adbaad3 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