From: Eric Dumazet Date: Tue, 4 May 2010 06:18:14 +0000 (-0700) Subject: net: skb_free_datagram_locked() fix X-Git-Tag: v2.6.35-rc1~473^2~286 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=93bb64eac10aad3dae6178d7da94765f207d121f;p=platform%2Fkernel%2Flinux-3.10.git net: skb_free_datagram_locked() fix Commit 4b0b72f7dd617b ( net: speedup udp receive path ) introduced a bug in skb_free_datagram_locked(). We should not skb_orphan() skb if we dont have the guarantee we are the last skb user, this might happen with MSG_PEEK concurrent users. To keep socket locked for the smallest period of time, we split consume_skb() logic, inlined in skb_free_datagram_locked() Reported-by: Stephen Hemminger Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- diff --git a/net/core/datagram.c b/net/core/datagram.c index 95b851f..e0097531 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -229,13 +229,18 @@ EXPORT_SYMBOL(skb_free_datagram); void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb) { + if (likely(atomic_read(&skb->users) == 1)) + smp_rmb(); + else if (likely(!atomic_dec_and_test(&skb->users))) + return; + lock_sock_bh(sk); skb_orphan(skb); sk_mem_reclaim_partial(sk); unlock_sock_bh(sk); - /* skb is now orphaned, might be freed outside of locked section */ - consume_skb(skb); + /* skb is now orphaned, can be freed outside of locked section */ + __kfree_skb(skb); } EXPORT_SYMBOL(skb_free_datagram_locked);