Skip to content

Commit

Permalink
udp: fix dst races with multicast early demux
Browse files Browse the repository at this point in the history
Multicast dst are not cached. They carry DST_NOCACHE.

As mentioned in commit f886497 ("ipv4: fix dst race in
sk_dst_get()"), these dst need special care before caching them
into a socket.

Caching them is allowed only if their refcnt was not 0, ie we
must use atomic_inc_not_zero()

Also, we must use READ_ONCE() to fetch sk->sk_rx_dst, as mentioned
in commit d0c294c ("tcp: prevent fetching dst twice in early demux
code")

Fixes: 421b388 ("udp: ipv4: Add udp early demux")
Tested-by: Gregory Hoggarth <Gregory.Hoggarth@alliedtelesis.co.nz>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: Gregory Hoggarth <Gregory.Hoggarth@alliedtelesis.co.nz>
Reported-by: Alex Gartrell <agartrell@fb.com>
Cc: Michal Kubeček <mkubecek@suse.cz>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Eric Dumazet authored and David S. Miller committed Aug 4, 2015
1 parent 2fc0996 commit 10e2eb8
Showing 1 changed file with 10 additions and 3 deletions.
13 changes: 10 additions & 3 deletions net/ipv4/udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1995,12 +1995,19 @@ void udp_v4_early_demux(struct sk_buff *skb)

skb->sk = sk;
skb->destructor = sock_efree;
dst = sk->sk_rx_dst;
dst = READ_ONCE(sk->sk_rx_dst);

if (dst)
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)
Expand Down

0 comments on commit 10e2eb8

Please sign in to comment.