From 5f7cb4c26f1572c3d98a4608fd37361d55acb327 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 2 Nov 2015 11:10:45 +0100 Subject: [PATCH] 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) --- ...bounds-before-writing-to-io_buffer-C.patch | 79 ++++++++++++++ ...-bounds-memory-access-in-pit_ioport_.patch | 45 ++++++++ ...-pcnet-fix-Negative-array-index-read.patch | 100 ++++++++++++++++++ ...buffer-access-to-be-in-bounds-during.patch | 50 +++++++++ qemu.spec | 28 ++++- 5 files changed, 300 insertions(+), 2 deletions(-) create mode 100644 0001-ide-Check-array-bounds-before-writing-to-io_buffer-C.patch create mode 100644 0002-i8254-fix-out-of-bounds-memory-access-in-pit_ioport_.patch create mode 100644 0003-pcnet-fix-Negative-array-index-read.patch create mode 100644 0004-pcnet-force-the-buffer-access-to-be-in-bounds-during.patch diff --git a/0001-ide-Check-array-bounds-before-writing-to-io_buffer-C.patch b/0001-ide-Check-array-bounds-before-writing-to-io_buffer-C.patch new file mode 100644 index 0000000..0fc72a6 --- /dev/null +++ b/0001-ide-Check-array-bounds-before-writing-to-io_buffer-C.patch @@ -0,0 +1,79 @@ +From fcb9de761d54ec4aaa44027a5ce95f7b3e36ebd9 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +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 +Reviewed-by: John Snow +(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 + diff --git a/0002-i8254-fix-out-of-bounds-memory-access-in-pit_ioport_.patch b/0002-i8254-fix-out-of-bounds-memory-access-in-pit_ioport_.patch new file mode 100644 index 0000000..c5a2ed5 --- /dev/null +++ b/0002-i8254-fix-out-of-bounds-memory-access-in-pit_ioport_.patch @@ -0,0 +1,45 @@ +From 1ed2665d9163d25cce12a1d8a764b939b2593c6e Mon Sep 17 00:00:00 2001 +From: Petr Matousek +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 +Fixes: 0505bcdec8228d8de39ab1a02644e71999e7c052 +Cc: qemu-stable@nongnu.org +Signed-off-by: Petr Matousek +Signed-off-by: Paolo Bonzini +(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 + diff --git a/0003-pcnet-fix-Negative-array-index-read.patch b/0003-pcnet-fix-Negative-array-index-read.patch new file mode 100644 index 0000000..e4444cf --- /dev/null +++ b/0003-pcnet-fix-Negative-array-index-read.patch @@ -0,0 +1,100 @@ +From c2c087239b676b7dcb75f74ed8509bd0d286ee1d Mon Sep 17 00:00:00 2001 +From: Gonglei +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 +Signed-off-by: Paolo Bonzini +Reviewed-by: Jason Wang +Reviewed-by: Jason Wang +Signed-off-by: Stefan Hajnoczi +(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 + diff --git a/0004-pcnet-force-the-buffer-access-to-be-in-bounds-during.patch b/0004-pcnet-force-the-buffer-access-to-be-in-bounds-during.patch new file mode 100644 index 0000000..a52e631 --- /dev/null +++ b/0004-pcnet-force-the-buffer-access-to-be-in-bounds-during.patch @@ -0,0 +1,50 @@ +From d913b8e2e9a6480bbefba2abc3e8f55bd9d1f1a7 Mon Sep 17 00:00:00 2001 +From: Petr Matousek +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 +Reported-by: Matt Tait +Reviewed-by: Peter Maydell +Reviewed-by: Stefan Hajnoczi +Signed-off-by: Stefan Hajnoczi +(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 + diff --git a/qemu.spec b/qemu.spec index 42fda0c..effb03b 100644 --- a/qemu.spec +++ b/qemu.spec @@ -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 - 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 - 2:2.0.0-1.5 - CVE-2015-3456: fdc: out-of-bounds fifo buffer memory access (bz #1221152)