fc108946cd
CVE-2015-5307 and CVE-2015-8104 aka XSA-156 CVE-2015-8339 and CVE-2015-8340 aka XSA-159 CVE-2015-8555 aka XSA-165 XSA-166 CVE-2015-8341 aka XSA-160 CVE-2015-8550 aka XSA-155 Bump pkgrevision
213 lines
7.3 KiB
Text
213 lines
7.3 KiB
Text
$NetBSD: patch-CVE-2015-8550,v 1.1 2016/01/07 17:48:34 bouyer 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-xen-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
|
|
@@ -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. */
|
|
|
|
--- qemu-xen-traditional/hw/xen_blkif.h.orig
|
|
+++ 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];
|
|
}
|
|
|
|
--- 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/block/xen_blkif.h
|
|
+++ 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];
|
|
}
|
|
|
|
--- qemu-xen/hw/display/xenfb.c.orig
|
|
+++ 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;
|