From 64fe61fd19b990f3d161859365460aaa719a7f3b Mon Sep 17 00:00:00 2001 From: Michael Young Date: Dec 17 2015 21:21:46 +0000 Subject: paravirtualized drivers incautious about shared memory contents [XSA-155, CVE-2015-8550] qemu-dm buffer overrun in MSI-X handling [XSA-164, CVE-2015-8554] information leak in legacy x86 FPU/XMM initialization [XSA-165, CVE-2015-8555] ioreq handling possibly susceptible to multiple read issue [XSA-166] --- diff --git a/xen.spec b/xen.spec index f6261a9..61d85ba 100644 --- a/xen.spec +++ b/xen.spec @@ -51,7 +51,7 @@ Summary: Xen is a virtual machine monitor Name: xen Version: 4.6.0 -Release: 6%{?dist} +Release: 7%{?dist} Group: Development/Libraries License: GPLv2+ and LGPLv2+ and BSD URL: http://xen.org/ @@ -117,6 +117,16 @@ Patch49: qemu.trad.CVE-2015-8345.patch Patch50: qemu.trad.CVE-2015-7512.patch Patch51: qemu.trad.CVE-2015-8504.patch Patch52: xsa158-fix.patch +Patch53: xsa155-xen-0001-xen-Add-RING_COPY_REQUEST.patch +Patch54: xsa155-xen-0002-blktap2-Use-RING_COPY_REQUEST.patch +Patch55: xsa155-xen-0003-libvchan-Read-prod-cons-only-once.patch +Patch56: xsa155-qemu-qdisk-double-access.patch +Patch57: xsa155-qemut-qdisk-double-access.patch +Patch58: xsa155-qemut-xenfb.patch +Patch59: xsa155-qemu-xenfb.patch +Patch60: xsa164.patch +Patch61: xsa165-4.6.patch +Patch62: xsa166.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root @@ -335,6 +345,16 @@ manage Xen virtual machines. %patch50 -p1 %patch51 -p1 %patch52 -p1 +%patch53 -p1 +%patch54 -p1 +%patch55 -p1 +%patch56 -p1 +%patch57 -p1 +%patch58 -p1 +%patch59 -p1 +%patch60 -p1 +%patch61 -p1 +%patch62 -p1 # stubdom sources cp -v %{SOURCE10} %{SOURCE11} %{SOURCE12} %{SOURCE13} %{SOURCE14} %{SOURCE15} stubdom @@ -861,6 +881,15 @@ rm -rf %{buildroot} %endif %changelog +* Thu Dec 17 2015 Michael Young - 4.6.0-7 +- four security updates (#1292439) + paravirtualized drivers incautious about shared memory contents + [XSA-155, CVE-2015-8550] + qemu-dm buffer overrun in MSI-X handling [XSA-164, CVE-2015-8554] + information leak in legacy x86 FPU/XMM initialization [XSA-165, + CVE-2015-8555] + ioreq handling possibly susceptible to multiple read issue [XSA-166] + * Thu Dec 10 2015 Michael Young - 4.6.0-6 - eepro100: Prevent two endless loops [CVE-2015-8345] (#1285215) - pcnet: fix rx buffer overflow [CVE-2015-7512] (#1286563) diff --git a/xsa155-qemu-qdisk-double-access.patch b/xsa155-qemu-qdisk-double-access.patch new file mode 100644 index 0000000..d8dc9fe --- /dev/null +++ b/xsa155-qemu-qdisk-double-access.patch @@ -0,0 +1,43 @@ +xen/blkif: Avoid double access to src->nr_segments + +src is stored in shared memory and src->nr_segments is dereferenced +twice at the end of the function. If a compiler decides to compile this +into two separate memory accesses then the size limitation could be +bypassed. + +Fix it by removing the double access to src->nr_segments. + +This is part of XSA-155. + +Signed-off-by: Stefano Stabellini + +diff --git a/tools/qemu-xen/hw/block/xen_blkif.h b/tools/qemu-xen/hw/block/xen_blkif.h +index 711b692..9e71e00 100644 +--- a/tools/qemu-xen/hw/block/xen_blkif.h ++++ b/tools/qemu-xen/hw/block/xen_blkif.h +@@ -85,8 +85,10 @@ static inline void blkif_get_x86_32_req(blkif_request_t *dst, blkif_x86_32_reque + d->nr_sectors = s->nr_sectors; + return; + } +- if (n > src->nr_segments) +- n = src->nr_segments; ++ /* prevent the compiler from optimizing the code and using src->nr_segments instead */ ++ barrier(); ++ if (n > dst->nr_segments) ++ n = dst->nr_segments; + for (i = 0; i < n; i++) + dst->seg[i] = src->seg[i]; + } +@@ -106,8 +108,10 @@ static inline void blkif_get_x86_64_req(blkif_request_t *dst, blkif_x86_64_reque + d->nr_sectors = s->nr_sectors; + return; + } +- if (n > src->nr_segments) +- n = src->nr_segments; ++ /* prevent the compiler from optimizing the code and using src->nr_segments instead */ ++ barrier(); ++ if (n > dst->nr_segments) ++ n = dst->nr_segments; + for (i = 0; i < n; i++) + dst->seg[i] = src->seg[i]; + } diff --git a/xsa155-qemu-xenfb.patch b/xsa155-qemu-xenfb.patch new file mode 100644 index 0000000..bdcb963 --- /dev/null +++ b/xsa155-qemu-xenfb.patch @@ -0,0 +1,41 @@ +xenfb: avoid reading twice the same fields from the shared page + +Reading twice the same field could give the guest an attack of +opportunity. In the case of event->type, gcc could compile the switch +statement into a jump table, effectively ending up reading the type +field multiple times. + +This is part of XSA-155. + +Signed-off-by: Stefano Stabellini + + +diff --git a/tools/qemu-xen/hw/display/xenfb.c b/tools/qemu-xen/hw/display/xenfb.c +index 5e324ef..4e2a27a 100644 +--- a/tools/qemu-xen/hw/display/xenfb.c ++++ b/tools/qemu-xen/hw/display/xenfb.c +@@ -784,18 +784,20 @@ static void xenfb_invalidate(void *opaque) + + static void xenfb_handle_events(struct XenFB *xenfb) + { +- uint32_t prod, cons; ++ uint32_t prod, cons, out_cons; + struct xenfb_page *page = xenfb->c.page; + + prod = page->out_prod; +- if (prod == page->out_cons) ++ out_cons = page->out_cons; ++ if (prod == out_cons) + return; + xen_rmb(); /* ensure we see ring contents up to prod */ +- for (cons = page->out_cons; cons != prod; cons++) { ++ for (cons = out_cons; cons != prod; cons++) { + union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons); ++ uint8_t type = event->type; + int x, y, w, h; + +- switch (event->type) { ++ switch (type) { + case XENFB_TYPE_UPDATE: + if (xenfb->up_count == UP_QUEUE) + xenfb->up_fullscreen = 1; diff --git a/xsa155-qemut-qdisk-double-access.patch b/xsa155-qemut-qdisk-double-access.patch new file mode 100644 index 0000000..3418ce2 --- /dev/null +++ b/xsa155-qemut-qdisk-double-access.patch @@ -0,0 +1,53 @@ +From 27942b0cb2327e93deb12326bbe7b36c81f9fa7b Mon Sep 17 00:00:00 2001 +From: Stefano Stabellini +Date: Fri, 20 Nov 2015 10:56:00 -0500 +Subject: [PATCH] blkif: Avoid double access to src->nr_segments + +src is stored in shared memory and src->nr_segments is dereferenced +twice at the end of the function. If a compiler decides to compile this +into two separate memory accesses then the size limitation could be +bypassed. + +Fix it by removing the double access to src->nr_segments. + +This is part of XSA-155. + +Signed-off-by: Stefano Stabellini +Signed-off-by: Konrad Rzeszutek Wilk +--- + tools/qemu-xen-traditional/hw/xen_blkif.h | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/tools/qemu-xen-traditional/hw/xen_blkif.h b/tools/qemu-xen-traditional/hw/xen_blkif.h +index ca3a65b..eb29cb1 100644 +--- a/tools/qemu-xen-traditional/hw/xen_blkif.h ++++ b/tools/qemu-xen-traditional/hw/xen_blkif.h +@@ -79,8 +79,10 @@ static inline void blkif_get_x86_32_req(blkif_request_t *dst, blkif_x86_32_reque + dst->handle = src->handle; + dst->id = src->id; + dst->sector_number = src->sector_number; +- if (n > src->nr_segments) +- n = src->nr_segments; ++ /* prevent the compiler from optimizing the code and using src->nr_segments instead */ ++ xen_mb(); ++ if (n > dst->nr_segments) ++ n = dst->nr_segments; + for (i = 0; i < n; i++) + dst->seg[i] = src->seg[i]; + } +@@ -94,8 +96,10 @@ static inline void blkif_get_x86_64_req(blkif_request_t *dst, blkif_x86_64_reque + dst->handle = src->handle; + dst->id = src->id; + dst->sector_number = src->sector_number; +- if (n > src->nr_segments) +- n = src->nr_segments; ++ /* prevent the compiler from optimizing the code and using src->nr_segments instead */ ++ xen_mb(); ++ if (n > dst->nr_segments) ++ n = dst->nr_segments; + for (i = 0; i < n; i++) + dst->seg[i] = src->seg[i]; + } +-- +2.4.3 + diff --git a/xsa155-qemut-xenfb.patch b/xsa155-qemut-xenfb.patch new file mode 100644 index 0000000..75d3c99 --- /dev/null +++ b/xsa155-qemut-xenfb.patch @@ -0,0 +1,50 @@ +From 0ffd4547665d2fec648ab2c9ff856c5d9db9b07c Mon Sep 17 00:00:00 2001 +From: Stefano Stabellini +Date: Fri, 20 Nov 2015 10:37:08 -0500 +Subject: [PATCH 2/2] xenfb: avoid reading twice the same fields from the + shared page + +Reading twice the same field could give the guest an attack of +opportunity. In the case of event->type, gcc could compile the switch +statement into a jump table, effectively ending up reading the type +field multiple times. + +This is part of XSA-155. + +Signed-off-by: Stefano Stabellini +--- + tools/qemu-xen-traditional/hw/xenfb.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/tools/qemu-xen-traditional/hw/xenfb.c b/tools/qemu-xen-traditional/hw/xenfb.c +index 75b2bc2..369d45d 100644 +--- a/tools/qemu-xen-traditional/hw/xenfb.c ++++ b/tools/qemu-xen-traditional/hw/xenfb.c +@@ -827,18 +827,20 @@ static void xenfb_invalidate(void *opaque) + + static void xenfb_handle_events(struct XenFB *xenfb) + { +- uint32_t prod, cons; ++ uint32_t prod, cons, out_cons; + struct xenfb_page *page = xenfb->c.page; + + prod = page->out_prod; +- if (prod == page->out_cons) ++ out_cons = page->out_cons; ++ if (prod == out_cons) + return; + xen_rmb(); /* ensure we see ring contents up to prod */ +- for (cons = page->out_cons; cons != prod; cons++) { ++ for (cons = out_cons; cons != prod; cons++) { + union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons); ++ uint8_t type = event->type; + int x, y, w, h; + +- switch (event->type) { ++ switch (type) { + case XENFB_TYPE_UPDATE: + if (xenfb->up_count == UP_QUEUE) + xenfb->up_fullscreen = 1; +-- +2.1.0 + diff --git a/xsa155-xen-0001-xen-Add-RING_COPY_REQUEST.patch b/xsa155-xen-0001-xen-Add-RING_COPY_REQUEST.patch new file mode 100644 index 0000000..7935e58 --- /dev/null +++ b/xsa155-xen-0001-xen-Add-RING_COPY_REQUEST.patch @@ -0,0 +1,56 @@ +From 12b11658a9d6a654a1e7acbf2f2d56ce9a396c86 Mon Sep 17 00:00:00 2001 +From: David Vrabel +Date: Fri, 20 Nov 2015 11:59:05 -0500 +Subject: [PATCH 1/3] xen: Add RING_COPY_REQUEST() + +Using RING_GET_REQUEST() on a shared ring is easy to use incorrectly +(i.e., by not considering that the other end may alter the data in the +shared ring while it is being inspected). Safe usage of a request +generally requires taking a local copy. + +Provide a RING_COPY_REQUEST() macro to use instead of +RING_GET_REQUEST() and an open-coded memcpy(). This takes care of +ensuring that the copy is done correctly regardless of any possible +compiler optimizations. + +Use a volatile source to prevent the compiler from reordering or +omitting the copy. + +This is part of XSA155. + +Signed-off-by: David Vrabel +Signed-off-by: Konrad Rzeszutek Wilk +--- +v2: Add comment about GCC bug. +--- + xen/include/public/io/ring.h | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/xen/include/public/io/ring.h b/xen/include/public/io/ring.h +index ba9401b..801c0da 100644 +--- a/xen/include/public/io/ring.h ++++ b/xen/include/public/io/ring.h +@@ -212,6 +212,20 @@ typedef struct __name##_back_ring __name##_back_ring_t + #define RING_GET_REQUEST(_r, _idx) \ + (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req)) + ++/* ++ * Get a local copy of a request. ++ * ++ * Use this in preference to RING_GET_REQUEST() so all processing is ++ * done on a local copy that cannot be modified by the other end. ++ * ++ * Note that https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58145 may cause this ++ * to be ineffective where _req is a struct which consists of only bitfields. ++ */ ++#define RING_COPY_REQUEST(_r, _idx, _req) do { \ ++ /* Use volatile to force the copy into _req. */ \ ++ *(_req) = *(volatile typeof(_req))RING_GET_REQUEST(_r, _idx); \ ++} while (0) ++ + #define RING_GET_RESPONSE(_r, _idx) \ + (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].rsp)) + +-- +2.1.0 + diff --git a/xsa155-xen-0002-blktap2-Use-RING_COPY_REQUEST.patch b/xsa155-xen-0002-blktap2-Use-RING_COPY_REQUEST.patch new file mode 100644 index 0000000..2d80a7b --- /dev/null +++ b/xsa155-xen-0002-blktap2-Use-RING_COPY_REQUEST.patch @@ -0,0 +1,75 @@ +From 851ffb4eea917e2708c912291dea4d133026c0ac Mon Sep 17 00:00:00 2001 +From: Konrad Rzeszutek Wilk +Date: Fri, 20 Nov 2015 12:16:02 -0500 +Subject: [PATCH 2/3] blktap2: Use RING_COPY_REQUEST + +Instead of RING_GET_REQUEST. Using a local copy of the +ring (and also with proper memory barriers) will mean +we can do not have to worry about the compiler optimizing +the code and doing a double-fetch in the shared memory space. + +This is part of XSA155. + +Signed-off-by: Konrad Rzeszutek Wilk + +--- +v2: Fix compile issues with tapdisk-vbd +--- + tools/blktap2/drivers/block-log.c | 3 ++- + tools/blktap2/drivers/tapdisk-vbd.c | 8 ++++---- + 2 files changed, 6 insertions(+), 5 deletions(-) + +diff --git a/tools/blktap2/drivers/block-log.c b/tools/blktap2/drivers/block-log.c +index 5330cdc..5f3bd35 100644 +--- a/tools/blktap2/drivers/block-log.c ++++ b/tools/blktap2/drivers/block-log.c +@@ -494,11 +494,12 @@ static int ctl_kick(struct tdlog_state* s, int fd) + reqstart = s->bring.req_cons; + reqend = s->sring->req_prod; + ++ xen_mb(); + BDPRINTF("ctl: ring kicked (start = %u, end = %u)", reqstart, reqend); + + while (reqstart != reqend) { + /* XXX actually submit these! */ +- memcpy(&req, RING_GET_REQUEST(&s->bring, reqstart), sizeof(req)); ++ RING_COPY_REQUEST(&s->bring, reqstart, &req); + BDPRINTF("ctl: read request %"PRIu64":%u", req.sector, req.count); + s->bring.req_cons = ++reqstart; + +diff --git a/tools/blktap2/drivers/tapdisk-vbd.c b/tools/blktap2/drivers/tapdisk-vbd.c +index 6d1d94a..89ef9ed 100644 +--- a/tools/blktap2/drivers/tapdisk-vbd.c ++++ b/tools/blktap2/drivers/tapdisk-vbd.c +@@ -1555,7 +1555,7 @@ tapdisk_vbd_pull_ring_requests(td_vbd_t *vbd) + int idx; + RING_IDX rp, rc; + td_ring_t *ring; +- blkif_request_t *req; ++ blkif_request_t req; + td_vbd_request_t *vreq; + + ring = &vbd->ring; +@@ -1566,16 +1566,16 @@ tapdisk_vbd_pull_ring_requests(td_vbd_t *vbd) + xen_rmb(); + + for (rc = ring->fe_ring.req_cons; rc != rp; rc++) { +- req = RING_GET_REQUEST(&ring->fe_ring, rc); ++ RING_COPY_REQUEST(&ring->fe_ring, rc, &req); + ++ring->fe_ring.req_cons; + +- idx = req->id; ++ idx = req.id; + vreq = &vbd->request_list[idx]; + + ASSERT(list_empty(&vreq->next)); + ASSERT(vreq->secs_pending == 0); + +- memcpy(&vreq->req, req, sizeof(blkif_request_t)); ++ memcpy(&vreq->req, &req, sizeof(blkif_request_t)); + vbd->received++; + vreq->vbd = vbd; + +-- +2.1.4 + diff --git a/xsa155-xen-0003-libvchan-Read-prod-cons-only-once.patch b/xsa155-xen-0003-libvchan-Read-prod-cons-only-once.patch new file mode 100644 index 0000000..56a6e53 --- /dev/null +++ b/xsa155-xen-0003-libvchan-Read-prod-cons-only-once.patch @@ -0,0 +1,41 @@ +From c1fce65e2b720684ea6ba76ae59921542bd154bb Mon Sep 17 00:00:00 2001 +From: Konrad Rzeszutek Wilk +Date: Fri, 20 Nov 2015 12:22:14 -0500 +Subject: [PATCH 3/3] libvchan: Read prod/cons only once. + +We must ensure that the prod/cons are only read once and that +the compiler won't try to optimize the reads. That is split +the read of these in multiple instructions influencing later +branch code. As such insert barriers when fetching the cons +and prod index. + +This is part of XSA155. + +Signed-off-by: Konrad Rzeszutek Wilk +--- + tools/libvchan/io.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/tools/libvchan/io.c b/tools/libvchan/io.c +index 8a9629b..381cc05 100644 +--- a/tools/libvchan/io.c ++++ b/tools/libvchan/io.c +@@ -117,6 +117,7 @@ static inline int send_notify(struct libxenvchan *ctrl, uint8_t bit) + static inline int raw_get_data_ready(struct libxenvchan *ctrl) + { + uint32_t ready = rd_prod(ctrl) - rd_cons(ctrl); ++ xen_mb(); /* Ensure 'ready' is read only once. */ + if (ready > rd_ring_size(ctrl)) + /* We have no way to return errors. Locking up the ring is + * better than the alternatives. */ +@@ -158,6 +159,7 @@ int libxenvchan_data_ready(struct libxenvchan *ctrl) + static inline int raw_get_buffer_space(struct libxenvchan *ctrl) + { + uint32_t ready = wr_ring_size(ctrl) - (wr_prod(ctrl) - wr_cons(ctrl)); ++ xen_mb(); /* Ensure 'ready' is read only once. */ + if (ready > wr_ring_size(ctrl)) + /* We have no way to return errors. Locking up the ring is + * better than the alternatives. */ +-- +2.1.0 + diff --git a/xsa164.patch b/xsa164.patch new file mode 100644 index 0000000..00edb76 --- /dev/null +++ b/xsa164.patch @@ -0,0 +1,34 @@ +MSI-X: avoid array overrun upon MSI-X table writes + +pt_msix_init() allocates msix->msix_entry[] to just cover +msix->total_entries entries. While pci_msix_readl() resorts to reading +physical memory for out of bounds reads, pci_msix_writel() so far +simply accessed/corrupted unrelated memory. + +pt_iomem_map()'s call to cpu_register_physical_memory() registers a +page granular region, which is necessary as the Pending Bit Array may +share space with the MSI-X table (but nothing else is allowed to). This +also explains why pci_msix_readl() actually honors out of bounds reads, +but pci_msi_writel() doesn't need to. + +This is XSA-164. + +Signed-off-by: Jan Beulich +Acked-by: Ian Campbell + +--- a/tools/qemu-xen-traditional/hw/pt-msi.c ++++ b/tools/qemu-xen-traditional/hw/pt-msi.c +@@ -440,6 +440,13 @@ static void pci_msix_writel(void *opaque + return; + } + ++ if ( addr - msix->mmio_base_addr >= msix->total_entries * 16 ) ++ { ++ PT_LOG("Error: Out of bounds write to MSI-X table," ++ " addr %016"PRIx64"\n", addr); ++ return; ++ } ++ + entry_nr = (addr - msix->mmio_base_addr) / 16; + entry = &msix->msix_entry[entry_nr]; + offset = ((addr - msix->mmio_base_addr) % 16) / 4; diff --git a/xsa165-4.6.patch b/xsa165-4.6.patch new file mode 100644 index 0000000..81de03c --- /dev/null +++ b/xsa165-4.6.patch @@ -0,0 +1,85 @@ +x86: don't leak ST(n)/XMMn values to domains first using them + +FNINIT doesn't alter these registers, and hence using it is +insufficient to initialize a guest's initial state. + +This is XSA-165. + +Signed-off-by: Jan Beulich +Reviewed-by: Andrew Cooper + +--- a/xen/arch/x86/domain.c ++++ b/xen/arch/x86/domain.c +@@ -851,6 +851,17 @@ int arch_set_info_guest( + if ( v->arch.xsave_area ) + v->arch.xsave_area->xsave_hdr.xstate_bv = XSTATE_FP_SSE; + } ++ else if ( v->arch.xsave_area ) ++ memset(&v->arch.xsave_area->xsave_hdr, 0, ++ sizeof(v->arch.xsave_area->xsave_hdr)); ++ else ++ { ++ typeof(v->arch.xsave_area->fpu_sse) *fpu_sse = v->arch.fpu_ctxt; ++ ++ memset(fpu_sse, 0, sizeof(*fpu_sse)); ++ fpu_sse->fcw = FCW_DEFAULT; ++ fpu_sse->mxcsr = MXCSR_DEFAULT; ++ } + + if ( !compat ) + { +--- a/xen/arch/x86/i387.c ++++ b/xen/arch/x86/i387.c +@@ -17,19 +17,6 @@ + #include + #include + +-static void fpu_init(void) +-{ +- unsigned long val; +- +- asm volatile ( "fninit" ); +- if ( cpu_has_xmm ) +- { +- /* load default value into MXCSR control/status register */ +- val = MXCSR_DEFAULT; +- asm volatile ( "ldmxcsr %0" : : "m" (val) ); +- } +-} +- + /*******************************/ + /* FPU Restore Functions */ + /*******************************/ +@@ -248,15 +235,8 @@ void vcpu_restore_fpu_lazy(struct vcpu * + + if ( cpu_has_xsave ) + fpu_xrstor(v, XSTATE_LAZY); +- else if ( v->fpu_initialised ) +- { +- if ( cpu_has_fxsr ) +- fpu_fxrstor(v); +- else +- fpu_frstor(v); +- } + else +- fpu_init(); ++ fpu_fxrstor(v); + + v->fpu_initialised = 1; + v->fpu_dirtied = 1; +@@ -313,7 +293,14 @@ int vcpu_init_fpu(struct vcpu *v) + else + { + v->arch.fpu_ctxt = _xzalloc(sizeof(v->arch.xsave_area->fpu_sse), 16); +- if ( !v->arch.fpu_ctxt ) ++ if ( v->arch.fpu_ctxt ) ++ { ++ typeof(v->arch.xsave_area->fpu_sse) *fpu_sse = v->arch.fpu_ctxt; ++ ++ fpu_sse->fcw = FCW_DEFAULT; ++ fpu_sse->mxcsr = MXCSR_DEFAULT; ++ } ++ else + rc = -ENOMEM; + } + diff --git a/xsa166.patch b/xsa166.patch new file mode 100644 index 0000000..d3ba5d5 --- /dev/null +++ b/xsa166.patch @@ -0,0 +1,46 @@ +x86/HVM: avoid reading ioreq state more than once + +Otherwise, especially when the compiler chooses to translate the +switch() to a jump table, unpredictable behavior (and in the jump table +case arbitrary code execution) can result. + +This is XSA-166. + +Signed-off-by: Jan Beulich +Acked-by: Ian Campbell + +--- a/xen/arch/x86/hvm/hvm.c ++++ b/xen/arch/x86/hvm/hvm.c +@@ -460,7 +460,10 @@ static bool_t hvm_wait_for_io(struct hvm + { + while ( sv->pending ) + { +- switch ( p->state ) ++ unsigned int state = p->state; ++ ++ rmb(); ++ switch ( state ) + { + case STATE_IOREQ_NONE: + /* +@@ -471,18 +474,15 @@ static bool_t hvm_wait_for_io(struct hvm + hvm_io_assist(sv, ~0ul); + break; + case STATE_IORESP_READY: /* IORESP_READY -> NONE */ +- rmb(); /* see IORESP_READY /then/ read contents of ioreq */ + p->state = STATE_IOREQ_NONE; + hvm_io_assist(sv, p->data); + break; + case STATE_IOREQ_READY: /* IOREQ_{READY,INPROCESS} -> IORESP_READY */ + case STATE_IOREQ_INPROCESS: +- wait_on_xen_event_channel(sv->ioreq_evtchn, +- (p->state != STATE_IOREQ_READY) && +- (p->state != STATE_IOREQ_INPROCESS)); ++ wait_on_xen_event_channel(sv->ioreq_evtchn, p->state != state); + break; + default: +- gdprintk(XENLOG_ERR, "Weird HVM iorequest state %d.\n", p->state); ++ gdprintk(XENLOG_ERR, "Weird HVM iorequest state %u\n", state); + sv->pending = 0; + domain_crash(sv->vcpu->domain); + return 0; /* bail */