rpms/kernel/F-11 e1000-e1000e-don-t-use-small-hardware-rx-buffers.patch, NONE, 1.1.2.1 e1000-enhance-frame-fragment-detection.patch, NONE, 1.1.2.1 e1000e-enhance-frame-fragment-detection.patch, NONE, 1.1.2.1 kernel.spec, 1.1784.2.5, 1.1784.2.6

Chuck Ebbert cebbert at fedoraproject.org
Sat Jan 30 14:06:40 UTC 2010


Author: cebbert

Update of /cvs/pkgs/rpms/kernel/F-11
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv16226

Modified Files:
      Tag: private-fedora-11-2_6_30
	kernel.spec 
Added Files:
      Tag: private-fedora-11-2_6_30
	e1000-e1000e-don-t-use-small-hardware-rx-buffers.patch 
	e1000-enhance-frame-fragment-detection.patch 
	e1000e-enhance-frame-fragment-detection.patch 
Log Message:
CVE-2009-4536 kernel: e1000 issue reported at 26c3
CVE-2009-4538 kernel: e1000e frame fragment issue

e1000-e1000e-don-t-use-small-hardware-rx-buffers.patch:
 e1000/e1000_main.c |   20 +-------------------
 e1000e/netdev.c    |   20 +-------------------
 2 files changed, 2 insertions(+), 38 deletions(-)

--- NEW FILE e1000-e1000e-don-t-use-small-hardware-rx-buffers.patch ---
>From 9926146b15fd96d78a4f7c32e7a26d50639369f4 Mon Sep 17 00:00:00 2001
From: Jesse Brandeburg <jesse.brandeburg at intel.com>
Date: Fri, 22 Jan 2010 22:56:16 +0000
Subject: e1000/e1000e: don't use small hardware rx buffers

From: Chuck Ebbert <cebbert at redhat.com>
[ backport to 2.6.30 ]

commit 9926146b15fd96d78a4f7c32e7a26d50639369f4 upstream.

When testing the "e1000: enhance frame fragment detection" (and e1000e)
patches we found some bugs with reducing the MTU size.  The 1024 byte
descriptor used with the 1000 mtu test also (re) introduced the
(originally) reported bug, and causes us to need the e1000_clean_tx_irq
"enhance frame fragment detection" fix.

So what has occured here is that 2.6.32 is only vulnerable for mtu <
1500 due to the jumbo specific routines in both e1000 and e1000e.
So, 2.6.32 needs the 2kB buffer len fix for those smaller MTUs, but
is not vulnerable to the original issue reported.  It has been pointed
out that this vulnerability needs to be patched in older kernels that
don't have the e1000 jumbo routine.  Without the jumbo routines, we
need the "enhance frame fragment detection" fix the e1000, old
e1000e is only vulnerable for < 1500 mtu, and needs a similar
fix.  We split the patches up to provide easy backport paths.

There is only a slight bit of extra code when this fix and the
original "enhance frame fragment detection" fixes are applied, so
please apply both, even though it is a bit of overkill.

Signed-off-by: Jesse Brandeburg <jesse.brandeburg at intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher at intel.com>
Signed-off-by: David S. Miller <davem at davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>

---
 drivers/net/e1000/e1000_main.c |   20 +-------------------
 drivers/net/e1000e/netdev.c    |   20 +-------------------
 2 files changed, 2 insertions(+), 38 deletions(-)

--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -1698,18 +1698,6 @@ static void e1000_setup_rctl(struct e100
 	rctl &= ~E1000_RCTL_SZ_4096;
 	rctl |= E1000_RCTL_BSEX;
 	switch (adapter->rx_buffer_len) {
-		case E1000_RXBUFFER_256:
-			rctl |= E1000_RCTL_SZ_256;
-			rctl &= ~E1000_RCTL_BSEX;
-			break;
-		case E1000_RXBUFFER_512:
-			rctl |= E1000_RCTL_SZ_512;
-			rctl &= ~E1000_RCTL_BSEX;
-			break;
-		case E1000_RXBUFFER_1024:
-			rctl |= E1000_RCTL_SZ_1024;
-			rctl &= ~E1000_RCTL_BSEX;
-			break;
 		case E1000_RXBUFFER_2048:
 		default:
 			rctl |= E1000_RCTL_SZ_2048;
@@ -3468,13 +3468,7 @@ static int e1000_change_mtu(struct net_d
 	 * larger slab size
 	 * i.e. RXBUFFER_2048 --> size-4096 slab */
 
-	if (max_frame <= E1000_RXBUFFER_256)
-		adapter->rx_buffer_len = E1000_RXBUFFER_256;
-	else if (max_frame <= E1000_RXBUFFER_512)
-		adapter->rx_buffer_len = E1000_RXBUFFER_512;
-	else if (max_frame <= E1000_RXBUFFER_1024)
-		adapter->rx_buffer_len = E1000_RXBUFFER_1024;
-	else if (max_frame <= E1000_RXBUFFER_2048)
+	if (max_frame <= E1000_RXBUFFER_2048)
 		adapter->rx_buffer_len = E1000_RXBUFFER_2048;
 	else if (max_frame <= E1000_RXBUFFER_4096)
 		adapter->rx_buffer_len = E1000_RXBUFFER_4096;
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -2347,18 +2347,6 @@ static void e1000_setup_rctl(struct e100
 	rctl &= ~E1000_RCTL_SZ_4096;
 	rctl |= E1000_RCTL_BSEX;
 	switch (adapter->rx_buffer_len) {
-	case 256:
-		rctl |= E1000_RCTL_SZ_256;
-		rctl &= ~E1000_RCTL_BSEX;
-		break;
-	case 512:
-		rctl |= E1000_RCTL_SZ_512;
-		rctl &= ~E1000_RCTL_BSEX;
-		break;
-	case 1024:
-		rctl |= E1000_RCTL_SZ_1024;
-		rctl &= ~E1000_RCTL_BSEX;
-		break;
 	case 2048:
 	default:
 		rctl |= E1000_RCTL_SZ_2048;
@@ -4338,13 +4326,7 @@ static int e1000_change_mtu(struct net_d
 	 * fragmented skbs
 	 */
 
-	if (max_frame <= 256)
-		adapter->rx_buffer_len = 256;
-	else if (max_frame <= 512)
-		adapter->rx_buffer_len = 512;
-	else if (max_frame <= 1024)
-		adapter->rx_buffer_len = 1024;
-	else if (max_frame <= 2048)
+	if (max_frame <= 2048)
 		adapter->rx_buffer_len = 2048;
 	else
 		adapter->rx_buffer_len = 4096;

e1000-enhance-frame-fragment-detection.patch:
 e1000.h      |    2 ++
 e1000_main.c |   13 +++++++++++--
 2 files changed, 13 insertions(+), 2 deletions(-)

--- NEW FILE e1000-enhance-frame-fragment-detection.patch ---
>From 40a14deaf411592b57cb0720f0e8004293ab9865 Mon Sep 17 00:00:00 2001
From: Jesse Brandeburg <jesse.brandeburg at intel.com>
Date: Tue, 19 Jan 2010 14:15:38 +0000
Subject: e1000: enhance frame fragment detection

From: Jesse Brandeburg <jesse.brandeburg at intel.com>

commit 40a14deaf411592b57cb0720f0e8004293ab9865 upstream.

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>
Signed-off-by: David S. Miller <davem at davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>

---
 drivers/net/e1000/e1000.h      |    2 ++
 drivers/net/e1000/e1000_main.c |   13 +++++++++++--
 2 files changed, 13 insertions(+), 2 deletions(-)

--- 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 {
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -3827,13 +3827,22 @@ static bool e1000_clean_rx_irq(struct e1
 
 		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;
 		}
 

e1000e-enhance-frame-fragment-detection.patch:
 e1000.h  |    1 +
 netdev.c |   25 +++++++++++++++++++++----
 2 files changed, 22 insertions(+), 4 deletions(-)

--- NEW FILE e1000e-enhance-frame-fragment-detection.patch ---
>From b94b50289622e816adc9f94111cfc2679c80177c Mon Sep 17 00:00:00 2001
From: Jesse Brandeburg <jesse.brandeburg at intel.com>
Date: Tue, 19 Jan 2010 14:15:59 +0000
Subject: e1000e: enhance frame fragment detection

From: Chuck Ebbert <cebbert at redhat.com>
[ backport to 2.6.30 ]

commit b94b50289622e816adc9f94111cfc2679c80177c upstream.

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

Signed-off-by: Jesse Brandeburg <jesse.brandeburg at intel.com>
CC: Neil Horman <nhorman at tuxdriver.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher at intel.com>
Signed-off-by: David S. Miller <davem at davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>

---
 drivers/net/e1000e/e1000.h  |    1 +
 drivers/net/e1000e/netdev.c |   25 +++++++++++++++++++++----
 2 files changed, 22 insertions(+), 4 deletions(-)

--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -417,6 +417,7 @@ struct e1000_info {
 
 /* CRC Stripping defines */
 #define FLAG2_CRC_STRIPPING               (1 << 0)
+#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
@@ -482,14 +482,24 @@ static bool e1000_clean_rx_irq(struct e1
 
 		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;
 		}
 
@@ -747,10 +757,16 @@ static bool e1000_clean_rx_irq_ps(struct
 				 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;
 		}
 
@@ -1120,6 +1136,7 @@ static void e1000_clean_rx_ring(struct e
 
 	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);


Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-11/kernel.spec,v
retrieving revision 1.1784.2.5
retrieving revision 1.1784.2.6
diff -u -p -r1.1784.2.5 -r1.1784.2.6
--- kernel.spec	29 Jan 2010 16:34:11 -0000	1.1784.2.5
+++ kernel.spec	30 Jan 2010 14:06:38 -0000	1.1784.2.6
@@ -858,6 +858,11 @@ Patch16502: kernel-signal.c-fix-kernel-i
 # cve-2009-4141
 Patch16503: fasync-split-fasync_helper-into-separate-add-remove-functions.patch
 
+# cve-2009-4536, cve-2009-4538
+Patch16511: e1000-enhance-frame-fragment-detection.patch
+Patch16512: e1000e-enhance-frame-fragment-detection.patch
+Patch16513: e1000-e1000e-don-t-use-small-hardware-rx-buffers.patch
+
 %endif
 
 BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root
@@ -1613,6 +1618,11 @@ ApplyPatch kernel-signal.c-fix-kernel-in
 # cve-2009-4141
 ApplyPatch fasync-split-fasync_helper-into-separate-add-remove-functions.patch
 
+# cve-2009-4536, cve-2009-4538
+ApplyPatch e1000-enhance-frame-fragment-detection.patch
+ApplyPatch e1000e-enhance-frame-fragment-detection.patch
+ApplyPatch e1000-e1000e-don-t-use-small-hardware-rx-buffers.patch
+
 # END OF PATCH APPLICATIONS
 
 %endif
@@ -2201,7 +2211,11 @@ fi
 # and build.
 
 %changelog
-* Fri Jan 28 2010 Chuck Ebbert <cebbert at redhat.com>  2.6.30.10-105.2.5
+* Sat Jan 30 2010 Chuck Ebbert <cebbert at redhat.com>  2.6.30.10-105.2.6
+- CVE-2009-4536 kernel: e1000 issue reported at 26c3
+- CVE-2009-4538 kernel: e1000e frame fragment issue
+
+* Fri Jan 29 2010 Chuck Ebbert <cebbert at redhat.com>  2.6.30.10-105.2.5
 - CVE-2009-4141 kernel: create_elf_tables can leave urandom in a bad state
 
 * Tue Jan 19 2010 Chuck Ebbert <cebbert at redhat.com>  2.6.30.10-105.2.4



More information about the scm-commits mailing list