|
@@ -1995,12 +1995,19 @@ void udp_v4_early_demux(struct sk_buff *skb)
|
|
|
|
|
|
skb->sk = sk;
|
|
skb->sk = sk;
|
|
skb->destructor = sock_efree;
|
|
skb->destructor = sock_efree;
|
|
- dst = sk->sk_rx_dst;
|
|
|
|
|
|
+ dst = READ_ONCE(sk->sk_rx_dst);
|
|
|
|
|
|
if (dst)
|
|
if (dst)
|
|
dst = dst_check(dst, 0);
|
|
dst = dst_check(dst, 0);
|
|
- if (dst)
|
|
|
|
- skb_dst_set_noref(skb, dst);
|
|
|
|
|
|
+ if (dst) {
|
|
|
|
+ /* DST_NOCACHE can not be used without taking a reference */
|
|
|
|
+ if (dst->flags & DST_NOCACHE) {
|
|
|
|
+ if (likely(atomic_inc_not_zero(&dst->__refcnt)))
|
|
|
|
+ skb_dst_set(skb, dst);
|
|
|
|
+ } else {
|
|
|
|
+ skb_dst_set_noref(skb, dst);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
int udp_rcv(struct sk_buff *skb)
|
|
int udp_rcv(struct sk_buff *skb)
|