udp: add a missing smp_wmb() in udp_lib_get_port()
authorEric Dumazet <dada1@cosmosbay.com>
Sun, 2 Nov 2008 04:19:18 +0000 (21:19 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sun, 2 Nov 2008 04:19:18 +0000 (21:19 -0700)
Corey Minyard spotted a missing memory barrier in udp_lib_get_port()

We need to make sure a reader cannot read the new 'sk->sk_next' value
and previous value of 'sk->sk_hash'. Or else, an item could be deleted
from a chain, and inserted into another chain. If new chain was empty
before the move, 'next' pointer is NULL, and lockless reader can
not detect it missed following items in original chain.

This patch is temporary, since we expect an upcoming patch
to introduce another way of handling the problem.

Signed-off-by: Eric Dumazet <dada1@cosmosbay.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/udp.c

index bcb5def2b09e4c76d1c4ad92b5720f67838ffdb0..7e4d9c87115321eb53d0864b2d500d0abba0fd30 100644 (file)
@@ -189,6 +189,11 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum,
        inet_sk(sk)->num = snum;
        sk->sk_hash = snum;
        if (sk_unhashed(sk)) {
+               /*
+                * We need that previous write to sk->sk_hash committed
+                * before write to sk->next done in following add_node() variant
+                */
+               smp_wmb();
                sk_add_node_rcu(sk, &hslot->head);
                sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
        }