Fix a race between neigh_timer_handler() calling down to arp_solicit() with an sk_buff peeked from the head of the neigh->arp_queue, and neigh_event_send() unqueuing and freeing the head of the same queue because it's reached the maximum length of 3, by taking an extra sk_buff reference while holding neigh->lock. Signed-off-by: Greg Banks Index: linux/net/core/neighbour.c =================================================================== --- linux.orig/net/core/neighbour.c 2004-10-04 14:36:05.%N +1000 +++ linux/net/core/neighbour.c 2004-10-05 19:31:00.%N +1000 @@ -805,9 +805,15 @@ static void neigh_timer_handler(unsigned add_timer(&neigh->timer); } if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) { + struct sk_buff *skb = skb_peek(&neigh->arp_queue); + /* keep skb alive even if arp_queue overflows */ + if (skb) + skb_get(skb); write_unlock(&neigh->lock); - neigh->ops->solicit(neigh, skb_peek(&neigh->arp_queue)); + neigh->ops->solicit(neigh, skb); atomic_inc(&neigh->probes); + if (skb) + kfree_skb(skb); } else { out: write_unlock(&neigh->lock);