CVE-2016-2538: Integer overflow in usb module (bz #1305815)
CVE-2016-2841: ne2000: infinite loop (bz #1304047) CVE-2016-2857: net: out of bounds read (bz #1309564) CVE-2016-2392: usb: null pointer dereference (bz #1307115) Fix external snapshot any more after active committing (bz #1300209)
This commit is contained in:
parent
3fa9b818a6
commit
d76f65307f
61
0103-usb-check-RNDIS-message-length.patch
Normal file
61
0103-usb-check-RNDIS-message-length.patch
Normal file
@ -0,0 +1,61 @@
|
||||
From: Prasad J Pandit <pjp@fedoraproject.org>
|
||||
Date: Wed, 17 Feb 2016 00:23:40 +0530
|
||||
Subject: [PATCH] usb: check RNDIS message length
|
||||
|
||||
When processing remote NDIS control message packets, the USB Net
|
||||
device emulator uses a fixed length(4096) data buffer. The incoming
|
||||
packet length could exceed this limit. Add a check to avoid it.
|
||||
|
||||
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
|
||||
Message-id: 1455648821-17340-2-git-send-email-ppandit@redhat.com
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
(cherry picked from commit 64c9bc181fc78275596649f591302d72df2d3071)
|
||||
---
|
||||
hw/usb/core.c | 18 +++++++++---------
|
||||
1 file changed, 9 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/hw/usb/core.c b/hw/usb/core.c
|
||||
index d0025db..7f46370 100644
|
||||
--- a/hw/usb/core.c
|
||||
+++ b/hw/usb/core.c
|
||||
@@ -128,9 +128,16 @@ static void do_token_setup(USBDevice *s, USBPacket *p)
|
||||
}
|
||||
|
||||
usb_packet_copy(p, s->setup_buf, p->iov.size);
|
||||
+ s->setup_index = 0;
|
||||
p->actual_length = 0;
|
||||
s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6];
|
||||
- s->setup_index = 0;
|
||||
+ if (s->setup_len > sizeof(s->data_buf)) {
|
||||
+ fprintf(stderr,
|
||||
+ "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
|
||||
+ s->setup_len, sizeof(s->data_buf));
|
||||
+ p->status = USB_RET_STALL;
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
request = (s->setup_buf[0] << 8) | s->setup_buf[1];
|
||||
value = (s->setup_buf[3] << 8) | s->setup_buf[2];
|
||||
@@ -151,13 +158,6 @@ static void do_token_setup(USBDevice *s, USBPacket *p)
|
||||
}
|
||||
s->setup_state = SETUP_STATE_DATA;
|
||||
} else {
|
||||
- if (s->setup_len > sizeof(s->data_buf)) {
|
||||
- fprintf(stderr,
|
||||
- "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
|
||||
- s->setup_len, sizeof(s->data_buf));
|
||||
- p->status = USB_RET_STALL;
|
||||
- return;
|
||||
- }
|
||||
if (s->setup_len == 0)
|
||||
s->setup_state = SETUP_STATE_ACK;
|
||||
else
|
||||
@@ -176,7 +176,7 @@ static void do_token_in(USBDevice *s, USBPacket *p)
|
||||
request = (s->setup_buf[0] << 8) | s->setup_buf[1];
|
||||
value = (s->setup_buf[3] << 8) | s->setup_buf[2];
|
||||
index = (s->setup_buf[5] << 8) | s->setup_buf[4];
|
||||
-
|
||||
+
|
||||
switch(s->setup_state) {
|
||||
case SETUP_STATE_ACK:
|
||||
if (!(s->setup_buf[0] & USB_DIR_IN)) {
|
56
0104-usb-check-RNDIS-buffer-offsets-length.patch
Normal file
56
0104-usb-check-RNDIS-buffer-offsets-length.patch
Normal file
@ -0,0 +1,56 @@
|
||||
From: Prasad J Pandit <pjp@fedoraproject.org>
|
||||
Date: Wed, 17 Feb 2016 00:23:41 +0530
|
||||
Subject: [PATCH] usb: check RNDIS buffer offsets & length
|
||||
|
||||
When processing remote NDIS control message packets,
|
||||
the USB Net device emulator uses a fixed length(4096) data buffer.
|
||||
The incoming informationBufferOffset & Length combination could
|
||||
overflow and cross that range. Check control message buffer
|
||||
offsets and length to avoid it.
|
||||
|
||||
Reported-by: Qinghao Tang <luodalongde@gmail.com>
|
||||
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
|
||||
Message-id: 1455648821-17340-3-git-send-email-ppandit@redhat.com
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
(cherry picked from commit fe3c546c5ff2a6210f9a4d8561cc64051ca8603e)
|
||||
---
|
||||
hw/usb/dev-network.c | 9 ++++++---
|
||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
|
||||
index 7800cee..ba3c7a7 100644
|
||||
--- a/hw/usb/dev-network.c
|
||||
+++ b/hw/usb/dev-network.c
|
||||
@@ -914,8 +914,9 @@ static int rndis_query_response(USBNetState *s,
|
||||
|
||||
bufoffs = le32_to_cpu(buf->InformationBufferOffset) + 8;
|
||||
buflen = le32_to_cpu(buf->InformationBufferLength);
|
||||
- if (bufoffs + buflen > length)
|
||||
+ if (buflen > length || bufoffs >= length || bufoffs + buflen > length) {
|
||||
return USB_RET_STALL;
|
||||
+ }
|
||||
|
||||
infobuflen = ndis_query(s, le32_to_cpu(buf->OID),
|
||||
bufoffs + (uint8_t *) buf, buflen, infobuf,
|
||||
@@ -960,8 +961,9 @@ static int rndis_set_response(USBNetState *s,
|
||||
|
||||
bufoffs = le32_to_cpu(buf->InformationBufferOffset) + 8;
|
||||
buflen = le32_to_cpu(buf->InformationBufferLength);
|
||||
- if (bufoffs + buflen > length)
|
||||
+ if (buflen > length || bufoffs >= length || bufoffs + buflen > length) {
|
||||
return USB_RET_STALL;
|
||||
+ }
|
||||
|
||||
ret = ndis_set(s, le32_to_cpu(buf->OID),
|
||||
bufoffs + (uint8_t *) buf, buflen);
|
||||
@@ -1211,8 +1213,9 @@ static void usb_net_handle_dataout(USBNetState *s, USBPacket *p)
|
||||
if (le32_to_cpu(msg->MessageType) == RNDIS_PACKET_MSG) {
|
||||
uint32_t offs = 8 + le32_to_cpu(msg->DataOffset);
|
||||
uint32_t size = le32_to_cpu(msg->DataLength);
|
||||
- if (offs + size <= len)
|
||||
+ if (offs < len && size < len && offs + size <= len) {
|
||||
qemu_send_packet(qemu_get_queue(s->nic), s->out_buf + offs, size);
|
||||
+ }
|
||||
}
|
||||
s->out_ptr -= len;
|
||||
memmove(s->out_buf, &s->out_buf[len], s->out_ptr);
|
34
0105-net-ne2000-check-ring-buffer-control-registers.patch
Normal file
34
0105-net-ne2000-check-ring-buffer-control-registers.patch
Normal file
@ -0,0 +1,34 @@
|
||||
From: Prasad J Pandit <pjp@fedoraproject.org>
|
||||
Date: Wed, 24 Feb 2016 11:41:33 +0530
|
||||
Subject: [PATCH] net: ne2000: check ring buffer control registers
|
||||
|
||||
Ne2000 NIC uses ring buffer of NE2000_MEM_SIZE(49152)
|
||||
bytes to process network packets. Registers PSTART & PSTOP
|
||||
define ring buffer size & location. Setting these registers
|
||||
to invalid values could lead to infinite loop or OOB r/w
|
||||
access issues. Add check to avoid it.
|
||||
|
||||
Reported-by: Yang Hongke <yanghongke@huawei.com>
|
||||
Tested-by: Yang Hongke <yanghongke@huawei.com>
|
||||
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
|
||||
Signed-off-by: Jason Wang <jasowang@redhat.com>
|
||||
(cherry picked from commit 415ab35a441eca767d033a2702223e785b9d5190)
|
||||
---
|
||||
hw/net/ne2000.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c
|
||||
index a3dffff..995115e 100644
|
||||
--- a/hw/net/ne2000.c
|
||||
+++ b/hw/net/ne2000.c
|
||||
@@ -154,6 +154,10 @@ static int ne2000_buffer_full(NE2000State *s)
|
||||
{
|
||||
int avail, index, boundary;
|
||||
|
||||
+ if (s->stop <= s->start) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
index = s->curpag << 8;
|
||||
boundary = s->boundary << 8;
|
||||
if (index < boundary)
|
44
0106-net-check-packet-payload-length.patch
Normal file
44
0106-net-check-packet-payload-length.patch
Normal file
@ -0,0 +1,44 @@
|
||||
From: Prasad J Pandit <pjp@fedoraproject.org>
|
||||
Date: Wed, 2 Mar 2016 17:29:58 +0530
|
||||
Subject: [PATCH] net: check packet payload length
|
||||
|
||||
While computing IP checksum, 'net_checksum_calculate' reads
|
||||
payload length from the packet. It could exceed the given 'data'
|
||||
buffer size. Add a check to avoid it.
|
||||
|
||||
Reported-by: Liu Ling <liuling-it@360.cn>
|
||||
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
|
||||
Signed-off-by: Jason Wang <jasowang@redhat.com>
|
||||
(cherry picked from commit 362786f14a753d8a5256ef97d7c10ed576d6572b)
|
||||
---
|
||||
net/checksum.c | 10 ++++++++--
|
||||
1 file changed, 8 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/net/checksum.c b/net/checksum.c
|
||||
index 14c0855..0942437 100644
|
||||
--- a/net/checksum.c
|
||||
+++ b/net/checksum.c
|
||||
@@ -59,6 +59,11 @@ void net_checksum_calculate(uint8_t *data, int length)
|
||||
int hlen, plen, proto, csum_offset;
|
||||
uint16_t csum;
|
||||
|
||||
+ /* Ensure data has complete L2 & L3 headers. */
|
||||
+ if (length < 14 + 20) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if ((data[14] & 0xf0) != 0x40)
|
||||
return; /* not IPv4 */
|
||||
hlen = (data[14] & 0x0f) * 4;
|
||||
@@ -76,8 +81,9 @@ void net_checksum_calculate(uint8_t *data, int length)
|
||||
return;
|
||||
}
|
||||
|
||||
- if (plen < csum_offset+2)
|
||||
- return;
|
||||
+ if (plen < csum_offset + 2 || 14 + hlen + plen > length) {
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
data[14+hlen+csum_offset] = 0;
|
||||
data[14+hlen+csum_offset+1] = 0;
|
32
0107-usb-check-USB-configuration-descriptor-object.patch
Normal file
32
0107-usb-check-USB-configuration-descriptor-object.patch
Normal file
@ -0,0 +1,32 @@
|
||||
From: Prasad J Pandit <pjp@fedoraproject.org>
|
||||
Date: Thu, 11 Feb 2016 16:31:20 +0530
|
||||
Subject: [PATCH] usb: check USB configuration descriptor object
|
||||
|
||||
When processing remote NDIS control message packets, the USB Net
|
||||
device emulator checks to see if the USB configuration descriptor
|
||||
object is of RNDIS type(2). But it does not check if it is null,
|
||||
which leads to a null dereference error. Add check to avoid it.
|
||||
|
||||
Reported-by: Qinghao Tang <luodalongde@gmail.com>
|
||||
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
|
||||
Message-id: 1455188480-14688-1-git-send-email-ppandit@redhat.com
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
(cherry picked from commit 80eecda8e5d09c442c24307f340840a5b70ea3b9)
|
||||
---
|
||||
hw/usb/dev-network.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
|
||||
index ba3c7a7..180adce 100644
|
||||
--- a/hw/usb/dev-network.c
|
||||
+++ b/hw/usb/dev-network.c
|
||||
@@ -653,7 +653,8 @@ typedef struct USBNetState {
|
||||
|
||||
static int is_rndis(USBNetState *s)
|
||||
{
|
||||
- return s->dev.config->bConfigurationValue == DEV_RNDIS_CONFIG_VALUE;
|
||||
+ return s->dev.config ?
|
||||
+ s->dev.config->bConfigurationValue == DEV_RNDIS_CONFIG_VALUE : 0;
|
||||
}
|
||||
|
||||
static int ndis_query(USBNetState *s, uint32_t oid,
|
114
0108-block-set-device_list.tqe_prev-to-NULL-on-BDS-remova.patch
Normal file
114
0108-block-set-device_list.tqe_prev-to-NULL-on-BDS-remova.patch
Normal file
@ -0,0 +1,114 @@
|
||||
From: Jeff Cody <jcody@redhat.com>
|
||||
Date: Mon, 1 Feb 2016 20:33:10 -0500
|
||||
Subject: [PATCH] block: set device_list.tqe_prev to NULL on BDS removal
|
||||
|
||||
This fixes a regression introduced with commit 3f09bfbc7. Multiple
|
||||
bugs arise in conjunction with live snapshots and mirroring operations
|
||||
(which include active layer commit).
|
||||
|
||||
After a live snapshot occurs, the active layer and the base layer both
|
||||
have a non-NULL tqe_prev field in the device_list, although the base
|
||||
node's tqe_prev field points to a NULL entry. This non-NULL tqe_prev
|
||||
field occurs after the bdrv_append() in the external snapshot calls
|
||||
change_parent_backing_link().
|
||||
|
||||
In change_parent_backing_link(), when the previous active layer is
|
||||
removed from device_list, the device_list.tqe_prev pointer is not
|
||||
set to NULL.
|
||||
|
||||
The operating scheme in the block layer is to indicate that a BDS belongs
|
||||
in the bdrv_states device_list iff the device_list.tqe_prev pointer
|
||||
is non-NULL.
|
||||
|
||||
This patch does two things:
|
||||
|
||||
1.) Introduces a new block layer helper bdrv_device_remove() to remove a
|
||||
BDS from the device_list, and
|
||||
2.) uses that new API, which also fixes the regression once used in
|
||||
change_parent_backing_link().
|
||||
|
||||
Signed-off-by: Jeff Cody <jcody@redhat.com>
|
||||
Message-id: 0cd51e11c0666c04ddb7c05293fe94afeb551e89.1454376655.git.jcody@redhat.com
|
||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
||||
(cherry picked from commit f8aa905a4fec89863c82de4186352447d851871e)
|
||||
---
|
||||
block.c | 24 ++++++++++++++----------
|
||||
blockdev.c | 3 +--
|
||||
include/block/block.h | 1 +
|
||||
3 files changed, 16 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/block.c b/block.c
|
||||
index 3a7324b..3c172dd 100644
|
||||
--- a/block.c
|
||||
+++ b/block.c
|
||||
@@ -1976,21 +1976,25 @@ void bdrv_close_all(void)
|
||||
}
|
||||
}
|
||||
|
||||
+/* Note that bs->device_list.tqe_prev is initially null,
|
||||
+ * and gets set to non-null by QTAILQ_INSERT_TAIL(). Establish
|
||||
+ * the useful invariant "bs in bdrv_states iff bs->tqe_prev" by
|
||||
+ * resetting it to null on remove. */
|
||||
+void bdrv_device_remove(BlockDriverState *bs)
|
||||
+{
|
||||
+ QTAILQ_REMOVE(&bdrv_states, bs, device_list);
|
||||
+ bs->device_list.tqe_prev = NULL;
|
||||
+}
|
||||
+
|
||||
/* make a BlockDriverState anonymous by removing from bdrv_state and
|
||||
* graph_bdrv_state list.
|
||||
Also, NULL terminate the device_name to prevent double remove */
|
||||
void bdrv_make_anon(BlockDriverState *bs)
|
||||
{
|
||||
- /*
|
||||
- * Take care to remove bs from bdrv_states only when it's actually
|
||||
- * in it. Note that bs->device_list.tqe_prev is initially null,
|
||||
- * and gets set to non-null by QTAILQ_INSERT_TAIL(). Establish
|
||||
- * the useful invariant "bs in bdrv_states iff bs->tqe_prev" by
|
||||
- * resetting it to null on remove.
|
||||
- */
|
||||
+ /* Take care to remove bs from bdrv_states only when it's actually
|
||||
+ * in it. */
|
||||
if (bs->device_list.tqe_prev) {
|
||||
- QTAILQ_REMOVE(&bdrv_states, bs, device_list);
|
||||
- bs->device_list.tqe_prev = NULL;
|
||||
+ bdrv_device_remove(bs);
|
||||
}
|
||||
if (bs->node_name[0] != '\0') {
|
||||
QTAILQ_REMOVE(&graph_bdrv_states, bs, node_list);
|
||||
@@ -2031,7 +2035,7 @@ static void change_parent_backing_link(BlockDriverState *from,
|
||||
if (!to->device_list.tqe_prev) {
|
||||
QTAILQ_INSERT_BEFORE(from, to, device_list);
|
||||
}
|
||||
- QTAILQ_REMOVE(&bdrv_states, from, device_list);
|
||||
+ bdrv_device_remove(from);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/blockdev.c b/blockdev.c
|
||||
index 80932e8..c236126 100644
|
||||
--- a/blockdev.c
|
||||
+++ b/blockdev.c
|
||||
@@ -2384,8 +2384,7 @@ void qmp_x_blockdev_remove_medium(const char *device, Error **errp)
|
||||
|
||||
/* This follows the convention established by bdrv_make_anon() */
|
||||
if (bs->device_list.tqe_prev) {
|
||||
- QTAILQ_REMOVE(&bdrv_states, bs, device_list);
|
||||
- bs->device_list.tqe_prev = NULL;
|
||||
+ bdrv_device_remove(bs);
|
||||
}
|
||||
|
||||
blk_remove_bs(blk);
|
||||
diff --git a/include/block/block.h b/include/block/block.h
|
||||
index 3477328..d83d420 100644
|
||||
--- a/include/block/block.h
|
||||
+++ b/include/block/block.h
|
||||
@@ -196,6 +196,7 @@ int bdrv_create(BlockDriver *drv, const char* filename,
|
||||
int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp);
|
||||
BlockDriverState *bdrv_new_root(void);
|
||||
BlockDriverState *bdrv_new(void);
|
||||
+void bdrv_device_remove(BlockDriverState *bs);
|
||||
void bdrv_make_anon(BlockDriverState *bs);
|
||||
void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old);
|
||||
void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top);
|
20
qemu.spec
20
qemu.spec
@ -42,7 +42,7 @@
|
||||
Summary: QEMU is a FAST! processor emulator
|
||||
Name: qemu
|
||||
Version: 2.5.0
|
||||
Release: 9%{?dist}
|
||||
Release: 10%{?dist}
|
||||
Epoch: 2
|
||||
License: GPLv2+ and LGPLv2+ and BSD
|
||||
Group: Development/Tools
|
||||
@ -110,6 +110,17 @@ Patch0019: 0019-target-ppc-kvm-fix-floating-point-registers-sync-on-.patch
|
||||
# Fix qemu-img vmdk images to work with VMware (bz #1299185)
|
||||
Patch0101: 0101-vmdk-Create-streamOptimized-as-version-3.patch
|
||||
Patch0102: 0102-vmdk-Fix-converting-to-streamOptimized.patch
|
||||
# CVE-2016-2538: Integer overflow in usb module (bz #1305815)
|
||||
Patch0103: 0103-usb-check-RNDIS-message-length.patch
|
||||
Patch0104: 0104-usb-check-RNDIS-buffer-offsets-length.patch
|
||||
# CVE-2016-2841: ne2000: infinite loop (bz #1304047)
|
||||
Patch0105: 0105-net-ne2000-check-ring-buffer-control-registers.patch
|
||||
# CVE-2016-2857: net: out of bounds read (bz #1309564)
|
||||
Patch0106: 0106-net-check-packet-payload-length.patch
|
||||
# CVE-2016-2392: usb: null pointer dereference (bz #1307115)
|
||||
Patch0107: 0107-usb-check-USB-configuration-descriptor-object.patch
|
||||
# Fix external snapshot any more after active committing (bz #1300209)
|
||||
Patch0108: 0108-block-set-device_list.tqe_prev-to-NULL-on-BDS-remova.patch
|
||||
|
||||
BuildRequires: SDL2-devel
|
||||
BuildRequires: zlib-devel
|
||||
@ -1203,6 +1214,13 @@ getent passwd qemu >/dev/null || \
|
||||
|
||||
|
||||
%changelog
|
||||
* Thu Mar 17 2016 Cole Robinson <crobinso@redhat.com> - 2:2.5.0-10
|
||||
- CVE-2016-2538: Integer overflow in usb module (bz #1305815)
|
||||
- CVE-2016-2841: ne2000: infinite loop (bz #1304047)
|
||||
- CVE-2016-2857: net: out of bounds read (bz #1309564)
|
||||
- CVE-2016-2392: usb: null pointer dereference (bz #1307115)
|
||||
- Fix external snapshot any more after active committing (bz #1300209)
|
||||
|
||||
* Wed Mar 9 2016 Peter Robinson <pbrobinson@fedoraproject.org> 2:2.5.0-9
|
||||
- Rebuild for tcmalloc ifunc issues on non x86 arches (see rhbz 1312462)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user