summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools
diff options
context:
space:
mode:
authorSteve Sakoman <steve@sakoman.com>2020-10-27 06:45:19 -1000
committerSteve Sakoman <steve@sakoman.com>2020-11-02 04:05:13 -1000
commitdc91e39e6a5c117a2fec7afc2bab683ff0ab096a (patch)
treeae69ad7eb60160254eb2d40e1d0c783ace435ae1 /meta/recipes-devtools
parent8a367cbbf092339a8c82c680a2565567b594b6c6 (diff)
downloadopenembedded-core-contrib-dc91e39e6a5c117a2fec7afc2bab683ff0ab096a.tar.gz
qemu: fix CVE-2019-20175
CVE: CVE-2019-20175 Signed-off-by: Steve Sakoman <steve@sakoman.com>
Diffstat (limited to 'meta/recipes-devtools')
-rw-r--r--meta/recipes-devtools/qemu/qemu.inc1
-rw-r--r--meta/recipes-devtools/qemu/qemu/CVE-2019-20175.patch94
2 files changed, 95 insertions, 0 deletions
diff --git a/meta/recipes-devtools/qemu/qemu.inc b/meta/recipes-devtools/qemu/qemu.inc
index 76f97eef35..b6941403ea 100644
--- a/meta/recipes-devtools/qemu/qemu.inc
+++ b/meta/recipes-devtools/qemu/qemu.inc
@@ -49,6 +49,7 @@ SRC_URI = "https://download.qemu.org/${BPN}-${PV}.tar.xz \
file://CVE-2020-14415.patch \
file://CVE-2020-16092.patch \
file://0001-target-mips-Increase-number-of-TLB-entries-on-the-34.patch \
+ file://CVE-2019-20175.patch \
"
UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+(\.\d+)+)\.tar"
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2019-20175.patch b/meta/recipes-devtools/qemu/qemu/CVE-2019-20175.patch
new file mode 100644
index 0000000000..cbbb6d094c
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/CVE-2019-20175.patch
@@ -0,0 +1,94 @@
+From ed78352a59ea7acf7520d4d47a96b9911bae7fc3 Mon Sep 17 00:00:00 2001
+From: Alexander Popov <alex.popov@linux.com>
+Date: Mon, 23 Dec 2019 20:51:16 +0300
+Subject: [PATCH] ide: Fix incorrect handling of some PRDTs in ide_dma_cb()
+
+The commit a718978ed58a from July 2015 introduced the assertion which
+implies that the size of successful DMA transfers handled in ide_dma_cb()
+should be multiple of 512 (the size of a sector). But guest systems can
+initiate DMA transfers that don't fit this requirement.
+
+For fixing that let's check the number of bytes prepared for the transfer
+by the prepare_buf() handler. The code in ide_dma_cb() must behave
+according to the Programming Interface for Bus Master IDE Controller
+(Revision 1.0 5/16/94):
+1. If PRDs specified a smaller size than the IDE transfer
+ size, then the Interrupt and Active bits in the Controller
+ status register are not set (Error Condition).
+2. If the size of the physical memory regions was equal to
+ the IDE device transfer size, the Interrupt bit in the
+ Controller status register is set to 1, Active bit is set to 0.
+3. If PRDs specified a larger size than the IDE transfer size,
+ the Interrupt and Active bits in the Controller status register
+ are both set to 1.
+
+Signed-off-by: Alexander Popov <alex.popov@linux.com>
+Reviewed-by: Kevin Wolf <kwolf@redhat.com>
+Message-id: 20191223175117.508990-2-alex.popov@linux.com
+Signed-off-by: John Snow <jsnow@redhat.com>
+
+Upstream-Status: Backport
+CVE: CVE-2019-20175
+Signed-off-by: Steve Sakoman <steve@sakoman.com>
+
+---
+ hw/ide/core.c | 30 ++++++++++++++++++++++--------
+ 1 file changed, 22 insertions(+), 8 deletions(-)
+
+diff --git a/hw/ide/core.c b/hw/ide/core.c
+index 754ff4dc343..80000eb7661 100644
+--- a/hw/ide/core.c
++++ b/hw/ide/core.c
+@@ -849,6 +849,7 @@ static void ide_dma_cb(void *opaque, int ret)
+ int64_t sector_num;
+ uint64_t offset;
+ bool stay_active = false;
++ int32_t prep_size = 0;
+
+ if (ret == -EINVAL) {
+ ide_dma_error(s);
+@@ -863,13 +864,15 @@ static void ide_dma_cb(void *opaque, int ret)
+ }
+ }
+
+- n = s->io_buffer_size >> 9;
+- if (n > s->nsector) {
+- /* The PRDs were longer than needed for this request. Shorten them so
+- * we don't get a negative remainder. The Active bit must remain set
+- * after the request completes. */
++ if (s->io_buffer_size > s->nsector * 512) {
++ /*
++ * The PRDs were longer than needed for this request.
++ * The Active bit must remain set after the request completes.
++ */
+ n = s->nsector;
+ stay_active = true;
++ } else {
++ n = s->io_buffer_size >> 9;
+ }
+
+ sector_num = ide_get_sector(s);
+@@ -892,9 +895,20 @@ static void ide_dma_cb(void *opaque, int ret)
+ n = s->nsector;
+ s->io_buffer_index = 0;
+ s->io_buffer_size = n * 512;
+- if (s->bus->dma->ops->prepare_buf(s->bus->dma, s->io_buffer_size) < 512) {
+- /* The PRDs were too short. Reset the Active bit, but don't raise an
+- * interrupt. */
++ prep_size = s->bus->dma->ops->prepare_buf(s->bus->dma, s->io_buffer_size);
++ /* prepare_buf() must succeed and respect the limit */
++ assert(prep_size >= 0 && prep_size <= n * 512);
++
++ /*
++ * Now prep_size stores the number of bytes in the sglist, and
++ * s->io_buffer_size stores the number of bytes described by the PRDs.
++ */
++
++ if (prep_size < n * 512) {
++ /*
++ * The PRDs are too short for this request. Error condition!
++ * Reset the Active bit and don't raise the interrupt.
++ */
+ s->status = READY_STAT | SEEK_STAT;
+ dma_buf_commit(s, 0);
+ goto eot;