[kernel] r19809 - in dists/squeeze-security/linux-2.6/debian: . patches/features/all/xen patches/series
Dann Frazier
dannf at alioth.debian.org
Thu Feb 14 09:33:01 UTC 2013
Author: dannf
Date: Thu Feb 14 09:33:00 2013
New Revision: 19809
Log:
xen: netback: shutdown the ring if it contains garbage (CVE-2013-0216)
Added:
dists/squeeze-security/linux-2.6/debian/patches/features/all/xen/xsa39-classic-0001-xen-netback-garbage-ring.patch
dists/squeeze-security/linux-2.6/debian/patches/series/46squeeze1-extra
Modified:
dists/squeeze-security/linux-2.6/debian/changelog
Modified: dists/squeeze-security/linux-2.6/debian/changelog
==============================================================================
--- dists/squeeze-security/linux-2.6/debian/changelog Thu Feb 14 07:22:42 2013 (r19808)
+++ dists/squeeze-security/linux-2.6/debian/changelog Thu Feb 14 09:33:00 2013 (r19809)
@@ -9,6 +9,7 @@
* net: sk_add_backlog() take rmem_alloc into account (CVE-2010-4805)
* ipv6: discard overlapping fragment (CVE-2012-4444)
* x86/msr: Add capabilities check (CVE-2013-0268)
+ * xen: netback: shutdown the ring if it contains garbage (CVE-2013-0216)
-- dann frazier <dannf at debian.org> Mon, 22 Oct 2012 20:34:13 -0500
Added: dists/squeeze-security/linux-2.6/debian/patches/features/all/xen/xsa39-classic-0001-xen-netback-garbage-ring.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/squeeze-security/linux-2.6/debian/patches/features/all/xen/xsa39-classic-0001-xen-netback-garbage-ring.patch Thu Feb 14 09:33:00 2013 (r19809)
@@ -0,0 +1,244 @@
+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 at citrix.com>
+Signed-off-by: Jan Beulich <JBeulich at suse.com>
+[dannf: backported to Debian's 2.6.32]
+
+diff -urpN a/drivers/xen/netback/common.h b/drivers/xen/netback/common.h
+--- a/drivers/xen/netback/common.h 2013-02-14 00:22:26.000000000 -0700
++++ b/drivers/xen/netback/common.h 2013-02-14 00:29:04.000000000 -0700
+@@ -221,6 +221,9 @@ int netif_be_start_xmit(struct sk_buff *
+ struct net_device_stats *netif_be_get_stats(struct net_device *dev);
+ irqreturn_t netif_be_int(int irq, void *dev_id);
+
++/* Prevent the device from generating any further traffic. */
++void xenvif_carrier_off(struct xen_netif *netif);
++
+ static inline int netbk_can_queue(struct net_device *dev)
+ {
+ struct xen_netif *netif = netdev_priv(dev);
+diff -urpN a/drivers/xen/netback/interface.c b/drivers/xen/netback/interface.c
+--- a/drivers/xen/netback/interface.c 2013-02-14 00:22:26.000000000 -0700
++++ b/drivers/xen/netback/interface.c 2013-02-14 00:39:19.000000000 -0700
+@@ -442,17 +442,21 @@ err_rx:
+ return err;
+ }
+
++void xenvif_carrier_off(struct xen_netif *netif)
++{
++ rtnl_lock();
++ netback_carrier_off(netif);
++ netif_carrier_off(netif->dev); /* discard queued packets */
++ if (netif_running(netif->dev))
++ __netif_down(netif);
++ rtnl_unlock();
++ netif_put(netif);
++}
++
+ void netif_disconnect(struct xen_netif *netif)
+ {
+- if (netback_carrier_ok(netif)) {
+- rtnl_lock();
+- netback_carrier_off(netif);
+- netif_carrier_off(netif->dev); /* discard queued packets */
+- if (netif_running(netif->dev))
+- __netif_down(netif);
+- rtnl_unlock();
+- netif_put(netif);
+- }
++ if (netback_carrier_ok(netif))
++ xenvif_carrier_off(netif);
+
+ atomic_dec(&netif->refcnt);
+ wait_event(netif->waiting_to_free, atomic_read(&netif->refcnt) == 0);
+diff -urpN a/drivers/xen/netback/netback.c b/drivers/xen/netback/netback.c
+--- a/drivers/xen/netback/netback.c 2013-02-14 00:22:26.000000000 -0700
++++ b/drivers/xen/netback/netback.c 2013-02-14 00:38:04.000000000 -0700
+@@ -986,6 +986,14 @@ static void netbk_tx_err(struct xen_neti
+ netif_put(netif);
+ }
+
++static void netbk_fatal_tx_err(struct xen_netif *netif)
++{
++ printk(KERN_ERR "%s: fatal error; disabling device\n",
++ netif->dev->name);
++ xenvif_carrier_off(netif);
++ netif_put(netif);
++}
++
+ static int netbk_count_requests(struct xen_netif *netif,
+ struct xen_netif_tx_request *first,
+ struct xen_netif_tx_request *txp, int work_to_do)
+@@ -998,19 +1006,25 @@ static int netbk_count_requests(struct x
+
+ do {
+ if (frags >= work_to_do) {
+- DPRINTK("Need more frags\n");
++ printk(KERN_ERR "%s: Need more frags\n",
++ netif->dev->name);
++ netbk_fatal_tx_err(netif);
+ return -frags;
+ }
+
+ if (unlikely(frags >= MAX_SKB_FRAGS)) {
+- DPRINTK("Too many frags\n");
++ printk(KERN_ERR "%s: Too many frags\n",
++ netif->dev->name);
++ netbk_fatal_tx_err(netif);
+ return -frags;
+ }
+
+ memcpy(txp, RING_GET_REQUEST(&netif->tx, cons + frags),
+ sizeof(*txp));
+ if (txp->size > first->size) {
+- DPRINTK("Frags galore\n");
++ printk(KERN_ERR "%s: Frag is bigger than frame.\n",
++ netif->dev->name);
++ netbk_fatal_tx_err(netif);
+ return -frags;
+ }
+
+@@ -1018,8 +1032,9 @@ static int netbk_count_requests(struct x
+ frags++;
+
+ if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) {
+- DPRINTK("txp->offset: %x, size: %u\n",
+- txp->offset, txp->size);
++ printk(KERN_ERR "%s: txp->offset: %x, size: %u\n",
++ netif->dev->name, txp->offset, txp->size);
++ netbk_fatal_tx_err(netif);
+ return -frags;
+ }
+ } while ((txp++)->flags & NETTXF_more_data);
+@@ -1178,7 +1193,9 @@ int netbk_get_extras(struct xen_netif *n
+
+ do {
+ if (unlikely(work_to_do-- <= 0)) {
+- DPRINTK("Missing extra info\n");
++ printk(KERN_ERR "%s: Missing extra info\n",
++ netif->dev->name);
++ netbk_fatal_tx_err(netif);
+ return -EBADR;
+ }
+
+@@ -1187,7 +1204,9 @@ int netbk_get_extras(struct xen_netif *n
+ if (unlikely(!extra.type ||
+ extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
+ netif->tx.req_cons = ++cons;
+- DPRINTK("Invalid extra type: %d\n", extra.type);
++ printk(KERN_ERR "%s: Invalid extra type: %d\n",
++ netif->dev->name, extra.type);
++ netbk_fatal_tx_err(netif);
+ return -EINVAL;
+ }
+
+@@ -1198,16 +1217,21 @@ int netbk_get_extras(struct xen_netif *n
+ return work_to_do;
+ }
+
+-static int netbk_set_skb_gso(struct sk_buff *skb, struct xen_netif_extra_info *gso)
++static int netbk_set_skb_gso(struct xen_netif *netif, struct sk_buff *skb,
++ struct xen_netif_extra_info *gso)
+ {
+ if (!gso->u.gso.size) {
+- DPRINTK("GSO size must not be zero.\n");
++ printk(KERN_ERR "%s: GSO size must not be zero.\n",
++ netif->dev->name);
++ netbk_fatal_tx_err(netif);
+ return -EINVAL;
+ }
+
+ /* Currently only TCPv4 S.O. is supported. */
+ if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) {
+- DPRINTK("Bad GSO type %d.\n", gso->u.gso.type);
++ printk(KERN_ERR "%s: Bad GSO type %d.\n",
++ netif->dev->name, gso->u.gso.type);
++ netbk_fatal_tx_err(netif);
+ return -EINVAL;
+ }
+
+@@ -1317,6 +1341,16 @@ static unsigned net_tx_build_mops(struct
+ netif_get(netif);
+ remove_from_net_schedule_list(netif);
+
++ if (netif->tx.sring->req_prod - netif->tx.req_cons >
++ NET_TX_RING_SIZE) {
++ printk(KERN_ERR "%s: Impossible number of requests. "
++ "req_prod %u, req_cons %u, size %lu\n",
++ netif->dev->name, netif->tx.sring->req_prod,
++ netif->tx.req_cons, NET_TX_RING_SIZE);
++ netbk_fatal_tx_err(netif);
++ continue;
++ }
++
+ RING_FINAL_CHECK_FOR_REQUESTS(&netif->tx, work_to_do);
+ if (!work_to_do) {
+ netif_put(netif);
+@@ -1344,17 +1378,14 @@ static unsigned net_tx_build_mops(struct
+ work_to_do = netbk_get_extras(netif, extras,
+ work_to_do);
+ idx = netif->tx.req_cons;
+- if (unlikely(work_to_do < 0)) {
+- netbk_tx_err(netif, &txreq, idx);
++ if (unlikely(work_to_do < 0))
+ continue;
+- }
+ }
+
+ ret = netbk_count_requests(netif, &txreq, txfrags, work_to_do);
+- if (unlikely(ret < 0)) {
+- netbk_tx_err(netif, &txreq, idx - ret);
++ if (unlikely(ret < 0))
+ continue;
+- }
++
+ idx += ret;
+
+ if (unlikely(txreq.size < ETH_HLEN)) {
+@@ -1365,10 +1396,10 @@ static unsigned net_tx_build_mops(struct
+
+ /* No crossing a page as the payload mustn't fragment. */
+ if (unlikely((txreq.offset + txreq.size) > PAGE_SIZE)) {
+- DPRINTK("txreq.offset: %x, size: %u, end: %lu\n",
+- txreq.offset, txreq.size,
+- (txreq.offset &~PAGE_MASK) + txreq.size);
+- netbk_tx_err(netif, &txreq, idx);
++ printk(KERN_ERR "%s: txreq.offset: %x, size: %u, end: %lu\n",
++ netif->dev->name, txreq.offset, txreq.size,
++ (txreq.offset & ~PAGE_MASK) + txreq.size);
++ netbk_fatal_tx_err(netif);
+ continue;
+ }
+
+@@ -1394,9 +1425,9 @@ static unsigned net_tx_build_mops(struct
+ struct xen_netif_extra_info *gso;
+ gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1];
+
+- if (netbk_set_skb_gso(skb, gso)) {
++ if (netbk_set_skb_gso(netif, skb, gso)) {
++ /* Failure in netbk_set_skb_gso is fatal. */
+ kfree_skb(skb);
+- netbk_tx_err(netif, &txreq, idx);
+ continue;
+ }
+ }
Added: dists/squeeze-security/linux-2.6/debian/patches/series/46squeeze1-extra
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/squeeze-security/linux-2.6/debian/patches/series/46squeeze1-extra Thu Feb 14 09:33:00 2013 (r19809)
@@ -0,0 +1 @@
++ features/all/xen/xsa39-classic-0001-xen-netback-garbage-ring.patch featureset=xen
More information about the Kernel-svn-changes
mailing list