| From foo@baz Sat Mar 18 22:03:53 CST 2017 |
| From: Brian Russell <brussell@brocade.com> |
| Date: Fri, 24 Feb 2017 17:47:11 +0000 |
| Subject: vxlan: don't allow overwrite of config src addr |
| |
| From: Brian Russell <brussell@brocade.com> |
| |
| |
| [ Upstream commit 1158632b5a2dcce0786c1b1b99654e81cc867981 ] |
| |
| When using IPv6 transport and a default dst, a pointer to the configured |
| source address is passed into the route lookup. If no source address is |
| configured, then the value is overwritten. |
| |
| IPv6 route lookup ignores egress ifindex match if the source address is set, |
| so if egress ifindex match is desired, the source address must be passed |
| as any. The overwrite breaks this for subsequent lookups. |
| |
| Avoid this by copying the configured address to an existing stack variable |
| and pass a pointer to that instead. |
| |
| Fixes: 272d96a5ab10 ("net: vxlan: lwt: Use source ip address during route lookup.") |
| |
| Signed-off-by: Brian Russell <brussell@brocade.com> |
| Acked-by: Jiri Benc <jbenc@redhat.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/net/vxlan.c | 12 +++++------- |
| 1 file changed, 5 insertions(+), 7 deletions(-) |
| |
| --- a/drivers/net/vxlan.c |
| +++ b/drivers/net/vxlan.c |
| @@ -1992,7 +1992,6 @@ static void vxlan_xmit_one(struct sk_buf |
| const struct iphdr *old_iph = ip_hdr(skb); |
| union vxlan_addr *dst; |
| union vxlan_addr remote_ip, local_ip; |
| - union vxlan_addr *src; |
| struct vxlan_metadata _md; |
| struct vxlan_metadata *md = &_md; |
| __be16 src_port = 0, dst_port; |
| @@ -2019,7 +2018,7 @@ static void vxlan_xmit_one(struct sk_buf |
| |
| dst_port = rdst->remote_port ? rdst->remote_port : vxlan->cfg.dst_port; |
| vni = rdst->remote_vni; |
| - src = &vxlan->cfg.saddr; |
| + local_ip = vxlan->cfg.saddr; |
| dst_cache = &rdst->dst_cache; |
| md->gbp = skb->mark; |
| ttl = vxlan->cfg.ttl; |
| @@ -2052,7 +2051,6 @@ static void vxlan_xmit_one(struct sk_buf |
| dst = &remote_ip; |
| dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port; |
| vni = tunnel_id_to_key32(info->key.tun_id); |
| - src = &local_ip; |
| dst_cache = &info->dst_cache; |
| if (info->options_len) |
| md = ip_tunnel_info_opts(info); |
| @@ -2072,7 +2070,7 @@ static void vxlan_xmit_one(struct sk_buf |
| rt = vxlan_get_route(vxlan, dev, sock4, skb, |
| rdst ? rdst->remote_ifindex : 0, tos, |
| dst->sin.sin_addr.s_addr, |
| - &src->sin.sin_addr.s_addr, |
| + &local_ip.sin.sin_addr.s_addr, |
| dst_port, src_port, |
| dst_cache, info); |
| if (IS_ERR(rt)) { |
| @@ -2099,7 +2097,7 @@ static void vxlan_xmit_one(struct sk_buf |
| if (err < 0) |
| goto tx_error; |
| |
| - udp_tunnel_xmit_skb(rt, sock4->sock->sk, skb, src->sin.sin_addr.s_addr, |
| + udp_tunnel_xmit_skb(rt, sock4->sock->sk, skb, local_ip.sin.sin_addr.s_addr, |
| dst->sin.sin_addr.s_addr, tos, ttl, df, |
| src_port, dst_port, xnet, !udp_sum); |
| #if IS_ENABLED(CONFIG_IPV6) |
| @@ -2109,7 +2107,7 @@ static void vxlan_xmit_one(struct sk_buf |
| ndst = vxlan6_get_route(vxlan, dev, sock6, skb, |
| rdst ? rdst->remote_ifindex : 0, tos, |
| label, &dst->sin6.sin6_addr, |
| - &src->sin6.sin6_addr, |
| + &local_ip.sin6.sin6_addr, |
| dst_port, src_port, |
| dst_cache, info); |
| if (IS_ERR(ndst)) { |
| @@ -2137,7 +2135,7 @@ static void vxlan_xmit_one(struct sk_buf |
| goto tx_error; |
| |
| udp_tunnel6_xmit_skb(ndst, sock6->sock->sk, skb, dev, |
| - &src->sin6.sin6_addr, |
| + &local_ip.sin6.sin6_addr, |
| &dst->sin6.sin6_addr, tos, ttl, |
| label, src_port, dst_port, !udp_sum); |
| #endif |