[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