diff options
author | Natanael Copa <ncopa@alpinelinux.org> | 2013-02-05 15:59:04 +0000 |
---|---|---|
committer | Natanael Copa <ncopa@alpinelinux.org> | 2013-02-05 16:04:20 +0000 |
commit | 03f76f442fe7e358e07f507978eea46777af4268 (patch) | |
tree | d07069ef7259bc0b21a0f848ca8c08392860bd44 /main/linux-grsec | |
parent | 90e8b091cd1484e0a7b28ee905bd792e4b12d56c (diff) | |
download | aports-03f76f442fe7e358e07f507978eea46777af4268.tar.bz2 aports-03f76f442fe7e358e07f507978eea46777af4268.tar.xz |
main/linux-grsec: various xen security fixes
Diffstat (limited to 'main/linux-grsec')
5 files changed, 470 insertions, 1 deletions
diff --git a/main/linux-grsec/APKBUILD b/main/linux-grsec/APKBUILD index c0b6f84f97..cb719e4f8a 100644 --- a/main/linux-grsec/APKBUILD +++ b/main/linux-grsec/APKBUILD @@ -4,7 +4,7 @@ _flavor=grsec pkgname=linux-${_flavor} pkgver=3.6.11 _kernver=3.6 -pkgrel=9 +pkgrel=10 pkgdesc="Linux kernel with grsecurity" url=http://grsecurity.net depends="mkinitfs linux-firmware" @@ -23,6 +23,12 @@ source="http://ftp.kernel.org/pub/linux/kernel/v3.x/linux-$_kernver.tar.xz 0001-r8169-remove-the-obsolete-and-incorrect-AMD-workarou.patch r8169-fix-vlan-tag-reordering.patch + xsa39-pvops-0001-xen-netback-shutdown-the-ring-if-it-contains-garbage.patch + xsa39-pvops-0002-xen-netback-don-t-leak-pages-on-failure-in-xen_netbk.patch + xsa39-pvops-0003-xen-netback-free-already-allocated-memory-on-failure.patch + xsa39-pvops-0004-netback-correct-netbk_tx_err-to-handle-wrap-around.patch + + kernelconfig.x86 kernelconfig.x86_64 " @@ -152,5 +158,9 @@ daf2cbb558588c49c138fe9ca2482b64 r8169-num-rx-desc.patch d9b4a528e722d10ba53034ebd440c31b ipv4-remove-output-route-check-in-ipv4_mtu.patch 63468b44e34fa19237e0a2a1f6737b14 0001-r8169-remove-the-obsolete-and-incorrect-AMD-workarou.patch 44a37e1289e1056300574848aea8bd31 r8169-fix-vlan-tag-reordering.patch +706652ed6c17c5f7bb46a6c8318f9e75 xsa39-pvops-0001-xen-netback-shutdown-the-ring-if-it-contains-garbage.patch +286101482a2e4b7d8c0dff16af36b3e9 xsa39-pvops-0002-xen-netback-don-t-leak-pages-on-failure-in-xen_netbk.patch +89dbb0886c9d17c3c4a5ff4f1443e936 xsa39-pvops-0003-xen-netback-free-already-allocated-memory-on-failure.patch +bce9f08c86570a0a86ef36f1d2e7a2dd xsa39-pvops-0004-netback-correct-netbk_tx_err-to-handle-wrap-around.patch 373db5888708938c6b1baed6da781fcb kernelconfig.x86 190788fb10e79abce9d570d5e87ec3b4 kernelconfig.x86_64" diff --git a/main/linux-grsec/xsa39-pvops-0001-xen-netback-shutdown-the-ring-if-it-contains-garbage.patch b/main/linux-grsec/xsa39-pvops-0001-xen-netback-shutdown-the-ring-if-it-contains-garbage.patch new file mode 100644 index 0000000000..3f983028f2 --- /dev/null +++ b/main/linux-grsec/xsa39-pvops-0001-xen-netback-shutdown-the-ring-if-it-contains-garbage.patch @@ -0,0 +1,253 @@ +From 7dd7ce44593a8c4c715fa665027af8e07245c8cf Mon Sep 17 00:00:00 2001 +From: Ian Campbell <ian.campbell@citrix.com> +Date: Fri, 11 Jan 2013 14:26:29 +0000 +Subject: [PATCH 1/4] xen/netback: shutdown the ring if it contains garbage. + +A buggy or malicious frontend should not be able to confuse netback. +If we spot anything which is not as it should be then shutdown the +device and don't try to continue with the ring in a potentially +hostile state. Well behaved and non-hostile frontends will not be +penalised. + +As well as making the existing checks for such errors fatal also add a +new check that ensures that there isn't an insane number of requests +on the ring (i.e. more than would fit in the ring). If the ring +contains garbage then previously is was possible to loop over this +insane number, getting an error each time and therefore not generating +any more pending requests and therefore not exiting the loop in +xen_netbk_tx_build_gops for an externded period. + +Also turn various netdev_dbg calls which no precipitate a fatal error +into netdev_err, they are rate limited because the device is shutdown +afterwards. + +This fixes at least one known DoS/softlockup of the backend domain. + +Signed-off-by: Ian Campbell <ian.campbell@citrix.com> +Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> +Acked-by: Jan Beulich <JBeulich@suse.com> +--- + drivers/net/xen-netback/common.h | 3 ++ + drivers/net/xen-netback/interface.c | 23 ++++++++----- + drivers/net/xen-netback/netback.c | 63 +++++++++++++++++++++++++--------- + 3 files changed, 63 insertions(+), 26 deletions(-) + +diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h +index 94b79c3..9d7f172 100644 +--- a/drivers/net/xen-netback/common.h ++++ b/drivers/net/xen-netback/common.h +@@ -151,6 +151,9 @@ void xen_netbk_queue_tx_skb(struct xenvif *vif, struct sk_buff *skb); + /* Notify xenvif that ring now has space to send an skb to the frontend */ + void xenvif_notify_tx_completion(struct xenvif *vif); + ++/* Prevent the device from generating any further traffic. */ ++void xenvif_carrier_off(struct xenvif *vif); ++ + /* Returns number of ring slots required to send an skb to the frontend */ + unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb); + +diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c +index b7d41f8..b8c5193 100644 +--- a/drivers/net/xen-netback/interface.c ++++ b/drivers/net/xen-netback/interface.c +@@ -343,17 +343,22 @@ err: + return err; + } + +-void xenvif_disconnect(struct xenvif *vif) ++void xenvif_carrier_off(struct xenvif *vif) + { + struct net_device *dev = vif->dev; +- if (netif_carrier_ok(dev)) { +- rtnl_lock(); +- netif_carrier_off(dev); /* discard queued packets */ +- if (netif_running(dev)) +- xenvif_down(vif); +- rtnl_unlock(); +- xenvif_put(vif); +- } ++ ++ rtnl_lock(); ++ netif_carrier_off(dev); /* discard queued packets */ ++ if (netif_running(dev)) ++ xenvif_down(vif); ++ rtnl_unlock(); ++ xenvif_put(vif); ++} ++ ++void xenvif_disconnect(struct xenvif *vif) ++{ ++ if (netif_carrier_ok(vif->dev)) ++ xenvif_carrier_off(vif); + + atomic_dec(&vif->refcnt); + wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0); +diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c +index f2d6b78..1a449f9 100644 +--- a/drivers/net/xen-netback/netback.c ++++ b/drivers/net/xen-netback/netback.c +@@ -888,6 +888,13 @@ static void netbk_tx_err(struct xenvif *vif, + xenvif_put(vif); + } + ++static void netbk_fatal_tx_err(struct xenvif *vif) ++{ ++ netdev_err(vif->dev, "fatal error; disabling device\n"); ++ xenvif_carrier_off(vif); ++ xenvif_put(vif); ++} ++ + static int netbk_count_requests(struct xenvif *vif, + struct xen_netif_tx_request *first, + struct xen_netif_tx_request *txp, +@@ -901,19 +908,22 @@ static int netbk_count_requests(struct xenvif *vif, + + do { + if (frags >= work_to_do) { +- netdev_dbg(vif->dev, "Need more frags\n"); ++ netdev_err(vif->dev, "Need more frags\n"); ++ netbk_fatal_tx_err(vif); + return -frags; + } + + if (unlikely(frags >= MAX_SKB_FRAGS)) { +- netdev_dbg(vif->dev, "Too many frags\n"); ++ netdev_err(vif->dev, "Too many frags\n"); ++ netbk_fatal_tx_err(vif); + return -frags; + } + + memcpy(txp, RING_GET_REQUEST(&vif->tx, cons + frags), + sizeof(*txp)); + if (txp->size > first->size) { +- netdev_dbg(vif->dev, "Frags galore\n"); ++ netdev_err(vif->dev, "Frag is bigger than frame.\n"); ++ netbk_fatal_tx_err(vif); + return -frags; + } + +@@ -921,8 +931,9 @@ static int netbk_count_requests(struct xenvif *vif, + frags++; + + if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) { +- netdev_dbg(vif->dev, "txp->offset: %x, size: %u\n", ++ netdev_err(vif->dev, "txp->offset: %x, size: %u\n", + txp->offset, txp->size); ++ netbk_fatal_tx_err(vif); + return -frags; + } + } while ((txp++)->flags & XEN_NETTXF_more_data); +@@ -1095,7 +1106,8 @@ static int xen_netbk_get_extras(struct xenvif *vif, + + do { + if (unlikely(work_to_do-- <= 0)) { +- netdev_dbg(vif->dev, "Missing extra info\n"); ++ netdev_err(vif->dev, "Missing extra info\n"); ++ netbk_fatal_tx_err(vif); + return -EBADR; + } + +@@ -1104,8 +1116,9 @@ static int xen_netbk_get_extras(struct xenvif *vif, + if (unlikely(!extra.type || + extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) { + vif->tx.req_cons = ++cons; +- netdev_dbg(vif->dev, ++ netdev_err(vif->dev, + "Invalid extra type: %d\n", extra.type); ++ netbk_fatal_tx_err(vif); + return -EINVAL; + } + +@@ -1121,13 +1134,15 @@ static int netbk_set_skb_gso(struct xenvif *vif, + struct xen_netif_extra_info *gso) + { + if (!gso->u.gso.size) { +- netdev_dbg(vif->dev, "GSO size must not be zero.\n"); ++ netdev_err(vif->dev, "GSO size must not be zero.\n"); ++ netbk_fatal_tx_err(vif); + return -EINVAL; + } + + /* Currently only TCPv4 S.O. is supported. */ + if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) { +- netdev_dbg(vif->dev, "Bad GSO type %d.\n", gso->u.gso.type); ++ netdev_err(vif->dev, "Bad GSO type %d.\n", gso->u.gso.type); ++ netbk_fatal_tx_err(vif); + return -EINVAL; + } + +@@ -1264,9 +1279,26 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) + + /* Get a netif from the list with work to do. */ + vif = poll_net_schedule_list(netbk); ++ /* ++ * This can sometimes happen because the test of ++ * list_empty(net_schedule_list) at the top of the ++ * loop is unlocked. Just go back and have another ++ * look. ++ */ + if (!vif) + continue; + ++ if (vif->tx.sring->req_prod - vif->tx.req_cons > ++ XEN_NETIF_TX_RING_SIZE) { ++ netdev_err(vif->dev, ++ "Impossible number of requests. " ++ "req_prod %d, req_cons %d, size %ld\n", ++ vif->tx.sring->req_prod, vif->tx.req_cons, ++ XEN_NETIF_TX_RING_SIZE); ++ netbk_fatal_tx_err(vif); ++ continue; ++ } ++ + RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, work_to_do); + if (!work_to_do) { + xenvif_put(vif); +@@ -1294,17 +1326,14 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) + work_to_do = xen_netbk_get_extras(vif, extras, + work_to_do); + idx = vif->tx.req_cons; +- if (unlikely(work_to_do < 0)) { +- netbk_tx_err(vif, &txreq, idx); ++ if (unlikely(work_to_do < 0)) + continue; +- } + } + + ret = netbk_count_requests(vif, &txreq, txfrags, work_to_do); +- if (unlikely(ret < 0)) { +- netbk_tx_err(vif, &txreq, idx - ret); ++ if (unlikely(ret < 0)) + continue; +- } ++ + idx += ret; + + if (unlikely(txreq.size < ETH_HLEN)) { +@@ -1316,11 +1345,11 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) + + /* No crossing a page as the payload mustn't fragment. */ + if (unlikely((txreq.offset + txreq.size) > PAGE_SIZE)) { +- netdev_dbg(vif->dev, ++ netdev_err(vif->dev, + "txreq.offset: %x, size: %u, end: %lu\n", + txreq.offset, txreq.size, + (txreq.offset&~PAGE_MASK) + txreq.size); +- netbk_tx_err(vif, &txreq, idx); ++ netbk_fatal_tx_err(vif); + continue; + } + +@@ -1348,8 +1377,8 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) + gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1]; + + if (netbk_set_skb_gso(vif, skb, gso)) { ++ /* Failure in netbk_set_skb_gso is fatal. */ + kfree_skb(skb); +- netbk_tx_err(vif, &txreq, idx); + continue; + } + } +-- +1.7.2.5 + diff --git a/main/linux-grsec/xsa39-pvops-0002-xen-netback-don-t-leak-pages-on-failure-in-xen_netbk.patch b/main/linux-grsec/xsa39-pvops-0002-xen-netback-don-t-leak-pages-on-failure-in-xen_netbk.patch new file mode 100644 index 0000000000..686f38bb7a --- /dev/null +++ b/main/linux-grsec/xsa39-pvops-0002-xen-netback-don-t-leak-pages-on-failure-in-xen_netbk.patch @@ -0,0 +1,132 @@ +From 90420631d2b78aca28c94beb66b25447e57a8dd4 Mon Sep 17 00:00:00 2001 +From: Ian Campbell <ian.campbell@citrix.com> +Date: Mon, 14 Jan 2013 12:20:04 +0000 +Subject: [PATCH 2/4] xen/netback: don't leak pages on failure in xen_netbk_tx_check_gop. + +Signed-off-by: Matthew Daley <mattjd@gmail.com> +Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> +Acked-by: Ian Campbell <ian.campbell@citrix.com> +Acked-by: Jan Beulich <JBeulich@suse.com> +--- + drivers/net/xen-netback/netback.c | 38 ++++++++++++------------------------ + 1 files changed, 13 insertions(+), 25 deletions(-) + +diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c +index 1a449f9..975241e 100644 +--- a/drivers/net/xen-netback/netback.c ++++ b/drivers/net/xen-netback/netback.c +@@ -147,7 +147,8 @@ void xen_netbk_remove_xenvif(struct xenvif *vif) + atomic_dec(&netbk->netfront_count); + } + +-static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx); ++static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx, ++ u8 status); + static void make_tx_response(struct xenvif *vif, + struct xen_netif_tx_request *txp, + s8 st); +@@ -1007,30 +1008,20 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, + { + struct gnttab_copy *gop = *gopp; + u16 pending_idx = *((u16 *)skb->data); +- struct pending_tx_info *pending_tx_info = netbk->pending_tx_info; +- struct xenvif *vif = pending_tx_info[pending_idx].vif; +- struct xen_netif_tx_request *txp; + struct skb_shared_info *shinfo = skb_shinfo(skb); + int nr_frags = shinfo->nr_frags; + int i, err, start; + + /* Check status of header. */ + err = gop->status; +- if (unlikely(err)) { +- pending_ring_idx_t index; +- index = pending_index(netbk->pending_prod++); +- txp = &pending_tx_info[pending_idx].req; +- make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); +- netbk->pending_ring[index] = pending_idx; +- xenvif_put(vif); +- } ++ if (unlikely(err)) ++ xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); + + /* Skip first skb fragment if it is on same page as header fragment. */ + start = (frag_get_pending_idx(&shinfo->frags[0]) == pending_idx); + + for (i = start; i < nr_frags; i++) { + int j, newerr; +- pending_ring_idx_t index; + + pending_idx = frag_get_pending_idx(&shinfo->frags[i]); + +@@ -1039,16 +1030,12 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, + if (likely(!newerr)) { + /* Had a previous error? Invalidate this fragment. */ + if (unlikely(err)) +- xen_netbk_idx_release(netbk, pending_idx); ++ xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); + continue; + } + + /* Error on this fragment: respond to client with an error. */ +- txp = &netbk->pending_tx_info[pending_idx].req; +- make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); +- index = pending_index(netbk->pending_prod++); +- netbk->pending_ring[index] = pending_idx; +- xenvif_put(vif); ++ xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); + + /* Not the first error? Preceding frags already invalidated. */ + if (err) +@@ -1056,10 +1043,10 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, + + /* First error: invalidate header and preceding fragments. */ + pending_idx = *((u16 *)skb->data); +- xen_netbk_idx_release(netbk, pending_idx); ++ xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); + for (j = start; j < i; j++) { + pending_idx = frag_get_pending_idx(&shinfo->frags[j]); +- xen_netbk_idx_release(netbk, pending_idx); ++ xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); + } + + /* Remember the error: invalidate all subsequent fragments. */ +@@ -1093,7 +1080,7 @@ static void xen_netbk_fill_frags(struct xen_netbk *netbk, struct sk_buff *skb) + + /* Take an extra reference to offset xen_netbk_idx_release */ + get_page(netbk->mmap_pages[pending_idx]); +- xen_netbk_idx_release(netbk, pending_idx); ++ xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); + } + } + +@@ -1477,7 +1464,7 @@ static void xen_netbk_tx_submit(struct xen_netbk *netbk) + txp->size -= data_len; + } else { + /* Schedule a response immediately. */ +- xen_netbk_idx_release(netbk, pending_idx); ++ xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); + } + + if (txp->flags & XEN_NETTXF_csum_blank) +@@ -1529,7 +1516,8 @@ static void xen_netbk_tx_action(struct xen_netbk *netbk) + xen_netbk_tx_submit(netbk); + } + +-static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx) ++static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx, ++ u8 status) + { + struct xenvif *vif; + struct pending_tx_info *pending_tx_info; +@@ -1543,7 +1531,7 @@ static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx) + + vif = pending_tx_info->vif; + +- make_tx_response(vif, &pending_tx_info->req, XEN_NETIF_RSP_OKAY); ++ make_tx_response(vif, &pending_tx_info->req, status); + + index = pending_index(netbk->pending_prod++); + netbk->pending_ring[index] = pending_idx; +-- +1.7.2.5 + diff --git a/main/linux-grsec/xsa39-pvops-0003-xen-netback-free-already-allocated-memory-on-failure.patch b/main/linux-grsec/xsa39-pvops-0003-xen-netback-free-already-allocated-memory-on-failure.patch new file mode 100644 index 0000000000..1c71801958 --- /dev/null +++ b/main/linux-grsec/xsa39-pvops-0003-xen-netback-free-already-allocated-memory-on-failure.patch @@ -0,0 +1,47 @@ +From b6b1f17aa44acfe1024968bafb1d1fe7704a749a Mon Sep 17 00:00:00 2001 +From: Ian Campbell <ian.campbell@citrix.com> +Date: Mon, 14 Jan 2013 12:51:22 +0000 +Subject: [PATCH 3/4] xen/netback: free already allocated memory on failure in xen_netbk_get_requests + +Signed-off-by: Ian Campbell <ian.campbell@citrix.com> +--- + drivers/net/xen-netback/netback.c | 16 +++++++++++++++- + 1 files changed, 15 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c +index 975241e..1a99288 100644 +--- a/drivers/net/xen-netback/netback.c ++++ b/drivers/net/xen-netback/netback.c +@@ -978,7 +978,7 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk, + pending_idx = netbk->pending_ring[index]; + page = xen_netbk_alloc_page(netbk, skb, pending_idx); + if (!page) +- return NULL; ++ goto err; + + gop->source.u.ref = txp->gref; + gop->source.domid = vif->domid; +@@ -1000,6 +1000,20 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk, + } + + return gop; ++err: ++ /* ++ * Unwind, freeing all pages and sending error ++ * reponses. ++ */ ++ while (i-- > start) { ++ xen_netbk_idx_release(netbk, frag_get_pending_idx(&frags[i]), ++ XEN_NETIF_RSP_ERROR); ++ } ++ /* The head too, if necessary. */ ++ if (start) ++ xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); ++ ++ return NULL; + } + + static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, +-- +1.7.2.5 + diff --git a/main/linux-grsec/xsa39-pvops-0004-netback-correct-netbk_tx_err-to-handle-wrap-around.patch b/main/linux-grsec/xsa39-pvops-0004-netback-correct-netbk_tx_err-to-handle-wrap-around.patch new file mode 100644 index 0000000000..c76a2c40eb --- /dev/null +++ b/main/linux-grsec/xsa39-pvops-0004-netback-correct-netbk_tx_err-to-handle-wrap-around.patch @@ -0,0 +1,27 @@ +From ea5e3c1e8fd9ffe6080e01af7769a9fa420cc62e Mon Sep 17 00:00:00 2001 +From: Ian Campbell <ian.campbell@citrix.com> +Date: Mon, 14 Jan 2013 13:32:31 +0000 +Subject: [PATCH 4/4] netback: correct netbk_tx_err to handle wrap around. + +Signed-off-by: Ian Campbell <ian.campbell@citrix.com> +Acked-by: Jan Beulich <JBeulich@suse.com> +--- + drivers/net/xen-netback/netback.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c +index 1a99288..28d5e06 100644 +--- a/drivers/net/xen-netback/netback.c ++++ b/drivers/net/xen-netback/netback.c +@@ -880,7 +880,7 @@ static void netbk_tx_err(struct xenvif *vif, + + do { + make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); +- if (cons >= end) ++ if (cons == end) + break; + txp = RING_GET_REQUEST(&vif->tx, cons++); + } while (1); +-- +1.7.2.5 + |