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 <gnb@melbourne.sgi.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
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);