diff options
Diffstat (limited to 'net/ipv4/udp.c')
-rw-r--r-- | net/ipv4/udp.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 83aa604f9273..1b8c5ba7d5f7 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -1995,12 +1995,19 @@ void udp_v4_early_demux(struct sk_buff *skb) | |||
1995 | 1995 | ||
1996 | skb->sk = sk; | 1996 | skb->sk = sk; |
1997 | skb->destructor = sock_efree; | 1997 | skb->destructor = sock_efree; |
1998 | dst = sk->sk_rx_dst; | 1998 | dst = READ_ONCE(sk->sk_rx_dst); |
1999 | 1999 | ||
2000 | if (dst) | 2000 | if (dst) |
2001 | dst = dst_check(dst, 0); | 2001 | dst = dst_check(dst, 0); |
2002 | if (dst) | 2002 | if (dst) { |
2003 | skb_dst_set_noref(skb, dst); | 2003 | /* DST_NOCACHE can not be used without taking a reference */ |
2004 | if (dst->flags & DST_NOCACHE) { | ||
2005 | if (likely(atomic_inc_not_zero(&dst->__refcnt))) | ||
2006 | skb_dst_set(skb, dst); | ||
2007 | } else { | ||
2008 | skb_dst_set_noref(skb, dst); | ||
2009 | } | ||
2010 | } | ||
2004 | } | 2011 | } |
2005 | 2012 | ||
2006 | int udp_rcv(struct sk_buff *skb) | 2013 | int udp_rcv(struct sk_buff *skb) |