5e8735d
From b73bd1edc05d1bad5c018228146930d79315a5da Mon Sep 17 00:00:00 2001
5e8735d
From: Ian Jackson <ian.jackson@eu.citrix.com>
5e8735d
Date: Mon, 14 Nov 2016 17:19:46 +0000
5e8735d
Subject: [PATCH] qemu: ioport_read, ioport_write: be defensive about 32-bit
5e8735d
 addresses
5e8735d
5e8735d
On x86, ioport addresses are 16-bit.  That these functions take 32-bit
5e8735d
arguments is a mistake.  Changing the argument type to 16-bit will
5e8735d
discard the top bits of any erroneous values from elsewhere in qemu.
5e8735d
5e8735d
Also, check just before use that the value is in range.  (This turns
5e8735d
an ill-advised change to MAX_IOPORTS into a possible guest crash
5e8735d
rather than a privilege escalation vulnerability.)
5e8735d
5e8735d
And, in the Xen ioreq processor, clamp incoming ioport addresses to
5e8735d
16-bit values.  Xen will never write >16-bit values but the guest may
5e8735d
have access to the ioreq ring.  We want to defend the rest of the qemu
5e8735d
code from wrong values.
5e8735d
5e8735d
This is XSA-199.
5e8735d
5e8735d
Reported-by: yanghongke <yanghongke@huawei.com>
5e8735d
Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
5e8735d
---
5e8735d
 i386-dm/helper2.c | 2 ++
5e8735d
 vl.c              | 9 +++++++--
5e8735d
 2 files changed, 9 insertions(+), 2 deletions(-)
5e8735d
5e8735d
diff --git a/i386-dm/helper2.c b/i386-dm/helper2.c
5e8735d
index 2706f2e..5d276bb 100644
5e8735d
--- a/i386-dm/helper2.c
5e8735d
+++ b/i386-dm/helper2.c
5e8735d
@ -379,6 +379,7 @@ static void cpu_ioreq_pio(CPUState *env, ioreq_t *req)
5e8735d
         fprintf(stderr, "PIO: bad size (%u)\n", req->size);
5e8735d
         exit(-1);
5e8735d
     }
5e8735d
+    req->addr &= 0x0ffffU;
5e8735d
 
5e8735d
     if (req->dir == IOREQ_READ) {
5e8735d
         if (!req->data_is_ptr) {
5e8735d
diff --git a/vl.c b/vl.c
5e8735d
index f9c4d7e..c3c5d63 100644
5e8735d
--- a/vl.c
5e8735d
+++ b/vl.c
5e8735d
@@ -52,6 +52,7 @@
5e8735d
 
5e8735d
 #include <xen/hvm/hvm_info_table.h>
5e8735d
 
5e8735d
+#include <assert.h>
5e8735d
 #include <unistd.h>
5e8735d
 #include <fcntl.h>
5e8735d
 #include <signal.h>
5e8735d
@@ -290,26 +291,30 @@ PicState2 *isa_pic;
5e8735d
 static IOPortReadFunc default_ioport_readb, default_ioport_readw, default_ioport_readl;
5e8735d
 static IOPortWriteFunc default_ioport_writeb, default_ioport_writew, default_ioport_writel;
5e8735d
 
5e8735d
-static uint32_t ioport_read(int index, uint32_t address)
5e8735d
+static uint32_t ioport_read(int index, uint16_t address)
5e8735d
 {
5e8735d
     static IOPortReadFunc *default_func[3] = {
5e8735d
         default_ioport_readb,
5e8735d
         default_ioport_readw,
5e8735d
         default_ioport_readl
5e8735d
     };
5e8735d
+    if (address >= MAX_IOPORTS)
5e8735d
+        abort();
5e8735d
     IOPortReadFunc *func = ioport_read_table[index][address];
5e8735d
     if (!func)
5e8735d
         func = default_func[index];
5e8735d
     return func(ioport_opaque[address], address);
5e8735d
 }
5e8735d
 
5e8735d
-static void ioport_write(int index, uint32_t address, uint32_t data)
5e8735d
+static void ioport_write(int index, uint16_t address, uint32_t data)
5e8735d
 {
5e8735d
     static IOPortWriteFunc *default_func[3] = {
5e8735d
         default_ioport_writeb,
5e8735d
         default_ioport_writew,
5e8735d
         default_ioport_writel
5e8735d
     };
5e8735d
+    if (address >= MAX_IOPORTS)
5e8735d
+        abort();
5e8735d
     IOPortWriteFunc *func = ioport_write_table[index][address];
5e8735d
     if (!func)
5e8735d
         func = default_func[index];
5e8735d
-- 
5e8735d
2.1.4
5e8735d