[app-emulation/qemu] bump
This commit is contained in:
parent
72a699e3c3
commit
bb55fdb739
86
app-emulation/qemu/files/qemu-2.4.0-CVE-2015-5225.patch
Normal file
86
app-emulation/qemu/files/qemu-2.4.0-CVE-2015-5225.patch
Normal file
@ -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
|
||||||
|
|
124
app-emulation/qemu/files/qemu-2.4.0-block-mirror-crash.patch
Normal file
124
app-emulation/qemu/files/qemu-2.4.0-block-mirror-crash.patch
Normal file
@ -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
|
||||||
|
|
39
app-emulation/qemu/files/qemu-2.4.0-e1000-loop.patch
Normal file
39
app-emulation/qemu/files/qemu-2.4.0-e1000-loop.patch
Normal file
@ -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
|
@ -21,7 +21,7 @@ if [[ ${PV} = *9999* ]]; then
|
|||||||
else
|
else
|
||||||
SRC_URI="http://wiki.qemu-project.org/download/${P}.tar.bz2
|
SRC_URI="http://wiki.qemu-project.org/download/${P}.tar.bz2
|
||||||
${BACKPORTS:+
|
${BACKPORTS:+
|
||||||
http://dev.gentoo.org/~cardoe/distfiles/${P}-${BACKPORTS}.tar.xz}"
|
https://dev.gentoo.org/~cardoe/distfiles/${P}-${BACKPORTS}.tar.xz}"
|
||||||
KEYWORDS="~amd64 ~ppc ~ppc64 ~x86 ~x86-fbsd"
|
KEYWORDS="~amd64 ~ppc ~ppc64 ~x86 ~x86-fbsd"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -41,8 +41,8 @@ virtfs +vnc vte xattr xen xfs"
|
|||||||
COMMON_TARGETS="aarch64 alpha arm cris i386 m68k microblaze microblazeel mips
|
COMMON_TARGETS="aarch64 alpha arm cris i386 m68k microblaze microblazeel mips
|
||||||
mips64 mips64el mipsel or32 ppc ppc64 s390x sh4 sh4eb sparc sparc64 unicore32
|
mips64 mips64el mipsel or32 ppc ppc64 s390x sh4 sh4eb sparc sparc64 unicore32
|
||||||
x86_64"
|
x86_64"
|
||||||
IUSE_SOFTMMU_TARGETS="${COMMON_TARGETS} lm32 moxie ppcemb xtensa xtensaeb"
|
IUSE_SOFTMMU_TARGETS="${COMMON_TARGETS} lm32 moxie ppcemb tricore xtensa xtensaeb"
|
||||||
IUSE_USER_TARGETS="${COMMON_TARGETS} armeb mipsn32 mipsn32el ppc64abi32 sparc32plus"
|
IUSE_USER_TARGETS="${COMMON_TARGETS} armeb mipsn32 mipsn32el ppc64abi32 ppc64le sparc32plus"
|
||||||
|
|
||||||
use_softmmu_targets=$(printf ' qemu_softmmu_targets_%s' ${IUSE_SOFTMMU_TARGETS})
|
use_softmmu_targets=$(printf ' qemu_softmmu_targets_%s' ${IUSE_SOFTMMU_TARGETS})
|
||||||
use_user_targets=$(printf ' qemu_user_targets_%s' ${IUSE_USER_TARGETS})
|
use_user_targets=$(printf ' qemu_user_targets_%s' ${IUSE_USER_TARGETS})
|
||||||
@ -136,7 +136,7 @@ USER_LIB_DEPEND="${COMMON_LIB_DEPEND}"
|
|||||||
X86_FIRMWARE_DEPEND="
|
X86_FIRMWARE_DEPEND="
|
||||||
>=sys-firmware/ipxe-1.0.0_p20130624
|
>=sys-firmware/ipxe-1.0.0_p20130624
|
||||||
pin-upstream-blobs? (
|
pin-upstream-blobs? (
|
||||||
~sys-firmware/seabios-1.7.5
|
~sys-firmware/seabios-1.8.2
|
||||||
~sys-firmware/sgabios-0.1_pre8
|
~sys-firmware/sgabios-0.1_pre8
|
||||||
~sys-firmware/vgabios-0.7a
|
~sys-firmware/vgabios-0.7a
|
||||||
)
|
)
|
||||||
@ -271,7 +271,29 @@ pkg_setup() {
|
|||||||
|
|
||||||
#S="${WORKDIR}/${MY_P}"
|
#S="${WORKDIR}/${MY_P}"
|
||||||
|
|
||||||
|
# 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() {
|
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
|
# Alter target makefiles to accept CFLAGS set via flag-o
|
||||||
sed -i -r \
|
sed -i -r \
|
||||||
-e 's/^(C|OP_C|HELPER_C)FLAGS=/\1FLAGS+=/' \
|
-e 's/^(C|OP_C|HELPER_C)FLAGS=/\1FLAGS+=/' \
|
||||||
@ -281,6 +303,9 @@ src_prepare() {
|
|||||||
use nls || rm -f po/*.po
|
use nls || rm -f po/*.po
|
||||||
|
|
||||||
epatch "${FILESDIR}"/qemu-1.7.0-cflags.patch
|
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} ]] && \
|
[[ -n ${BACKPORTS} ]] && \
|
||||||
EPATCH_FORCE=yes EPATCH_SUFFIX="patch" EPATCH_SOURCE="${S}/patches" \
|
EPATCH_FORCE=yes EPATCH_SUFFIX="patch" EPATCH_SOURCE="${S}/patches" \
|
||||||
epatch
|
epatch
|
Loading…
Reference in New Issue
Block a user