diff --git a/debian/changelog b/debian/changelog index 5c0d8ddc0..b58269dde 100644 --- a/debian/changelog +++ b/debian/changelog @@ -5,6 +5,7 @@ linux (4.3.3-3) UNRELEASED; urgency=medium * block: ensure to split after potentially bouncing a bio (Closes: #809082) * pptp: verify sockaddr_len in pptp_bind() and pptp_connect() (CVE-2015-8569) * bluetooth: Validate socket address length in sco_sock_bind() (CVE-2015-8575) + * [xen] Fix race conditions in back-end drivers (CVE-2015-8550, XSA-155) [ Salvatore Bonaccorso ] * ovl: fix permission checking for setattr (CVE-2015-8660) diff --git a/debian/patches/bugfix/all/xen-add-ring_copy_request.patch b/debian/patches/bugfix/all/xen-add-ring_copy_request.patch new file mode 100644 index 000000000..51e9546a6 --- /dev/null +++ b/debian/patches/bugfix/all/xen-add-ring_copy_request.patch @@ -0,0 +1,52 @@ +From: David Vrabel +Date: Fri, 30 Oct 2015 14:58:08 +0000 +Subject: [1/7] xen: Add RING_COPY_REQUEST() +Origin: https://git.kernel.org/linus/454d5d882c7e412b840e3c99010fe81a9862f6fb + +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. + +CC: stable@vger.kernel.org +Signed-off-by: David Vrabel +Signed-off-by: Konrad Rzeszutek Wilk +--- + include/xen/interface/io/ring.h | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/include/xen/interface/io/ring.h b/include/xen/interface/io/ring.h +index 7d28aff..7dc685b4 100644 +--- a/include/xen/interface/io/ring.h ++++ b/include/xen/interface/io/ring.h +@@ -181,6 +181,20 @@ struct __name##_back_ring { \ + #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)) + diff --git a/debian/patches/bugfix/all/xen-blkback-only-read-request-operation-from-shared-.patch b/debian/patches/bugfix/all/xen-blkback-only-read-request-operation-from-shared-.patch new file mode 100644 index 000000000..c77251c45 --- /dev/null +++ b/debian/patches/bugfix/all/xen-blkback-only-read-request-operation-from-shared-.patch @@ -0,0 +1,48 @@ +From: =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= +Date: Tue, 3 Nov 2015 16:34:09 +0000 +Subject: [4/7] xen-blkback: only read request operation from shared ring once +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Origin: https://git.kernel.org/linus/1f13d75ccb806260079e0679d55d9253e370ec8a + +A compiler may load a switch statement value multiple times, which could +be bad when the value is in memory shared with the frontend. + +When converting a non-native request to a native one, ensure that +src->operation is only loaded once by using READ_ONCE(). + +This is part of XSA155. + +CC: stable@vger.kernel.org +Signed-off-by: Roger Pau Monné +Signed-off-by: David Vrabel +Signed-off-by: Konrad Rzeszutek Wilk +--- + drivers/block/xen-blkback/common.h | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/block/xen-blkback/common.h ++++ b/drivers/block/xen-blkback/common.h +@@ -399,8 +399,8 @@ static inline void blkif_get_x86_32_req( + struct blkif_x86_32_request *src) + { + int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST, j; +- dst->operation = src->operation; +- switch (src->operation) { ++ dst->operation = READ_ONCE(src->operation); ++ switch (dst->operation) { + case BLKIF_OP_READ: + case BLKIF_OP_WRITE: + case BLKIF_OP_WRITE_BARRIER: +@@ -447,8 +447,8 @@ static inline void blkif_get_x86_64_req( + struct blkif_x86_64_request *src) + { + int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST, j; +- dst->operation = src->operation; +- switch (src->operation) { ++ dst->operation = READ_ONCE(src->operation); ++ switch (dst->operation) { + case BLKIF_OP_READ: + case BLKIF_OP_WRITE: + case BLKIF_OP_WRITE_BARRIER: diff --git a/debian/patches/bugfix/all/xen-blkback-read-from-indirect-descriptors-only-once.patch b/debian/patches/bugfix/all/xen-blkback-read-from-indirect-descriptors-only-once.patch new file mode 100644 index 000000000..c23a76566 --- /dev/null +++ b/debian/patches/bugfix/all/xen-blkback-read-from-indirect-descriptors-only-once.patch @@ -0,0 +1,65 @@ +From: =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= +Date: Tue, 3 Nov 2015 16:40:43 +0000 +Subject: [5/7] xen-blkback: read from indirect descriptors only once +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Origin: https://git.kernel.org/linus/18779149101c0dd43ded43669ae2a92d21b6f9cb + +Since indirect descriptors are in memory shared with the frontend, the +frontend could alter the first_sect and last_sect values after they have +been validated but before they are recorded in the request. This may +result in I/O requests that overflow the foreign page, possibly +overwriting local pages when the I/O request is executed. + +When parsing indirect descriptors, only read first_sect and last_sect +once. + +This is part of XSA155. + +CC: stable@vger.kernel.org +Signed-off-by: Roger Pau Monné +Signed-off-by: David Vrabel +Signed-off-by: Konrad Rzeszutek Wilk +[bwh: For 4.3, s/XEN_PAGE_SIZE/PAGE_SIZE/] +--- + drivers/block/xen-blkback/blkback.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c +index f909994..41fb1a9 100644 +--- a/drivers/block/xen-blkback/blkback.c ++++ b/drivers/block/xen-blkback/blkback.c +@@ -950,6 +950,8 @@ static int xen_blkbk_parse_indirect(struct blkif_request *req, + goto unmap; + + for (n = 0, i = 0; n < nseg; n++) { ++ uint8_t first_sect, last_sect; ++ + if ((n % SEGS_PER_INDIRECT_FRAME) == 0) { + /* Map indirect segments */ + if (segments) +@@ -957,15 +959,18 @@ static int xen_blkbk_parse_indirect(struct blkif_request *req, + segments = kmap_atomic(pages[n/SEGS_PER_INDIRECT_FRAME]->page); + } + i = n % SEGS_PER_INDIRECT_FRAME; ++ + pending_req->segments[n]->gref = segments[i].gref; +- seg[n].nsec = segments[i].last_sect - +- segments[i].first_sect + 1; +- seg[n].offset = (segments[i].first_sect << 9); +- if ((segments[i].last_sect >= (PAGE_SIZE >> 9)) || +- (segments[i].last_sect < segments[i].first_sect)) { ++ ++ first_sect = READ_ONCE(segments[i].first_sect); ++ last_sect = READ_ONCE(segments[i].last_sect); ++ if (last_sect >= (PAGE_SIZE >> 9) || last_sect < first_sect) { + rc = -EINVAL; + goto unmap; + } ++ ++ seg[n].nsec = last_sect - first_sect + 1; ++ seg[n].offset = first_sect << 9; + preq->nr_sects += seg[n].nsec; + } + diff --git a/debian/patches/bugfix/all/xen-netback-don-t-use-last-request-to-determine-mini.patch b/debian/patches/bugfix/all/xen-netback-don-t-use-last-request-to-determine-mini.patch new file mode 100644 index 000000000..f21dedd55 --- /dev/null +++ b/debian/patches/bugfix/all/xen-netback-don-t-use-last-request-to-determine-mini.patch @@ -0,0 +1,35 @@ +From: David Vrabel +Date: Fri, 30 Oct 2015 15:16:01 +0000 +Subject: [2/7] xen-netback: don't use last request to determine minimum Tx + credit +Origin: https://git.kernel.org/linus/0f589967a73f1f30ab4ac4dd9ce0bb399b4d6357 + +The last from guest transmitted request gives no indication about the +minimum amount of credit that the guest might need to send a packet +since the last packet might have been a small one. + +Instead allow for the worst case 128 KiB packet. + +This is part of XSA155. + +CC: stable@vger.kernel.org +Reviewed-by: Wei Liu +Signed-off-by: David Vrabel +Signed-off-by: Konrad Rzeszutek Wilk +--- + drivers/net/xen-netback/netback.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/net/xen-netback/netback.c ++++ b/drivers/net/xen-netback/netback.c +@@ -636,9 +636,7 @@ static void tx_add_credit(struct xenvif_ + * Allow a burst big enough to transmit a jumbo packet of up to 128kB. + * Otherwise the interface can seize up due to insufficient credit. + */ +- max_burst = RING_GET_REQUEST(&queue->tx, queue->tx.req_cons)->size; +- max_burst = min(max_burst, 131072UL); +- max_burst = max(max_burst, queue->credit_bytes); ++ max_burst = max(131072UL, queue->credit_bytes); + + /* Take care that adding a new chunk of credit doesn't wrap to zero. */ + max_credit = queue->remaining_credit + queue->credit_bytes; diff --git a/debian/patches/bugfix/all/xen-netback-use-ring_copy_request-throughout.patch b/debian/patches/bugfix/all/xen-netback-use-ring_copy_request-throughout.patch new file mode 100644 index 000000000..40f9d9d97 --- /dev/null +++ b/debian/patches/bugfix/all/xen-netback-use-ring_copy_request-throughout.patch @@ -0,0 +1,126 @@ +From: David Vrabel +Date: Fri, 30 Oct 2015 15:17:06 +0000 +Subject: [3/7] xen-netback: use RING_COPY_REQUEST() throughout +Origin: https://git.kernel.org/linus/68a33bfd8403e4e22847165d149823a2e0e67c9c + +Instead of open-coding memcpy()s and directly accessing Tx and Rx +requests, use the new RING_COPY_REQUEST() that ensures the local copy +is correct. + +This is more than is strictly necessary for guest Rx requests since +only the id and gref fields are used and it is harmless if the +frontend modifies these. + +This is part of XSA155. + +CC: stable@vger.kernel.org +Reviewed-by: Wei Liu +Signed-off-by: David Vrabel +Signed-off-by: Konrad Rzeszutek Wilk +--- + drivers/net/xen-netback/netback.c | 30 ++++++++++++++---------------- + 1 file changed, 14 insertions(+), 16 deletions(-) + +--- a/drivers/net/xen-netback/netback.c ++++ b/drivers/net/xen-netback/netback.c +@@ -258,18 +258,18 @@ static struct xenvif_rx_meta *get_next_r + struct netrx_pending_operations *npo) + { + struct xenvif_rx_meta *meta; +- struct xen_netif_rx_request *req; ++ struct xen_netif_rx_request req; + +- req = RING_GET_REQUEST(&queue->rx, queue->rx.req_cons++); ++ RING_COPY_REQUEST(&queue->rx, queue->rx.req_cons++, &req); + + meta = npo->meta + npo->meta_prod++; + meta->gso_type = XEN_NETIF_GSO_TYPE_NONE; + meta->gso_size = 0; + meta->size = 0; +- meta->id = req->id; ++ meta->id = req.id; + + npo->copy_off = 0; +- npo->copy_gref = req->gref; ++ npo->copy_gref = req.gref; + + return meta; + } +@@ -381,7 +381,7 @@ static int xenvif_gop_skb(struct sk_buff + struct xenvif *vif = netdev_priv(skb->dev); + int nr_frags = skb_shinfo(skb)->nr_frags; + int i; +- struct xen_netif_rx_request *req; ++ struct xen_netif_rx_request req; + struct xenvif_rx_meta *meta; + unsigned char *data; + int head = 1; +@@ -400,15 +400,15 @@ static int xenvif_gop_skb(struct sk_buff + + /* Set up a GSO prefix descriptor, if necessary */ + if ((1 << gso_type) & vif->gso_prefix_mask) { +- req = RING_GET_REQUEST(&queue->rx, queue->rx.req_cons++); ++ RING_COPY_REQUEST(&queue->rx, queue->rx.req_cons++, &req); + meta = npo->meta + npo->meta_prod++; + meta->gso_type = gso_type; + meta->gso_size = skb_shinfo(skb)->gso_size; + meta->size = 0; +- meta->id = req->id; ++ meta->id = req.id; + } + +- req = RING_GET_REQUEST(&queue->rx, queue->rx.req_cons++); ++ RING_COPY_REQUEST(&queue->rx, queue->rx.req_cons++, &req); + meta = npo->meta + npo->meta_prod++; + + if ((1 << gso_type) & vif->gso_mask) { +@@ -420,9 +420,9 @@ static int xenvif_gop_skb(struct sk_buff + } + + meta->size = 0; +- meta->id = req->id; ++ meta->id = req.id; + npo->copy_off = 0; +- npo->copy_gref = req->gref; ++ npo->copy_gref = req.gref; + + data = skb->data; + while (data < skb_tail_pointer(skb)) { +@@ -666,7 +666,7 @@ static void xenvif_tx_err(struct xenvif_ + spin_unlock_irqrestore(&queue->response_lock, flags); + if (cons == end) + break; +- txp = RING_GET_REQUEST(&queue->tx, cons++); ++ RING_COPY_REQUEST(&queue->tx, cons++, txp); + } while (1); + queue->tx.req_cons = cons; + } +@@ -733,8 +733,7 @@ static int xenvif_count_requests(struct + if (drop_err) + txp = &dropped_tx; + +- memcpy(txp, RING_GET_REQUEST(&queue->tx, cons + slots), +- sizeof(*txp)); ++ RING_COPY_REQUEST(&queue->tx, cons + slots, txp); + + /* If the guest submitted a frame >= 64 KiB then + * first->size overflowed and following slots will +@@ -1067,8 +1066,7 @@ static int xenvif_get_extras(struct xenv + return -EBADR; + } + +- memcpy(&extra, RING_GET_REQUEST(&queue->tx, cons), +- sizeof(extra)); ++ RING_COPY_REQUEST(&queue->tx, cons, &extra); + if (unlikely(!extra.type || + extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) { + queue->tx.req_cons = ++cons; +@@ -1277,7 +1275,7 @@ static void xenvif_tx_build_gops(struct + + idx = queue->tx.req_cons; + rmb(); /* Ensure that we see the request before we copy it. */ +- memcpy(&txreq, RING_GET_REQUEST(&queue->tx, idx), sizeof(txreq)); ++ RING_COPY_REQUEST(&queue->tx, idx, &txreq); + + /* Credit-based scheduling. */ + if (txreq.size > queue->remaining_credit && diff --git a/debian/patches/bugfix/all/xen-pciback-save-xen_pci_op-commands-before-processi.patch b/debian/patches/bugfix/all/xen-pciback-save-xen_pci_op-commands-before-processi.patch new file mode 100644 index 000000000..101afe8e3 --- /dev/null +++ b/debian/patches/bugfix/all/xen-pciback-save-xen_pci_op-commands-before-processi.patch @@ -0,0 +1,77 @@ +From: Konrad Rzeszutek Wilk +Date: Mon, 16 Nov 2015 12:40:48 -0500 +Subject: [7/7] xen/pciback: Save xen_pci_op commands before processing it +Origin: https://git.kernel.org/linus/8135cf8b092723dbfcc611fe6fdcb3a36c9951c5 + +Double fetch vulnerabilities that happen when a variable is +fetched twice from shared memory but a security check is only +performed the first time. + +The xen_pcibk_do_op function performs a switch statements on the op->cmd +value which is stored in shared memory. Interestingly this can result +in a double fetch vulnerability depending on the performed compiler +optimization. + +This patch fixes it by saving the xen_pci_op command before +processing it. We also use 'barrier' to make sure that the +compiler does not perform any optimization. + +This is part of XSA155. + +CC: stable@vger.kernel.org +Reviewed-by: Konrad Rzeszutek Wilk +Signed-off-by: Jan Beulich +Signed-off-by: David Vrabel +Signed-off-by: Konrad Rzeszutek Wilk +--- + drivers/xen/xen-pciback/pciback.h | 1 + + drivers/xen/xen-pciback/pciback_ops.c | 15 ++++++++++++++- + 2 files changed, 15 insertions(+), 1 deletion(-) + +diff --git a/drivers/xen/xen-pciback/pciback.h b/drivers/xen/xen-pciback/pciback.h +index 58e38d5..4d529f3 100644 +--- a/drivers/xen/xen-pciback/pciback.h ++++ b/drivers/xen/xen-pciback/pciback.h +@@ -37,6 +37,7 @@ struct xen_pcibk_device { + struct xen_pci_sharedinfo *sh_info; + unsigned long flags; + struct work_struct op_work; ++ struct xen_pci_op op; + }; + + struct xen_pcibk_dev_data { +diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c +index c4a0666..a0e0e3e 100644 +--- a/drivers/xen/xen-pciback/pciback_ops.c ++++ b/drivers/xen/xen-pciback/pciback_ops.c +@@ -298,9 +298,11 @@ void xen_pcibk_do_op(struct work_struct *data) + container_of(data, struct xen_pcibk_device, op_work); + struct pci_dev *dev; + struct xen_pcibk_dev_data *dev_data = NULL; +- struct xen_pci_op *op = &pdev->sh_info->op; ++ struct xen_pci_op *op = &pdev->op; + int test_intx = 0; + ++ *op = pdev->sh_info->op; ++ barrier(); + dev = xen_pcibk_get_pci_dev(pdev, op->domain, op->bus, op->devfn); + + if (dev == NULL) +@@ -342,6 +344,17 @@ void xen_pcibk_do_op(struct work_struct *data) + if ((dev_data->enable_intx != test_intx)) + xen_pcibk_control_isr(dev, 0 /* no reset */); + } ++ pdev->sh_info->op.err = op->err; ++ pdev->sh_info->op.value = op->value; ++#ifdef CONFIG_PCI_MSI ++ if (op->cmd == XEN_PCI_OP_enable_msix && op->err == 0) { ++ unsigned int i; ++ ++ for (i = 0; i < op->value; i++) ++ pdev->sh_info->op.msix_entries[i].vector = ++ op->msix_entries[i].vector; ++ } ++#endif + /* Tell the driver domain that we're done. */ + wmb(); + clear_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags); diff --git a/debian/patches/bugfix/all/xen-scsiback-safely-copy-requests.patch b/debian/patches/bugfix/all/xen-scsiback-safely-copy-requests.patch new file mode 100644 index 000000000..4f975df6a --- /dev/null +++ b/debian/patches/bugfix/all/xen-scsiback-safely-copy-requests.patch @@ -0,0 +1,34 @@ +From: David Vrabel +Date: Mon, 16 Nov 2015 18:02:32 +0000 +Subject: [6/7] xen-scsiback: safely copy requests +Origin: https://git.kernel.org/linus/be69746ec12f35b484707da505c6c76ff06f97dc + +The copy of the ring request was lacking a following barrier(), +potentially allowing the compiler to optimize the copy away. + +Use RING_COPY_REQUEST() to ensure the request is copied to local +memory. + +This is part of XSA155. + +CC: stable@vger.kernel.org +Reviewed-by: Juergen Gross +Signed-off-by: David Vrabel +Signed-off-by: Konrad Rzeszutek Wilk +--- + drivers/xen/xen-scsiback.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c +index 9eeefd7..2af9aa8 100644 +--- a/drivers/xen/xen-scsiback.c ++++ b/drivers/xen/xen-scsiback.c +@@ -727,7 +727,7 @@ static int scsiback_do_cmd_fn(struct vscsibk_info *info) + if (!pending_req) + return 1; + +- ring_req = *RING_GET_REQUEST(ring, rc); ++ RING_COPY_REQUEST(ring, rc, &ring_req); + ring->req_cons = ++rc; + + err = prepare_pending_reqs(info, &ring_req, pending_req); diff --git a/debian/patches/series b/debian/patches/series index c202faa2e..6205f82a9 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -109,3 +109,10 @@ bugfix/all/ovl-fix-permission-checking-for-setattr.patch bugfix/all/block-ensure-to-split-after-potentially-bouncing-a-b.patch bugfix/all/pptp-verify-sockaddr_len-in-pptp_bind-and-pptp_conne.patch bugfix/all/bluetooth-validate-socket-address-length-in-sco_sock.patch +bugfix/all/xen-add-ring_copy_request.patch +bugfix/all/xen-netback-don-t-use-last-request-to-determine-mini.patch +bugfix/all/xen-netback-use-ring_copy_request-throughout.patch +bugfix/all/xen-blkback-only-read-request-operation-from-shared-.patch +bugfix/all/xen-blkback-read-from-indirect-descriptors-only-once.patch +bugfix/all/xen-scsiback-safely-copy-requests.patch +bugfix/all/xen-pciback-save-xen_pci_op-commands-before-processi.patch