summaryrefslogtreecommitdiffstats
path: root/system/xen/xsa/xsa199-qemut.patch
blob: 50a7eb6c92b682a7294d560b0cd38cc927a637f7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
From b73bd1edc05d1bad5c018228146930d79315a5da Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Mon, 14 Nov 2016 17:19:46 +0000
Subject: [PATCH] qemu: ioport_read, ioport_write: be defensive about 32-bit
 addresses

On x86, ioport addresses are 16-bit.  That these functions take 32-bit
arguments is a mistake.  Changing the argument type to 16-bit will
discard the top bits of any erroneous values from elsewhere in qemu.

Also, check just before use that the value is in range.  (This turns
an ill-advised change to MAX_IOPORTS into a possible guest crash
rather than a privilege escalation vulnerability.)

And, in the Xen ioreq processor, clamp incoming ioport addresses to
16-bit values.  Xen will never write >16-bit values but the guest may
have access to the ioreq ring.  We want to defend the rest of the qemu
code from wrong values.

This is XSA-199.

Reported-by: yanghongke <yanghongke@huawei.com>
Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
---
 i386-dm/helper2.c | 2 ++
 vl.c              | 9 +++++++--
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/i386-dm/helper2.c b/i386-dm/helper2.c
index 2706f2e..5d276bb 100644
--- a/i386-dm/helper2.c
+++ b/i386-dm/helper2.c
@@ -375,6 +375,8 @@ static void cpu_ioreq_pio(CPUState *env, ioreq_t *req)
 {
     uint32_t i;
 
+    req->addr &= 0x0ffffU;
+
     if (req->dir == IOREQ_READ) {
         if (!req->data_is_ptr) {
             req->data = do_inp(env, req->addr, req->size);
diff --git a/vl.c b/vl.c
index f9c4d7e..c3c5d63 100644
--- a/vl.c
+++ b/vl.c
@@ -52,6 +52,7 @@
 
 #include <xen/hvm/hvm_info_table.h>
 
+#include <assert.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <signal.h>
@@ -290,26 +291,30 @@ PicState2 *isa_pic;
 static IOPortReadFunc default_ioport_readb, default_ioport_readw, default_ioport_readl;
 static IOPortWriteFunc default_ioport_writeb, default_ioport_writew, default_ioport_writel;
 
-static uint32_t ioport_read(int index, uint32_t address)
+static uint32_t ioport_read(int index, uint16_t address)
 {
     static IOPortReadFunc *default_func[3] = {
         default_ioport_readb,
         default_ioport_readw,
         default_ioport_readl
     };
+    if (address >= MAX_IOPORTS)
+        abort();
     IOPortReadFunc *func = ioport_read_table[index][address];
     if (!func)
         func = default_func[index];
     return func(ioport_opaque[address], address);
 }
 
-static void ioport_write(int index, uint32_t address, uint32_t data)
+static void ioport_write(int index, uint16_t address, uint32_t data)
 {
     static IOPortWriteFunc *default_func[3] = {
         default_ioport_writeb,
         default_ioport_writew,
         default_ioport_writel
     };
+    if (address >= MAX_IOPORTS)
+        abort();
     IOPortWriteFunc *func = ioport_write_table[index][address];
     if (!func)
         func = default_func[index];
-- 
2.1.4