From c1fa347f20f17f14a4a1575727fa24340e8a9117 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 19 Jan 2010 14:21:45 +0000 Subject: e1000/e1000e/igb/igbvf/ixgb/ixgbe: Fix tests of unsigned in *_tx_map() The variable count and i are unsigned so the (<|>=)0 tests do not work. Signed-off-by: Roel Kluin Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net/e1000/e1000_main.c') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 7e855f9bbd97..b3f67b41627f 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2802,13 +2802,13 @@ static int e1000_tx_map(struct e1000_adapter *adapter, dma_error: dev_err(&pdev->dev, "TX DMA map failed\n"); buffer_info->dma = 0; - count--; - - while (count >= 0) { + if (count) count--; - i--; - if (i < 0) + + while (count--) { + if (i==0) i += tx_ring->count; + i--; buffer_info = &tx_ring->buffer_info[i]; e1000_unmap_and_free_tx_resource(adapter, buffer_info); } -- cgit v1.2.2 From 40a14deaf411592b57cb0720f0e8004293ab9865 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 19 Jan 2010 14:15:38 +0000 Subject: e1000: enhance frame fragment detection Originally From: Neil Horman Modified by: Jesse Brandeburg 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 Acked-by: Neil Horman Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/net/e1000/e1000_main.c') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index b3f67b41627f..a53a2017c537 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; } -- cgit v1.2.2 From 9926146b15fd96d78a4f7c32e7a26d50639369f4 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 22 Jan 2010 22:56:16 +0000 Subject: e1000/e1000e: don't use small hardware rx buffers 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 Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) (limited to 'drivers/net/e1000/e1000_main.c') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index a53a2017c537..d29bb532eccf 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1698,18 +1698,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) 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; @@ -3176,13 +3164,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) * however with the new *_jumbo_rx* routines, jumbo receives will use * fragmented skbs */ - 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 (PAGE_SIZE >= E1000_RXBUFFER_16384) -- cgit v1.2.2