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,
On 16/12/2025 05:36, Wentao Liang wrote:
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,
Did you check what encap_bypass_if_local() does at all?
There is a reason why the code jumps to out_unlock on error, encap_bypass_if_local handles that case itself. Don't blindly change code, first check what it does.
Cheers, Nik
linux-stable-mirror@lists.linaro.org