[ovs-dev] [PATCH 3/3] lisp: avoid using stale lisp socket.

Pravin B Shelar pshelar at ovn.org
Sun Oct 30 04:33:06 UTC 2016


This patch is similar to earlier vxlan patch.
Lisp device close operation frees lisp socket. This
operation can race with lisp-xmit function which
dereferences lisp socket. Following patch uses RCU
mechanism to avoid this situation.

Signed-off-by: Pravin B Shelar <pshelar at ovn.org>
---
 datapath/linux/compat/lisp.c | 32 ++++++++++++++++++++++++--------
 1 file changed, 24 insertions(+), 8 deletions(-)

diff --git a/datapath/linux/compat/lisp.c b/datapath/linux/compat/lisp.c
index 3a4bebc..193196c 100644
--- a/datapath/linux/compat/lisp.c
+++ b/datapath/linux/compat/lisp.c
@@ -49,7 +49,7 @@ static int lisp_net_id;
 struct lisp_dev {
 	struct net         *net;        /* netns for packet i/o */
 	struct net_device  *dev;        /* netdev for lisp tunnel */
-	struct socket           *sock;
+	struct socket __rcu  *sock;
 	__be16             dst_port;
 	struct list_head   next;
 };
@@ -318,9 +318,10 @@ netdev_tx_t rpl_lisp_xmit(struct sk_buff *skb)
 	int network_offset = skb_network_offset(skb);
 	struct ip_tunnel_info *info;
 	struct ip_tunnel_key *tun_key;
+	__be16 src_port, dst_port;
 	struct rtable *rt;
 	int min_headroom;
-	__be16 src_port, dst_port;
+	struct socket *sock;
 	struct flowi4 fl;
 	__be16 df;
 	int err;
@@ -331,6 +332,12 @@ netdev_tx_t rpl_lisp_xmit(struct sk_buff *skb)
 		goto error;
 	}
 
+	sock = rcu_dereference(lisp_dev->sock);
+	if (!sock) {
+		err = -EIO;
+		goto error;
+	}
+
 	if (skb->protocol != htons(ETH_P_IP) &&
 			skb->protocol != htons(ETH_P_IPV6)) {
 		err = 0;
@@ -381,7 +388,7 @@ netdev_tx_t rpl_lisp_xmit(struct sk_buff *skb)
 	ovs_skb_set_inner_protocol(skb, skb->protocol);
 
 	df = tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
-	udp_tunnel_xmit_skb(rt, lisp_dev->sock->sk, skb,
+	udp_tunnel_xmit_skb(rt, sock->sk, skb,
 			    fl.saddr, tun_key->u.ipv4.dst,
 			    tun_key->tos, tun_key->ttl,
 			    df, src_port, dst_port, false, true);
@@ -442,11 +449,13 @@ static int lisp_open(struct net_device *dev)
 	struct lisp_dev *lisp = netdev_priv(dev);
 	struct udp_tunnel_sock_cfg tunnel_cfg;
 	struct net *net = lisp->net;
+	struct socket *sock;
 
-	lisp->sock = create_sock(net, false, lisp->dst_port);
-	if (IS_ERR(lisp->sock))
-		return PTR_ERR(lisp->sock);
+	sock = create_sock(net, false, lisp->dst_port);
+	if (IS_ERR(sock))
+		return PTR_ERR(sock);
 
+	rcu_assign_pointer(lisp->sock, sock);
 	/* Mark socket as an encapsulation socket */
 	tunnel_cfg.sk_user_data = dev;
 	tunnel_cfg.encap_type = 1;
@@ -459,9 +468,16 @@ static int lisp_open(struct net_device *dev)
 static int lisp_stop(struct net_device *dev)
 {
 	struct lisp_dev *lisp = netdev_priv(dev);
+	struct socket *socket;
+
+	socket = rtnl_dereference(lisp->sock);
+	if (!socket)
+		return 0;
+
+	rcu_assign_pointer(lisp->sock, NULL);
 
-	udp_tunnel_sock_release(lisp->sock);
-	lisp->sock = NULL;
+	synchronize_net();
+	udp_tunnel_sock_release(socket);
 	return 0;
 }
 
-- 
1.8.3.1




More information about the dev mailing list