In the vxlan_xmit_one(), when the encap_bypass_if_local() returns an error, the function jumps to out_unlock without releasing the dst reference obtained from the udp_tunnel_dst_lookup(). This causes a reference count leak in both IPv4 and IPv6 paths.
Fix by calling the dst_release() before goto out_unlock in both error paths: - For IPv4: release &rt->dst - For IPv6: release ndst
Fixes: 56de859e9967 ("vxlan: lock RCU on TX path") Cc: stable@vger.kernel.org Signed-off-by: Wentao Liang vulab@iscas.ac.cn --- drivers/net/vxlan/vxlan_core.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c index dab864bc733c..41bbc92cc234 100644 --- a/drivers/net/vxlan/vxlan_core.c +++ b/drivers/net/vxlan/vxlan_core.c @@ -2479,8 +2479,10 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, err = encap_bypass_if_local(skb, dev, vxlan, AF_INET, dst_port, ifindex, vni, &rt->dst, rt->rt_flags); - if (err) + if (err) { + dst_release(&rt->dst); goto out_unlock; + }
if (vxlan->cfg.df == VXLAN_DF_SET) { df = htons(IP_DF); @@ -2560,8 +2562,10 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, err = encap_bypass_if_local(skb, dev, vxlan, AF_INET6, dst_port, ifindex, vni, ndst, rt6i_flags); - if (err) + if (err) { + dst_release(ndst); goto out_unlock; + } }
err = skb_tunnel_check_pmtu(skb, ndst,