[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