summaryrefslogtreecommitdiff
path: root/sysutils/xentools42/patches/patch-CVE-2015-8550
diff options
context:
space:
mode:
Diffstat (limited to 'sysutils/xentools42/patches/patch-CVE-2015-8550')
-rw-r--r--sysutils/xentools42/patches/patch-CVE-2015-8550213
1 files changed, 213 insertions, 0 deletions
diff --git a/sysutils/xentools42/patches/patch-CVE-2015-8550 b/sysutils/xentools42/patches/patch-CVE-2015-8550
new file mode 100644
index 00000000000..f461d538b1b
--- /dev/null
+++ b/sysutils/xentools42/patches/patch-CVE-2015-8550
@@ -0,0 +1,213 @@
+$NetBSD: patch-CVE-2015-8550,v 1.1.2.2 2016/01/11 20:37:17 bsiegert Exp $
+
+patch for CVE-2015-8550 aka XSA-155 from
+http://xenbits.xenproject.org/xsa/xsa155-xen-0001-xen-Add-RING_COPY_REQUEST.patch
+http://xenbits.xenproject.org/xsa/xsa155-xen-0002-blktap2-Use-RING_COPY_REQUEST.patch
+http://xenbits.xenproject.org/xsa/xsa155-xen44-0003-libvchan-Read-prod-cons-only-once.patch
+http://xenbits.xenproject.org/xsa/xsa155-qemut-qdisk-double-access.patch
+http://xenbits.xenproject.org/xsa/xsa155-qemut-xenfb.patch
+http://xenbits.xenproject.org/xsa/xsa155-qemu-qdisk-double-access.patch
+http://xenbits.xenproject.org/xsa/xsa155-qemu-xenfb.patch
+
+--- ../xen/include/public/io/ring.h.orig
++++ ../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))
+
+--- blktap2/drivers/block-log.c.orig
++++ 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;
+
+--- blktap2/drivers/tapdisk-vbd.c.orig
++++ 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;
+
+--- libvchan/io.c.orig
++++ libvchan/io.c
+@@ -118,6 +118,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. */
+@@ -159,6 +160,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. */
+
+--- qemu-xen-traditional/hw/xen_blkif.h.orig 2013-10-10 16:15:47.000000000 +0200
++++ qemu-xen-traditional/hw/xen_blkif.h 2016-01-07 17:35:36.000000000 +0100
+@@ -79,8 +79,10 @@
+ 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 @@
+ 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];
+ }
+
+--- qemu-xen-traditional/hw/xenfb.c
++++ 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;
+
+--- qemu-xen/hw/xen_blkif.h.orig 2013-10-10 16:15:47.000000000 +0200
++++ qemu-xen/hw/xen_blkif.h 2016-01-07 17:35:36.000000000 +0100
+@@ -79,8 +79,10 @@
+ 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 @@
+ 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];
+ }
+
+--- qemu-xen/hw/xenfb.c.orig
++++ qemu-xen/hw/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;