[kernel] r14960 - in dists/trunk/linux-2.6/debian: . patches/bugfix/all patches/series

Ben Hutchings benh at alioth.debian.org
Thu Jan 21 01:07:19 UTC 2010


Author: benh
Date: Thu Jan 21 01:07:09 2010
New Revision: 14960

Log:
e1000,e1000e: enhance fragment detection (CVE-2009-4536, CVE-2009-4538)

Added:
   dists/trunk/linux-2.6/debian/patches/bugfix/all/e1000-enhance-fragment-detection.patch
   dists/trunk/linux-2.6/debian/patches/bugfix/all/e1000e-enhance-fragment-detection.patch
Modified:
   dists/trunk/linux-2.6/debian/changelog
   dists/trunk/linux-2.6/debian/patches/series/6

Modified: dists/trunk/linux-2.6/debian/changelog
==============================================================================
--- dists/trunk/linux-2.6/debian/changelog	Wed Jan 20 04:20:15 2010	(r14959)
+++ dists/trunk/linux-2.6/debian/changelog	Thu Jan 21 01:07:09 2010	(r14960)
@@ -31,6 +31,7 @@
       + agp/intel-agp: Clear entire GTT on startup
   * SCSI/megaraid_sas: remove sysfs poll_mode_io world writeable permissions
     (CVE-2009-3939)
+  * e1000,e1000e: enhance fragment detection (CVE-2009-4536, CVE-2009-4538)
 
   [ Ian Campbell ]
   * xen: Enable up to 32G of guest memory on i386.

Added: dists/trunk/linux-2.6/debian/patches/bugfix/all/e1000-enhance-fragment-detection.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/all/e1000-enhance-fragment-detection.patch	Thu Jan 21 01:07:09 2010	(r14960)
@@ -0,0 +1,73 @@
+Subject: [net-2.6,1/2] e1000: enhance frame fragment detection
+Date: Tue, 19 Jan 2010 14:15:38 -0000
+From: Jesse Brandeburg <jesse.brandeburg at intel.com>
+
+Originally From: Neil Horman <nhorman at tuxdriver.com>
+Modified by: Jesse Brandeburg <jesse.brandeburg at intel.com>
+
+Hey all-
+	A security discussion was recently given:
+http://events.ccc.de/congress/2009/Fahrplan//events/3596.en.html
+And a patch that I submitted awhile back was brought up.  Apparently some of
+their testing revealed that they were able to force a buffer fragment in e1000
+in which the trailing fragment was greater than 4 bytes.  As a result the
+fragment check I introduced failed to detect the fragement and a partial
+invalid frame was passed up into the network stack.  I've written this patch
+to correct it.  I'm in the process of testing it now, but it makes good
+logical sense to me.  Effectively it maintains a per-adapter state variable
+which detects a non-EOP frame, and discards it and subsequent non-EOP frames
+leading up to _and_ _including_ the next positive-EOP frame (as it is by
+definition the last fragment).  This should prevent any and all partial frames
+from entering the network stack from e1000.
+
+Signed-off-by: Jesse Brandeburg <jesse.brandeburg at intel.com>
+Acked-by: Neil Horman <nhorman at tuxdriver.com>
+Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher at intel.com>
+
+---
+drivers/net/e1000/e1000.h      |    2 ++
+ drivers/net/e1000/e1000_main.c |   13 +++++++++++--
+ 2 files changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
+index 2a567df..e8932db 100644
+--- a/drivers/net/e1000/e1000.h
++++ b/drivers/net/e1000/e1000.h
+@@ -326,6 +326,8 @@ struct e1000_adapter {
+ 	/* for ioport free */
+ 	int bars;
+ 	int need_ioport;
++
++	bool discarding;
+ };
+ 
+ enum e1000_state_t {
+diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
+index 7e855f9..9bc9fcd 100644
+--- a/drivers/net/e1000/e1000_main.c
++++ b/drivers/net/e1000/e1000_main.c
+@@ -3850,13 +3850,22 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
+ 
+ 		length = le16_to_cpu(rx_desc->length);
+ 		/* !EOP means multiple descriptors were used to store a single
+-		 * packet, also make sure the frame isn't just CRC only */
+-		if (unlikely(!(status & E1000_RXD_STAT_EOP) || (length <= 4))) {
++		 * packet, if thats the case we need to toss it.  In fact, we
++		 * to toss every packet with the EOP bit clear and the next
++		 * frame that _does_ have the EOP bit set, as it is by
++		 * definition only a frame fragment
++		 */
++		if (unlikely(!(status & E1000_RXD_STAT_EOP)))
++			adapter->discarding = true;
++
++		if (adapter->discarding) {
+ 			/* All receives must fit into a single buffer */
+ 			E1000_DBG("%s: Receive packet consumed multiple"
+ 				  " buffers\n", netdev->name);
+ 			/* recycle */
+ 			buffer_info->skb = skb;
++			if (status & E1000_RXD_STAT_EOP)
++				adapter->discarding = false;
+ 			goto next_desc;
+ 		}
+ 

Added: dists/trunk/linux-2.6/debian/patches/bugfix/all/e1000e-enhance-fragment-detection.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/all/e1000e-enhance-fragment-detection.patch	Thu Jan 21 01:07:09 2010	(r14960)
@@ -0,0 +1,80 @@
+Based on:
+
+Subject: [net-2.6,2/2] e1000e: enhance frame fragment detection
+Date: Tue, 19 Jan 2010 14:15:59 -0000
+From: Jesse Brandeburg <jesse.brandeburg at intel.com>
+
+Originally patched by Neil Horman <nhorman at tuxdriver.com>
+
+e1000e could with a jumbo frame enabled interface, and packet split disabled,
+receive a packet that would overflow a single rx buffer.  While in practice
+very hard to craft a packet that could abuse this, it is possible.
+
+this is related to CVE-2009-4538
+
+--- a/drivers/net/e1000e/e1000.h
++++ b/drivers/net/e1000e/e1000.h
+@@ -421,6 +421,7 @@ struct e1000_info {
+ /* CRC Stripping defines */
+ #define FLAG2_CRC_STRIPPING               (1 << 0)
+ #define FLAG2_HAS_PHY_WAKEUP              (1 << 1)
++#define FLAG2_IS_DISCARDING               (1 << 2)
+ 
+ #define E1000_RX_DESC_PS(R, i)	    \
+ 	(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
+--- a/drivers/net/e1000e/netdev.c
++++ b/drivers/net/e1000e/netdev.c
+@@ -450,14 +450,24 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
+ 
+ 		length = le16_to_cpu(rx_desc->length);
+ 
+-		/* !EOP means multiple descriptors were used to store a single
+-		 * packet, also make sure the frame isn't just CRC only */
+-		if (!(status & E1000_RXD_STAT_EOP) || (length <= 4)) {
++		/*
++		 * !EOP means multiple descriptors were used to store a single
++		 * packet, if that's the case we need to toss it.  In fact, we
++		 * need to toss every packet with the EOP bit clear and the
++		 * next frame that _does_ have the EOP bit set, as it is by
++		 * definition only a frame fragment
++		 */
++		if (unlikely(!(status & E1000_RXD_STAT_EOP)))
++			adapter->flags2 |= FLAG2_IS_DISCARDING;
++
++		if (adapter->flags2 & FLAG2_IS_DISCARDING) {
+ 			/* All receives must fit into a single buffer */
+ 			e_dbg("%s: Receive packet consumed multiple buffers\n",
+ 			      netdev->name);
+ 			/* recycle */
+ 			buffer_info->skb = skb;
++			if (status & E1000_RXD_STAT_EOP)
++				adapter->flags2 &= ~FLAG2_IS_DISCARDING;
+ 			goto next_desc;
+ 		}
+ 
+@@ -745,10 +755,16 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+ 				 PCI_DMA_FROMDEVICE);
+ 		buffer_info->dma = 0;
+ 
+-		if (!(staterr & E1000_RXD_STAT_EOP)) {
++		/* see !EOP comment in other rx routine */
++		if (!(staterr & E1000_RXD_STAT_EOP))
++			adapter->flags2 |= FLAG2_IS_DISCARDING;
++
++		if (adapter->flags2 & FLAG2_IS_DISCARDING) {
+ 			e_dbg("%s: Packet Split buffers didn't pick up the "
+ 			      "full packet\n", netdev->name);
+ 			dev_kfree_skb_irq(skb);
++			if (staterr & E1000_RXD_STAT_EOP)
++				adapter->flags2 &= ~FLAG2_IS_DISCARDING;
+ 			goto next_desc;
+ 		}
+ 
+@@ -1118,6 +1134,7 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter)
+ 
+ 	rx_ring->next_to_clean = 0;
+ 	rx_ring->next_to_use = 0;
++	adapter->flags2 &= ~FLAG2_IS_DISCARDING;
+ 
+ 	writel(0, adapter->hw.hw_addr + rx_ring->head);
+ 	writel(0, adapter->hw.hw_addr + rx_ring->tail);

Modified: dists/trunk/linux-2.6/debian/patches/series/6
==============================================================================
--- dists/trunk/linux-2.6/debian/patches/series/6	Wed Jan 20 04:20:15 2010	(r14959)
+++ dists/trunk/linux-2.6/debian/patches/series/6	Thu Jan 21 01:07:09 2010	(r14960)
@@ -27,3 +27,5 @@
 + bugfix/all/stable/2.6.32.4.patch
 + debian/mremap-fix-conflict-between-2.6.32.4-and-vserver.patch
 + bugfix/all/megaraid_sas-remove-poll_mode_io-world-write-perm.patch
++ bugfix/all/e1000-enhance-fragment-detection.patch
++ bugfix/all/e1000e-enhance-fragment-detection.patch



More information about the Kernel-svn-changes mailing list