Fixes for some security issues

CVE-2015-5154: ide: Check array bounds before writing to io_buffer (bz #1247143)
CVE-2015-3214: i8254: fix out-of-bounds memory access in pit_ioport_read() (bz #1243729)
CVE-2015-5154: pcnet: force the buffer access to be in bounds during tx (bz #1230538)
This commit is contained in:
Lubomir Rintel 2015-11-02 11:10:45 +01:00
parent 997d06a014
commit 5f7cb4c26f
5 changed files with 300 additions and 2 deletions

View File

@ -0,0 +1,79 @@
From fcb9de761d54ec4aaa44027a5ce95f7b3e36ebd9 Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Sun, 26 Jul 2015 23:42:53 -0400
Subject: [PATCH 1/4] ide: Check array bounds before writing to io_buffer
(CVE-2015-5154)
If the end_transfer_func of a command is called because enough data has
been read or written for the current PIO transfer, and it fails to
correctly call the command completion functions, the DRQ bit in the
status register and s->end_transfer_func may remain set. This allows the
guest to access further bytes in s->io_buffer beyond s->data_end, and
eventually overflowing the io_buffer.
One case where this currently happens is emulation of the ATAPI command
START STOP UNIT.
This patch fixes the problem by adding explicit array bounds checks
before accessing the buffer instead of relying on end_transfer_func to
function correctly.
Cc: qemu-stable@nongnu.org
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
(cherry picked from commit d2ff85854512574e7209f295e87b0835d5b032c6)
---
hw/ide/core.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/hw/ide/core.c b/hw/ide/core.c
index c943a4d..e2ad6ee 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1901,6 +1901,10 @@ void ide_data_writew(void *opaque, uint32_t addr, uint32_t val)
}
p = s->data_ptr;
+ if (p + 2 > s->data_end) {
+ return;
+ }
+
*(uint16_t *)p = le16_to_cpu(val);
p += 2;
s->data_ptr = p;
@@ -1922,6 +1926,10 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr)
}
p = s->data_ptr;
+ if (p + 2 > s->data_end) {
+ return 0;
+ }
+
ret = cpu_to_le16(*(uint16_t *)p);
p += 2;
s->data_ptr = p;
@@ -1943,6 +1951,10 @@ void ide_data_writel(void *opaque, uint32_t addr, uint32_t val)
}
p = s->data_ptr;
+ if (p + 4 > s->data_end) {
+ return;
+ }
+
*(uint32_t *)p = le32_to_cpu(val);
p += 4;
s->data_ptr = p;
@@ -1964,6 +1976,10 @@ uint32_t ide_data_readl(void *opaque, uint32_t addr)
}
p = s->data_ptr;
+ if (p + 4 > s->data_end) {
+ return 0;
+ }
+
ret = cpu_to_le32(*(uint32_t *)p);
p += 4;
s->data_ptr = p;
--
2.5.0

View File

@ -0,0 +1,45 @@
From 1ed2665d9163d25cce12a1d8a764b939b2593c6e Mon Sep 17 00:00:00 2001
From: Petr Matousek <pmatouse@redhat.com>
Date: Wed, 17 Jun 2015 12:46:11 +0200
Subject: [PATCH 2/4] i8254: fix out-of-bounds memory access in
pit_ioport_read()
Due converting PIO to the new memory read/write api we no longer provide
separate I/O region lenghts for read and write operations. As a result,
reading from PIT Mode/Command register will end with accessing
pit->channels with invalid index.
Fix this by ignoring read from the Mode/Command register.
This is CVE-2015-3214.
Reported-by: Matt Tait <matttait@google.com>
Fixes: 0505bcdec8228d8de39ab1a02644e71999e7c052
Cc: qemu-stable@nongnu.org
Signed-off-by: Petr Matousek <pmatouse@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit d4862a87e31a51de9eb260f25c9e99a75efe3235)
---
hw/timer/i8254.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/hw/timer/i8254.c b/hw/timer/i8254.c
index 28152d8..a5dd681 100644
--- a/hw/timer/i8254.c
+++ b/hw/timer/i8254.c
@@ -196,6 +196,12 @@ static uint64_t pit_ioport_read(void *opaque, hwaddr addr,
PITChannelState *s;
addr &= 3;
+
+ if (addr == 3) {
+ /* Mode/Command register is write only, read is ignored */
+ return 0;
+ }
+
s = &pit->channels[addr];
if (s->status_latched) {
s->status_latched = 0;
--
2.5.0

View File

@ -0,0 +1,100 @@
From c2c087239b676b7dcb75f74ed8509bd0d286ee1d Mon Sep 17 00:00:00 2001
From: Gonglei <arei.gonglei@huawei.com>
Date: Thu, 20 Nov 2014 19:35:02 +0800
Subject: [PATCH 3/4] pcnet: fix Negative array index read
s->xmit_pos maybe assigned to a negative value (-1),
but in this branch variable s->xmit_pos as an index to
array s->buffer. Let's add a check for s->xmit_pos.
Signed-off-by: Gonglei <arei.gonglei@huawei.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 7b50d00911ddd6d56a766ac5671e47304c20a21b)
---
hw/net/pcnet.c | 55 ++++++++++++++++++++++++++++++-------------------------
1 file changed, 30 insertions(+), 25 deletions(-)
diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c
index 7cb47b3..07069d7 100644
--- a/hw/net/pcnet.c
+++ b/hw/net/pcnet.c
@@ -1213,7 +1213,7 @@ static void pcnet_transmit(PCNetState *s)
hwaddr xmit_cxda = 0;
int count = CSR_XMTRL(s)-1;
int add_crc = 0;
-
+ int bcnt;
s->xmit_pos = -1;
if (!CSR_TXON(s)) {
@@ -1248,35 +1248,40 @@ static void pcnet_transmit(PCNetState *s)
s->xmit_pos = -1;
goto txdone;
}
+
+ if (s->xmit_pos < 0) {
+ goto txdone;
+ }
+
+ bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
+ s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
+ s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
+ s->xmit_pos += bcnt;
+
if (!GET_FIELD(tmd.status, TMDS, ENP)) {
- int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
- s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
- s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
- s->xmit_pos += bcnt;
- } else if (s->xmit_pos >= 0) {
- int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
- s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
- s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
- s->xmit_pos += bcnt;
+ goto txdone;
+ }
+
#ifdef PCNET_DEBUG
- printf("pcnet_transmit size=%d\n", s->xmit_pos);
+ printf("pcnet_transmit size=%d\n", s->xmit_pos);
#endif
- if (CSR_LOOP(s)) {
- if (BCR_SWSTYLE(s) == 1)
- add_crc = !GET_FIELD(tmd.status, TMDS, NOFCS);
- s->looptest = add_crc ? PCNET_LOOPTEST_CRC : PCNET_LOOPTEST_NOCRC;
- pcnet_receive(qemu_get_queue(s->nic), s->buffer, s->xmit_pos);
- s->looptest = 0;
- } else
- if (s->nic)
- qemu_send_packet(qemu_get_queue(s->nic), s->buffer,
- s->xmit_pos);
-
- s->csr[0] &= ~0x0008; /* clear TDMD */
- s->csr[4] |= 0x0004; /* set TXSTRT */
- s->xmit_pos = -1;
+ if (CSR_LOOP(s)) {
+ if (BCR_SWSTYLE(s) == 1)
+ add_crc = !GET_FIELD(tmd.status, TMDS, NOFCS);
+ s->looptest = add_crc ? PCNET_LOOPTEST_CRC : PCNET_LOOPTEST_NOCRC;
+ pcnet_receive(qemu_get_queue(s->nic), s->buffer, s->xmit_pos);
+ s->looptest = 0;
+ } else {
+ if (s->nic) {
+ qemu_send_packet(qemu_get_queue(s->nic), s->buffer,
+ s->xmit_pos);
+ }
}
+ s->csr[0] &= ~0x0008; /* clear TDMD */
+ s->csr[4] |= 0x0004; /* set TXSTRT */
+ s->xmit_pos = -1;
+
txdone:
SET_FIELD(&tmd.status, TMDS, OWN, 0);
TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
--
2.5.0

View File

@ -0,0 +1,50 @@
From d913b8e2e9a6480bbefba2abc3e8f55bd9d1f1a7 Mon Sep 17 00:00:00 2001
From: Petr Matousek <pmatouse@redhat.com>
Date: Sun, 24 May 2015 10:53:44 +0200
Subject: [PATCH 4/4] pcnet: force the buffer access to be in bounds during tx
4096 is the maximum length per TMD and it is also currently the size of
the relay buffer pcnet driver uses for sending the packet data to QEMU
for further processing. With packet spanning multiple TMDs it can
happen that the overall packet size will be bigger than sizeof(buffer),
which results in memory corruption.
Fix this by only allowing to queue maximum sizeof(buffer) bytes.
This is CVE-2015-3209.
[Fixed 3-space indentation to QEMU's 4-space coding standard.
--Stefan]
Signed-off-by: Petr Matousek <pmatouse@redhat.com>
Reported-by: Matt Tait <matttait@google.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 9f7c594c006289ad41169b854d70f5da6e400a2a)
---
hw/net/pcnet.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c
index 07069d7..a577daf 100644
--- a/hw/net/pcnet.c
+++ b/hw/net/pcnet.c
@@ -1254,6 +1254,14 @@ static void pcnet_transmit(PCNetState *s)
}
bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
+
+ /* if multi-tmd packet outsizes s->buffer then skip it silently.
+ Note: this is not what real hw does */
+ if (s->xmit_pos + bcnt > sizeof(s->buffer)) {
+ s->xmit_pos = -1;
+ goto txdone;
+ }
+
s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
s->xmit_pos += bcnt;
--
2.5.0

View File

@ -155,7 +155,7 @@
Summary: QEMU is a FAST! processor emulator
Name: qemu
Version: 2.0.0
Release: 1%{?dist}.5
Release: 1%{?dist}.6
Epoch: 2
License: GPLv2+ and LGPLv2+ and BSD
Group: Development/Tools
@ -199,12 +199,21 @@ Source12: bridge.conf
Source13: qemu-kvm.sh
# Change gtk quit accelerator to ctrl+shift+q (bz #1062393)
# Patches queued for 2.1
Patch0001: 0001-Change-gtk-quit-accelerator-to-ctrl-shift-q-bz-10623.patch
# CVE-2015-3456: fdc: out-of-bounds fifo buffer memory access # (bz #1221152)
Patch0002: 0002-fdc-force-the-fifo-access-to-be-in-bounds-of-the-all.patch
# CVE-2015-5154: ide: Check array bounds before writing to io_buffer (bz #1247143)
Patch0003: 0001-ide-Check-array-bounds-before-writing-to-io_buffer-C.patch
# CVE-2015-3214: i8254: fix out-of-bounds memory access in pit_ioport_read() (bz #1243729)
Patch0004: 0002-i8254-fix-out-of-bounds-memory-access-in-pit_ioport_.patch
# CVE-2015-5154: pcnet: force the buffer access to be in bounds during tx (bz #1230538)
Patch0005: 0003-pcnet-fix-Negative-array-index-read.patch
Patch0006: 0004-pcnet-force-the-buffer-access-to-be-in-bounds-during.patch
# EPEL specific patches
Patch6661: 0001-pxe-always-use-non-efi-roms.patch
@ -730,6 +739,16 @@ CAC emulation development files.
# CVE-2015-3456: fdc: out-of-bounds fifo buffer memory access # (bz #1221152)
%patch0002 -p1
# CVE-2015-5154: ide: Check array bounds before writing to io_buffer (bz #1247143)
%patch0003 -p1
# CVE-2015-3214: i8254: fix out-of-bounds memory access in pit_ioport_read() (bz #1243729)
%patch0004 -p1
# CVE-2015-5154: pcnet: force the buffer access to be in bounds during tx (bz #1230538)
%patch0005 -p1
%patch0006 -p1
# EPEL patches
%patch6661 -p1
@ -1514,6 +1533,11 @@ getent passwd qemu >/dev/null || \
%endif
%changelog
* Mon Nov 02 2015 Lubomir Rintel <lkundrak@v3.sk> - 2:2.0.0-1.6
- CVE-2015-5154: ide: Check array bounds before writing to io_buffer (bz #1247143)
- CVE-2015-3214: i8254: fix out-of-bounds memory access in pit_ioport_read() (bz #1243729)
- CVE-2015-5154: pcnet: force the buffer access to be in bounds during tx (bz #1230538)
* Mon May 25 2015 Lubomir Rintel <lkundrak@v3.sk> - 2:2.0.0-1.5
- CVE-2015-3456: fdc: out-of-bounds fifo buffer memory access (bz #1221152)