aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorEric Dumazet <dada1@cosmosbay.com>2008-11-02 00:19:18 -0400
committerDavid S. Miller <davem@davemloft.net>2008-11-02 00:19:18 -0400
commitc37ccc0d4e2a4ee52f1a40cff1be0049f2104bba (patch)
tree8ed76232d7debc5f63f5b80dac7b8a9ba44eb4ce /net/ipv4
parent7e3a42a12c4b9d99bfe81cb929cadf0e08a37c49 (diff)
udp: add a missing smp_wmb() in udp_lib_get_port()
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>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/udp.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index bcb5def2b09e..7e4d9c871153 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -189,6 +189,11 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum,
189 inet_sk(sk)->num = snum; 189 inet_sk(sk)->num = snum;
190 sk->sk_hash = snum; 190 sk->sk_hash = snum;
191 if (sk_unhashed(sk)) { 191 if (sk_unhashed(sk)) {
192 /*
193 * We need that previous write to sk->sk_hash committed
194 * before write to sk->next done in following add_node() variant
195 */
196 smp_wmb();
192 sk_add_node_rcu(sk, &hslot->head); 197 sk_add_node_rcu(sk, &hslot->head);
193 sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); 198 sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
194 } 199 }