Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 559835ea authored by Pravin B Shelar's avatar Pravin B Shelar Committed by David S. Miller
Browse files

vxlan: Use RCU apis to access sk_user_data.



Use of RCU api makes vxlan code easier to understand.  It also
fixes bug due to missing ACCESS_ONCE() on sk_user_data dereference.
In rare case without ACCESS_ONCE() compiler might omit vs on
sk_user_data dereference.
Compiler can use vs as alias for sk->sk_user_data, resulting in
multiple sk_user_data dereference in rcu read context which
could change.

CC: Jesse Gross <jesse@nicira.com>
Signed-off-by: default avatarPravin B Shelar <pshelar@nicira.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9a3bab6b
Loading
Loading
Loading
Loading
+3 −6
Original line number Original line Diff line number Diff line
@@ -952,8 +952,7 @@ void vxlan_sock_release(struct vxlan_sock *vs)


	spin_lock(&vn->sock_lock);
	spin_lock(&vn->sock_lock);
	hlist_del_rcu(&vs->hlist);
	hlist_del_rcu(&vs->hlist);
	smp_wmb();
	rcu_assign_sk_user_data(vs->sock->sk, NULL);
	vs->sock->sk->sk_user_data = NULL;
	vxlan_notify_del_rx_port(sk);
	vxlan_notify_del_rx_port(sk);
	spin_unlock(&vn->sock_lock);
	spin_unlock(&vn->sock_lock);


@@ -1048,8 +1047,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)


	port = inet_sk(sk)->inet_sport;
	port = inet_sk(sk)->inet_sport;


	smp_read_barrier_depends();
	vs = rcu_dereference_sk_user_data(sk);
	vs = (struct vxlan_sock *)sk->sk_user_data;
	if (!vs)
	if (!vs)
		goto drop;
		goto drop;


@@ -2302,8 +2300,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port,
	atomic_set(&vs->refcnt, 1);
	atomic_set(&vs->refcnt, 1);
	vs->rcv = rcv;
	vs->rcv = rcv;
	vs->data = data;
	vs->data = data;
	smp_wmb();
	rcu_assign_sk_user_data(vs->sock->sk, vs);
	vs->sock->sk->sk_user_data = vs;


	spin_lock(&vn->sock_lock);
	spin_lock(&vn->sock_lock);
	hlist_add_head_rcu(&vs->hlist, vs_head(net, port));
	hlist_add_head_rcu(&vs->hlist, vs_head(net, port));
+5 −0
Original line number Original line Diff line number Diff line
@@ -409,6 +409,11 @@ struct sock {
	void                    (*sk_destruct)(struct sock *sk);
	void                    (*sk_destruct)(struct sock *sk);
};
};


#define __sk_user_data(sk) ((*((void __rcu **)&(sk)->sk_user_data)))

#define rcu_dereference_sk_user_data(sk)	rcu_dereference(__sk_user_data((sk)))
#define rcu_assign_sk_user_data(sk, ptr)	rcu_assign_pointer(__sk_user_data((sk)), ptr)

/*
/*
 * SK_CAN_REUSE and SK_NO_REUSE on a socket mean that the socket is OK
 * SK_CAN_REUSE and SK_NO_REUSE on a socket mean that the socket is OK
 * or not whether his port will be reused by someone else. SK_FORCE_REUSE
 * or not whether his port will be reused by someone else. SK_FORCE_REUSE