From: "Anthony G. Basile" <blueness@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/hardened-dev:musl commit in: app-emulation/qemu/files/, app-emulation/qemu/
Date: Mon, 8 Jun 2015 12:26:49 +0000 (UTC) [thread overview]
Message-ID: <1433766459.dd8f541bb891cc198527837f2eedb81594efb1f3.blueness@gentoo> (raw)
commit: dd8f541bb891cc198527837f2eedb81594efb1f3
Author: Felix Janda <felix.janda <AT> posteo <DOT> de>
AuthorDate: Sun Jun 7 19:17:51 2015 +0000
Commit: Anthony G. Basile <blueness <AT> gentoo <DOT> org>
CommitDate: Mon Jun 8 12:27:39 2015 +0000
URL: https://gitweb.gentoo.org/proj/hardened-dev.git/commit/?id=dd8f541b
app-emulation/qemu: Bump to 2.2.0
.../qemu/files/qemu-2.2.1-CVE-2015-1779-1.patch | 241 +++++++++++++++++++++
.../qemu/files/qemu-2.2.1-CVE-2015-1779-2.patch | 58 +++++
.../qemu/files/qemu-2.3.0-CVE-2015-3456.patch | 86 ++++++++
...qemu-2.2.0-r99.ebuild => qemu-2.2.1-r99.ebuild} | 21 +-
4 files changed, 397 insertions(+), 9 deletions(-)
diff --git a/app-emulation/qemu/files/qemu-2.2.1-CVE-2015-1779-1.patch b/app-emulation/qemu/files/qemu-2.2.1-CVE-2015-1779-1.patch
new file mode 100644
index 0000000..35ef8fd
--- /dev/null
+++ b/app-emulation/qemu/files/qemu-2.2.1-CVE-2015-1779-1.patch
@@ -0,0 +1,241 @@
+From a2bebfd6e09d285aa793cae3fb0fc3a39a9fee6e Mon Sep 17 00:00:00 2001
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 23 Mar 2015 22:58:21 +0000
+Subject: [PATCH] CVE-2015-1779: incrementally decode websocket frames
+
+The logic for decoding websocket frames wants to fully
+decode the frame header and payload, before allowing the
+VNC server to see any of the payload data. There is no
+size limit on websocket payloads, so this allows a
+malicious network client to consume 2^64 bytes in memory
+in QEMU. It can trigger this denial of service before
+the VNC server even performs any authentication.
+
+The fix is to decode the header, and then incrementally
+decode the payload data as it is needed. With this fix
+the websocket decoder will allow at most 4k of data to
+be buffered before decoding and processing payload.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+
+[ kraxel: fix frequent spurious disconnects, suggested by Peter Maydell ]
+
+ @@ -361,7 +361,7 @@ int vncws_decode_frame_payload(Buffer *input,
+ - *payload_size = input->offset;
+ + *payload_size = *payload_remain;
+
+[ kraxel: fix 32bit build ]
+
+ @@ -306,7 +306,7 @@ struct VncState
+ - uint64_t ws_payload_remain;
+ + size_t ws_payload_remain;
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+---
+ ui/vnc-ws.c | 105 ++++++++++++++++++++++++++++++++++++++++--------------------
+ ui/vnc-ws.h | 9 ++++--
+ ui/vnc.h | 2 ++
+ 3 files changed, 80 insertions(+), 36 deletions(-)
+
+diff --git a/ui/vnc-ws.c b/ui/vnc-ws.c
+index 85dbb7e..0b7de4e 100644
+--- a/ui/vnc-ws.c
++++ b/ui/vnc-ws.c
+@@ -107,7 +107,7 @@ long vnc_client_read_ws(VncState *vs)
+ {
+ int ret, err;
+ uint8_t *payload;
+- size_t payload_size, frame_size;
++ size_t payload_size, header_size;
+ VNC_DEBUG("Read websocket %p size %zd offset %zd\n", vs->ws_input.buffer,
+ vs->ws_input.capacity, vs->ws_input.offset);
+ buffer_reserve(&vs->ws_input, 4096);
+@@ -117,18 +117,39 @@ long vnc_client_read_ws(VncState *vs)
+ }
+ vs->ws_input.offset += ret;
+
+- /* make sure that nothing is left in the ws_input buffer */
++ ret = 0;
++ /* consume as much of ws_input buffer as possible */
+ do {
+- err = vncws_decode_frame(&vs->ws_input, &payload,
+- &payload_size, &frame_size);
+- if (err <= 0) {
+- return err;
++ if (vs->ws_payload_remain == 0) {
++ err = vncws_decode_frame_header(&vs->ws_input,
++ &header_size,
++ &vs->ws_payload_remain,
++ &vs->ws_payload_mask);
++ if (err <= 0) {
++ return err;
++ }
++
++ buffer_advance(&vs->ws_input, header_size);
+ }
++ if (vs->ws_payload_remain != 0) {
++ err = vncws_decode_frame_payload(&vs->ws_input,
++ &vs->ws_payload_remain,
++ &vs->ws_payload_mask,
++ &payload,
++ &payload_size);
++ if (err < 0) {
++ return err;
++ }
++ if (err == 0) {
++ return ret;
++ }
++ ret += err;
+
+- buffer_reserve(&vs->input, payload_size);
+- buffer_append(&vs->input, payload, payload_size);
++ buffer_reserve(&vs->input, payload_size);
++ buffer_append(&vs->input, payload, payload_size);
+
+- buffer_advance(&vs->ws_input, frame_size);
++ buffer_advance(&vs->ws_input, payload_size);
++ }
+ } while (vs->ws_input.offset > 0);
+
+ return ret;
+@@ -265,15 +286,14 @@ void vncws_encode_frame(Buffer *output, const void *payload,
+ buffer_append(output, payload, payload_size);
+ }
+
+-int vncws_decode_frame(Buffer *input, uint8_t **payload,
+- size_t *payload_size, size_t *frame_size)
++int vncws_decode_frame_header(Buffer *input,
++ size_t *header_size,
++ size_t *payload_remain,
++ WsMask *payload_mask)
+ {
+ unsigned char opcode = 0, fin = 0, has_mask = 0;
+- size_t header_size = 0;
+- uint32_t *payload32;
++ size_t payload_len;
+ WsHeader *header = (WsHeader *)input->buffer;
+- WsMask mask;
+- int i;
+
+ if (input->offset < WS_HEAD_MIN_LEN + 4) {
+ /* header not complete */
+@@ -283,7 +303,7 @@ int vncws_decode_frame(Buffer *input, uint8_t **payload,
+ fin = (header->b0 & 0x80) >> 7;
+ opcode = header->b0 & 0x0f;
+ has_mask = (header->b1 & 0x80) >> 7;
+- *payload_size = header->b1 & 0x7f;
++ payload_len = header->b1 & 0x7f;
+
+ if (opcode == WS_OPCODE_CLOSE) {
+ /* disconnect */
+@@ -300,40 +320,57 @@ int vncws_decode_frame(Buffer *input, uint8_t **payload,
+ return -2;
+ }
+
+- if (*payload_size < 126) {
+- header_size = 6;
+- mask = header->u.m;
+- } else if (*payload_size == 126 && input->offset >= 8) {
+- *payload_size = be16_to_cpu(header->u.s16.l16);
+- header_size = 8;
+- mask = header->u.s16.m16;
+- } else if (*payload_size == 127 && input->offset >= 14) {
+- *payload_size = be64_to_cpu(header->u.s64.l64);
+- header_size = 14;
+- mask = header->u.s64.m64;
++ if (payload_len < 126) {
++ *payload_remain = payload_len;
++ *header_size = 6;
++ *payload_mask = header->u.m;
++ } else if (payload_len == 126 && input->offset >= 8) {
++ *payload_remain = be16_to_cpu(header->u.s16.l16);
++ *header_size = 8;
++ *payload_mask = header->u.s16.m16;
++ } else if (payload_len == 127 && input->offset >= 14) {
++ *payload_remain = be64_to_cpu(header->u.s64.l64);
++ *header_size = 14;
++ *payload_mask = header->u.s64.m64;
+ } else {
+ /* header not complete */
+ return 0;
+ }
+
+- *frame_size = header_size + *payload_size;
++ return 1;
++}
++
++int vncws_decode_frame_payload(Buffer *input,
++ size_t *payload_remain, WsMask *payload_mask,
++ uint8_t **payload, size_t *payload_size)
++{
++ size_t i;
++ uint32_t *payload32;
+
+- if (input->offset < *frame_size) {
+- /* frame not complete */
++ *payload = input->buffer;
++ /* If we aren't at the end of the payload, then drop
++ * off the last bytes, so we're always multiple of 4
++ * for purpose of unmasking, except at end of payload
++ */
++ if (input->offset < *payload_remain) {
++ *payload_size = input->offset - (input->offset % 4);
++ } else {
++ *payload_size = *payload_remain;
++ }
++ if (*payload_size == 0) {
+ return 0;
+ }
+-
+- *payload = input->buffer + header_size;
++ *payload_remain -= *payload_size;
+
+ /* unmask frame */
+ /* process 1 frame (32 bit op) */
+ payload32 = (uint32_t *)(*payload);
+ for (i = 0; i < *payload_size / 4; i++) {
+- payload32[i] ^= mask.u;
++ payload32[i] ^= payload_mask->u;
+ }
+ /* process the remaining bytes (if any) */
+ for (i *= 4; i < *payload_size; i++) {
+- (*payload)[i] ^= mask.c[i % 4];
++ (*payload)[i] ^= payload_mask->c[i % 4];
+ }
+
+ return 1;
+diff --git a/ui/vnc-ws.h b/ui/vnc-ws.h
+index ef229b7..14d4230 100644
+--- a/ui/vnc-ws.h
++++ b/ui/vnc-ws.h
+@@ -83,7 +83,12 @@ long vnc_client_read_ws(VncState *vs);
+ void vncws_process_handshake(VncState *vs, uint8_t *line, size_t size);
+ void vncws_encode_frame(Buffer *output, const void *payload,
+ const size_t payload_size);
+-int vncws_decode_frame(Buffer *input, uint8_t **payload,
+- size_t *payload_size, size_t *frame_size);
++int vncws_decode_frame_header(Buffer *input,
++ size_t *header_size,
++ size_t *payload_remain,
++ WsMask *payload_mask);
++int vncws_decode_frame_payload(Buffer *input,
++ size_t *payload_remain, WsMask *payload_mask,
++ uint8_t **payload, size_t *payload_size);
+
+ #endif /* __QEMU_UI_VNC_WS_H */
+diff --git a/ui/vnc.h b/ui/vnc.h
+index e19ac39..3f7c6a9 100644
+--- a/ui/vnc.h
++++ b/ui/vnc.h
+@@ -306,6 +306,8 @@ struct VncState
+ #ifdef CONFIG_VNC_WS
+ Buffer ws_input;
+ Buffer ws_output;
++ size_t ws_payload_remain;
++ WsMask ws_payload_mask;
+ #endif
+ /* current output mode information */
+ VncWritePixels *write_pixels;
+--
+2.3.5
+
diff --git a/app-emulation/qemu/files/qemu-2.2.1-CVE-2015-1779-2.patch b/app-emulation/qemu/files/qemu-2.2.1-CVE-2015-1779-2.patch
new file mode 100644
index 0000000..c7a8c8b
--- /dev/null
+++ b/app-emulation/qemu/files/qemu-2.2.1-CVE-2015-1779-2.patch
@@ -0,0 +1,58 @@
+From 2cdb5e142fb93e875fa53c52864ef5eb8d5d8b41 Mon Sep 17 00:00:00 2001
+From: "Daniel P. Berrange" <berrange@redhat.com>
+Date: Mon, 23 Mar 2015 22:58:22 +0000
+Subject: [PATCH] CVE-2015-1779: limit size of HTTP headers from websockets
+ clients
+
+The VNC server websockets decoder will read and buffer data from
+websockets clients until it sees the end of the HTTP headers,
+as indicated by \r\n\r\n. In theory this allows a malicious to
+trick QEMU into consuming an arbitrary amount of RAM. In practice,
+because QEMU runs g_strstr_len() across the buffered header data,
+it will spend increasingly long burning CPU time searching for
+the substring match and less & less time reading data. So while
+this does cause arbitrary memory growth, the bigger problem is
+that QEMU will be burning 100% of available CPU time.
+
+A novnc websockets client typically sends headers of around
+512 bytes in length. As such it is reasonable to place a 4096
+byte limit on the amount of data buffered while searching for
+the end of HTTP headers.
+
+Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+---
+ ui/vnc-ws.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/ui/vnc-ws.c b/ui/vnc-ws.c
+index 0b7de4e..62eb97f 100644
+--- a/ui/vnc-ws.c
++++ b/ui/vnc-ws.c
+@@ -81,8 +81,11 @@ void vncws_handshake_read(void *opaque)
+ VncState *vs = opaque;
+ uint8_t *handshake_end;
+ long ret;
+- buffer_reserve(&vs->ws_input, 4096);
+- ret = vnc_client_read_buf(vs, buffer_end(&vs->ws_input), 4096);
++ /* Typical HTTP headers from novnc are 512 bytes, so limiting
++ * total header size to 4096 is easily enough. */
++ size_t want = 4096 - vs->ws_input.offset;
++ buffer_reserve(&vs->ws_input, want);
++ ret = vnc_client_read_buf(vs, buffer_end(&vs->ws_input), want);
+
+ if (!ret) {
+ if (vs->csock == -1) {
+@@ -99,6 +102,9 @@ void vncws_handshake_read(void *opaque)
+ vncws_process_handshake(vs, vs->ws_input.buffer, vs->ws_input.offset);
+ buffer_advance(&vs->ws_input, handshake_end - vs->ws_input.buffer +
+ strlen(WS_HANDSHAKE_END));
++ } else if (vs->ws_input.offset >= 4096) {
++ VNC_DEBUG("End of headers not found in first 4096 bytes\n");
++ vnc_client_error(vs);
+ }
+ }
+
+--
+2.3.5
+
diff --git a/app-emulation/qemu/files/qemu-2.3.0-CVE-2015-3456.patch b/app-emulation/qemu/files/qemu-2.3.0-CVE-2015-3456.patch
new file mode 100644
index 0000000..87697d0
--- /dev/null
+++ b/app-emulation/qemu/files/qemu-2.3.0-CVE-2015-3456.patch
@@ -0,0 +1,86 @@
+https://bugs.gentoo.org/549404
+
+From e907746266721f305d67bc0718795fedee2e824c Mon Sep 17 00:00:00 2001
+From: Petr Matousek <pmatouse@redhat.com>
+Date: Wed, 6 May 2015 09:48:59 +0200
+Subject: [PATCH] fdc: force the fifo access to be in bounds of the allocated buffer
+
+During processing of certain commands such as FD_CMD_READ_ID and
+FD_CMD_DRIVE_SPECIFICATION_COMMAND the fifo memory access could
+get out of bounds leading to memory corruption with values coming
+from the guest.
+
+Fix this by making sure that the index is always bounded by the
+allocated memory.
+
+This is CVE-2015-3456.
+
+Signed-off-by: Petr Matousek <pmatouse@redhat.com>
+Reviewed-by: John Snow <jsnow@redhat.com>
+Signed-off-by: John Snow <jsnow@redhat.com>
+---
+ hw/block/fdc.c | 17 +++++++++++------
+ 1 files changed, 11 insertions(+), 6 deletions(-)
+
+diff --git a/hw/block/fdc.c b/hw/block/fdc.c
+index f72a392..d8a8edd 100644
+--- a/hw/block/fdc.c
++++ b/hw/block/fdc.c
+@@ -1497,7 +1497,7 @@ static uint32_t fdctrl_read_data(FDCtrl *fdctrl)
+ {
+ FDrive *cur_drv;
+ uint32_t retval = 0;
+- int pos;
++ uint32_t pos;
+
+ cur_drv = get_cur_drv(fdctrl);
+ fdctrl->dsr &= ~FD_DSR_PWRDOWN;
+@@ -1506,8 +1506,8 @@ static uint32_t fdctrl_read_data(FDCtrl *fdctrl)
+ return 0;
+ }
+ pos = fdctrl->data_pos;
++ pos %= FD_SECTOR_LEN;
+ if (fdctrl->msr & FD_MSR_NONDMA) {
+- pos %= FD_SECTOR_LEN;
+ if (pos == 0) {
+ if (fdctrl->data_pos != 0)
+ if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) {
+@@ -1852,10 +1852,13 @@ static void fdctrl_handle_option(FDCtrl *fdctrl, int direction)
+ static void fdctrl_handle_drive_specification_command(FDCtrl *fdctrl, int direction)
+ {
+ FDrive *cur_drv = get_cur_drv(fdctrl);
++ uint32_t pos;
+
+- if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x80) {
++ pos = fdctrl->data_pos - 1;
++ pos %= FD_SECTOR_LEN;
++ if (fdctrl->fifo[pos] & 0x80) {
+ /* Command parameters done */
+- if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x40) {
++ if (fdctrl->fifo[pos] & 0x40) {
+ fdctrl->fifo[0] = fdctrl->fifo[1];
+ fdctrl->fifo[2] = 0;
+ fdctrl->fifo[3] = 0;
+@@ -1955,7 +1958,7 @@ static uint8_t command_to_handler[256];
+ static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value)
+ {
+ FDrive *cur_drv;
+- int pos;
++ uint32_t pos;
+
+ /* Reset mode */
+ if (!(fdctrl->dor & FD_DOR_nRESET)) {
+@@ -2004,7 +2007,9 @@ static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value)
+ }
+
+ FLOPPY_DPRINTF("%s: %02x\n", __func__, value);
+- fdctrl->fifo[fdctrl->data_pos++] = value;
++ pos = fdctrl->data_pos++;
++ pos %= FD_SECTOR_LEN;
++ fdctrl->fifo[pos] = value;
+ if (fdctrl->data_pos == fdctrl->data_len) {
+ /* We now have all parameters
+ * and will be able to treat the command
+--
+1.7.0.4
+
diff --git a/app-emulation/qemu/qemu-2.2.0-r99.ebuild b/app-emulation/qemu/qemu-2.2.1-r99.ebuild
similarity index 97%
rename from app-emulation/qemu/qemu-2.2.0-r99.ebuild
rename to app-emulation/qemu/qemu-2.2.1-r99.ebuild
index 8bdbc95..5b8baf1 100644
--- a/app-emulation/qemu/qemu-2.2.0-r99.ebuild
+++ b/app-emulation/qemu/qemu-2.2.1-r99.ebuild
@@ -1,10 +1,10 @@
# Copyright 1999-2015 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
-# $Header: /var/cvsroot/gentoo-x86/app-emulation/qemu/qemu-2.2.0.ebuild,v 1.3 2015/03/12 10:06:51 ago Exp $
+# $Header: /var/cvsroot/gentoo-x86/app-emulation/qemu/qemu-2.2.1-r2.ebuild,v 1.3 2015/05/14 07:09:58 ago Exp $
EAPI=5
-PYTHON_COMPAT=( python{2_6,2_7} )
+PYTHON_COMPAT=( python2_7 )
PYTHON_REQ_USE="ncurses,readline"
inherit eutils flag-o-matic linux-info toolchain-funcs multilib python-r1 \
@@ -20,9 +20,8 @@ if [[ ${PV} = *9999* ]]; then
else
SRC_URI="http://wiki.qemu-project.org/download/${P}.tar.bz2
${BACKPORTS:+
- http://dev.gentoo.org/~cardoe/distfiles/${P}-${BACKPORTS}.tar.xz
- http://dev.gentoo.org/~tamiko/distfiles/${P}-${BACKPORTS}.tar.xz}"
- KEYWORDS="amd64 ~ppc ~x86"
+ http://dev.gentoo.org/~cardoe/distfiles/${P}-${BACKPORTS}.tar.xz}"
+ KEYWORDS="amd64 ~ppc ~ppc64 x86 ~x86-fbsd"
fi
DESCRIPTION="QEMU + Kernel-based Virtual Machine userland tools"
@@ -77,13 +76,13 @@ SOFTMMU_LIB_DEPEND="${COMMON_LIB_DEPEND}
curl? ( >=net-misc/curl-7.15.4[static-libs(+)] )
fdt? ( >=sys-apps/dtc-1.4.0[static-libs(+)] )
glusterfs? ( >=sys-cluster/glusterfs-3.4.0[static-libs(+)] )
- infiniband? ( sys-infiniband/librdmacm[static-libs(+)] )
- jpeg? ( virtual/jpeg[static-libs(+)] )
+ infiniband? ( sys-infiniband/librdmacm:=[static-libs(+)] )
+ jpeg? ( virtual/jpeg:=[static-libs(+)] )
lzo? ( dev-libs/lzo:2[static-libs(+)] )
ncurses? ( sys-libs/ncurses[static-libs(+)] )
nfs? ( >=net-fs/libnfs-1.9.3[static-libs(+)] )
numa? ( sys-process/numactl[static-libs(+)] )
- png? ( media-libs/libpng[static-libs(+)] )
+ png? ( media-libs/libpng:0=[static-libs(+)] )
rbd? ( sys-cluster/ceph[static-libs(+)] )
sasl? ( dev-libs/cyrus-sasl[static-libs(+)] )
sdl? ( >=media-libs/libsdl-1.2.11[static-libs(+)] )
@@ -246,6 +245,7 @@ pkg_pretend() {
pkg_setup() {
enewgroup kvm 78
+ python_setup
}
src_prepare() {
@@ -258,6 +258,9 @@ src_prepare() {
use nls || rm -f po/*.po
epatch "${FILESDIR}"/qemu-1.7.0-cflags.patch
+ epatch "${FILESDIR}"/${P}-CVE-2015-1779-1.patch #544328
+ epatch "${FILESDIR}"/${P}-CVE-2015-1779-2.patch #544328
+ epatch "${FILESDIR}"/${PN}-2.3.0-CVE-2015-3456.patch #549404
# Patching for musl
epatch "${FILESDIR}"/${PN}-2.0.0-F_SHLCK-and-F_EXLCK.patch
@@ -399,7 +402,7 @@ qemu_src_configure() {
gcc-specs-pie && conf_opts+=( --enable-pie )
fi
- einfo "./configure ${conf_opts[*]}"
+ einfo "../configure ${conf_opts[*]}"
cd "${builddir}"
../configure "${conf_opts[@]}" || die "configure failed"
next reply other threads:[~2015-06-08 12:26 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-06-08 12:26 Anthony G. Basile [this message]
-- strict thread matches above, loose matches on Subject: below --
2014-11-18 21:57 [gentoo-commits] proj/hardened-dev:musl commit in: app-emulation/qemu/files/, app-emulation/qemu/ Anthony G. Basile
2014-10-10 18:20 Anthony G. Basile
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1433766459.dd8f541bb891cc198527837f2eedb81594efb1f3.blueness@gentoo \
--to=blueness@gentoo.org \
--cc=gentoo-commits@lists.gentoo.org \
--cc=gentoo-dev@lists.gentoo.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox