72 lines
2.4 KiB
Diff
72 lines
2.4 KiB
Diff
From: Jan Beulich <JBeulich@suse.com>
|
|
Date: Tue, 22 Nov 2016 05:56:51 -0700
|
|
Subject: [PATCH] xen: fix ioreq handling
|
|
|
|
Avoid double fetches and bounds check size to avoid overflowing
|
|
internal variables.
|
|
|
|
This is CVE-2016-9381 / XSA-197.
|
|
|
|
Reported-by: yanghongke <yanghongke@huawei.com>
|
|
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
|
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
|
|
Signed-off-by: Stefano Stabellini <sstabellini@kernel.org>
|
|
(cherry picked from commit b85f9dfdb156ae2a2a52f39a36e9f1f270614cd2)
|
|
---
|
|
xen-hvm.c | 16 +++++++++++++++-
|
|
1 file changed, 15 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/xen-hvm.c b/xen-hvm.c
|
|
index 2f348edf86..097007d3ed 100644
|
|
--- a/xen-hvm.c
|
|
+++ b/xen-hvm.c
|
|
@@ -810,6 +810,10 @@ static void cpu_ioreq_pio(ioreq_t *req)
|
|
trace_cpu_ioreq_pio(req, req->dir, req->df, req->data_is_ptr, req->addr,
|
|
req->data, req->count, req->size);
|
|
|
|
+ if (req->size > sizeof(uint32_t)) {
|
|
+ hw_error("PIO: bad size (%u)", req->size);
|
|
+ }
|
|
+
|
|
if (req->dir == IOREQ_READ) {
|
|
if (!req->data_is_ptr) {
|
|
req->data = do_inp(req->addr, req->size);
|
|
@@ -846,6 +850,10 @@ static void cpu_ioreq_move(ioreq_t *req)
|
|
trace_cpu_ioreq_move(req, req->dir, req->df, req->data_is_ptr, req->addr,
|
|
req->data, req->count, req->size);
|
|
|
|
+ if (req->size > sizeof(req->data)) {
|
|
+ hw_error("MMIO: bad size (%u)", req->size);
|
|
+ }
|
|
+
|
|
if (!req->data_is_ptr) {
|
|
if (req->dir == IOREQ_READ) {
|
|
for (i = 0; i < req->count; i++) {
|
|
@@ -1010,11 +1018,13 @@ static int handle_buffered_iopage(XenIOState *state)
|
|
req.df = 1;
|
|
req.type = buf_req->type;
|
|
req.data_is_ptr = 0;
|
|
+ xen_rmb();
|
|
qw = (req.size == 8);
|
|
if (qw) {
|
|
buf_req = &buf_page->buf_ioreq[(rdptr + 1) %
|
|
IOREQ_BUFFER_SLOT_NUM];
|
|
req.data |= ((uint64_t)buf_req->data) << 32;
|
|
+ xen_rmb();
|
|
}
|
|
|
|
handle_ioreq(state, &req);
|
|
@@ -1045,7 +1055,11 @@ static void cpu_handle_ioreq(void *opaque)
|
|
|
|
handle_buffered_iopage(state);
|
|
if (req) {
|
|
- handle_ioreq(state, req);
|
|
+ ioreq_t copy = *req;
|
|
+
|
|
+ xen_rmb();
|
|
+ handle_ioreq(state, ©);
|
|
+ req->data = copy.data;
|
|
|
|
if (req->state != STATE_IOREQ_INPROCESS) {
|
|
fprintf(stderr, "Badness in I/O request ... not in service?!: "
|