From: AMEET M. PARANJAPE <aparanja@redhat.com> Date: Tue, 9 Jun 2009 10:31:12 -0400 Subject: [net] ehea: fix invalid pointer access Message-id: 20090609142758.30605.66468.sendpatchset@squad5-lp1.lab.bos.redhat.com O-Subject: [PATCH RHEL5.4 BZ504679] ehea: fix invalid pointer access Bugzilla: 504679 RH-Acked-by: David Howells <dhowells@redhat.com> RHBZ#: ====== https://bugzilla.redhat.com/show_bug.cgi?id=504679 Description: =========== This patch fixes an invalid pointer access in case the receive queue holds no pointer to the next skb when the queue is empty. RHEL Version Found: ================ RHEL 5.4 kABI Status: ============ No symbols were harmed. Brew: ===== Built on all platforms. http://brewweb.devel.redhat.com/brew/taskinfo?taskID=1833600 Upstream Status: ================ http://www.spinics.net/lists/netdev/msg96447.html Test Status: ============ Without this patch under conditions where the kernel runs short of memory or there is a high load on the network interface, the ehea network driver receive path has a weakness that leads to a kernel crash. Rebooting the system is the only way to bring the system back. With this patch applied under heavy stress on memory and/or the network interface the system does not crash. The patch has passed the following tests: - ipv4: ping, flood ping, broadcast ping - ipv6: ping, flood ping - flood ping with big pakets - ftp tests with large files using 4 connections with TSO on/off - ftp long run using 4 connections with TSO on/off - netpipe - netperf - netperf using LRO - netperf/udp - vlan ping - multicast basic - DLPAR port add/remove - DLPAR memory add/remove =============================================================== Ameet Paranjape 978-392-3903 ext 23903 IBM on-site partner Proposed Patch: =============== diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 4b37a9a..09397ba 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -40,7 +40,7 @@ #include <asm/io.h> #define DRV_NAME "ehea" -#define DRV_VERSION "EHEA_0092-04" +#define DRV_VERSION "EHEA_0092-05" /* eHEA capability flags */ #define DLPAR_PORT_ADD_REM 1 diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index a139a32..4c1b15e 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -548,14 +548,17 @@ static inline struct sk_buff *get_skb_by_index(struct sk_buff **skb_array, x &= (arr_len - 1); pref = skb_array[x]; - prefetchw(pref); - prefetchw(pref + EHEA_CACHE_LINE); - - pref = (skb_array[x]->data); - prefetch(pref); - prefetch(pref + EHEA_CACHE_LINE); - prefetch(pref + EHEA_CACHE_LINE * 2); - prefetch(pref + EHEA_CACHE_LINE * 3); + if (pref) { + prefetchw(pref); + prefetchw(pref + EHEA_CACHE_LINE); + + pref = (skb_array[x]->data); + prefetch(pref); + prefetch(pref + EHEA_CACHE_LINE); + prefetch(pref + EHEA_CACHE_LINE * 2); + prefetch(pref + EHEA_CACHE_LINE * 3); + } + skb = skb_array[skb_index]; skb_array[skb_index] = NULL; return skb; @@ -572,12 +575,14 @@ static inline struct sk_buff *get_skb_by_index_ll(struct sk_buff **skb_array, x &= (arr_len - 1); pref = skb_array[x]; - prefetchw(pref); - prefetchw(pref + EHEA_CACHE_LINE); + if (pref) { + prefetchw(pref); + prefetchw(pref + EHEA_CACHE_LINE); - pref = (skb_array[x]->data); - prefetchw(pref); - prefetchw(pref + EHEA_CACHE_LINE); + pref = (skb_array[x]->data); + prefetchw(pref); + prefetchw(pref + EHEA_CACHE_LINE); + } skb = skb_array[wqe_index]; skb_array[wqe_index] = NULL;