Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2574

kernel-2.6.18-238.el5.src.rpm

From: Neil Horman <nhorman@redhat.com>
Date: Tue, 2 Jun 2009 07:10:01 -0400
Subject: [net] e1000: fix skb_over_panic
Message-id: 20090602111001.GD17744@hmsreliant.think-freely.org
O-Subject: [kernel team] [RHEL 5.4][EMBARGOED] e1000: fix skb_over_panic (bz 503441)
Bugzilla: 503441
RH-Acked-by: Jiri Pirko <jpirko@redhat.com>
RH-Acked-by: John W. Linville <linville@redhat.com>
RH-Acked-by: Andy Gospodarek <gospo@redhat.com>
RH-Acked-by: Eugene Teo <eugene@redhat.com>
CVE: CVE-2009-1385

Hey all-
        This bug came in yesterday, apparently a customer reported that setting
the mtu on an interface very low and sending in a very large icmp echo request
results in an skb_over_panic on e1000 cards, which has been considered a denial
of service attack on RHEL4.  Gospo and I did some research, and he found that
(quite unexpectedly), we're getting this panic because we try to do an skb_put
on a buffer, passing in a length value that underflowed, resulting in a huge
positive value.  Doing some reading, it appears that e1000 (and all its brethren
hardware), appear to consistently allow packets to span multiple rx descriptors,
occasionally leading to a frame who's crc checksum is partially contained in a
separate descriptor.  None of the intel drivers are written to handle this
packet span condition, and so they simply discard the frame by checking the EOP
bit in the rx status word for the frame.  That handles the first part of the
packet, but the second part, which is usually very small has the EOP bit set and
so passes through.  Since the driver trucates the packet by 4 bytes to remove
the crc, if only part of the crc is available in the second packet, the length
value underflows and we panic.   Intels other drivers (e1000e, and I think
ixgb) handle this by also discarding any packets less than 4 bytes, but they
never bothered to port that fix over to e1000 in the upstream tree.  This patch
corrects that. Tested by Gospo and myself.

Neil

diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 96baf8d..cb5b9bd 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -4233,7 +4233,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
 
 		length = le16_to_cpu(rx_desc->length);
 
-		if (unlikely(!(status & E1000_RXD_STAT_EOP))) {
+		if (unlikely(!(status & E1000_RXD_STAT_EOP) || (length <= 4))) {
 			/* All receives must fit into a single buffer */
 			E1000_DBG("%s: Receive packet consumed multiple"
 				  " buffers\n", netdev->name);