Message ID | 20201104180753.41351-2-william.gray@canonical.com |
---|---|
State | New |
Headers | show |
Series | geneve: add transport ports in route lookup for geneve | expand |
On Wed, Nov 04, 2020 at 01:07:53PM -0500, William Breathitt Gray wrote: > From: Mark Gray <mark.d.gray@redhat.com> > > This patch adds transport ports information for route lookup so that > IPsec can select Geneve tunnel traffic to do encryption. This is > needed for OVS/OVN IPsec with encrypted Geneve tunnels. > > This can be tested by configuring a host-host VPN using an IKE > daemon and specifying port numbers. For example, for an > Openswan-type configuration, the following parameters should be > configured on both hosts and IPsec set up as-per normal: > > $ cat /etc/ipsec.conf > > conn in > ... > left=$IP1 > right=$IP2 > ... > leftprotoport=udp/6081 > rightprotoport=udp > ... > conn out > ... > left=$IP1 > right=$IP2 > ... > leftprotoport=udp > rightprotoport=udp/6081 > ... > > The tunnel can then be setup using "ip" on both hosts (but > changing the relevant IP addresses): > > $ ip link add tun type geneve id 1000 remote $IP2 > $ ip addr add 192.168.0.1/24 dev tun > $ ip link set tun up > > This can then be tested by pinging from $IP1: > > $ ping 192.168.0.2 > > Without this patch the traffic is unencrypted on the wire. > > Fixes: 2d07dc79fe04 ("geneve: add initial netdev driver for GENEVE tunnels") > Signed-off-by: Qiuyu Xiao <qiuyu.xiao.qyx@gmail.com> > Signed-off-by: Mark Gray <mark.d.gray@redhat.com> > Reviewed-by: Greg Rose <gvrose8192@gmail.com> > Signed-off-by: David S. Miller <davem@davemloft.net> > > CVE-2020-25645 > > (backported from commit 34beb21594519ce64a55a498c2fe7d567bc1ca20) > [ vilhelmgray: context adjustments ] > Signed-off-by: William Breathitt Gray <william.gray@canonical.com> > --- > drivers/net/geneve.c | 32 ++++++++++++++++++++++---------- > 1 file changed, 22 insertions(+), 10 deletions(-) > > diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c > index c9e0fa325218..d47dd1be86de 100644 > --- a/drivers/net/geneve.c > +++ b/drivers/net/geneve.c > @@ -750,7 +750,8 @@ free_dst: > static struct rtable *geneve_get_v4_rt(struct sk_buff *skb, > struct net_device *dev, > struct flowi4 *fl4, > - struct ip_tunnel_info *info) > + struct ip_tunnel_info *info, > + __be16 dport, __be16 sport) > { > struct geneve_dev *geneve = netdev_priv(dev); > struct rtable *rt = NULL; > @@ -759,6 +760,8 @@ static struct rtable *geneve_get_v4_rt(struct sk_buff *skb, > memset(fl4, 0, sizeof(*fl4)); > fl4->flowi4_mark = skb->mark; > fl4->flowi4_proto = IPPROTO_UDP; > + fl4->fl4_dport = dport; > + fl4->fl4_sport = sport; > > if (info) { > fl4->daddr = info->key.u.ipv4.dst; > @@ -793,7 +796,8 @@ static struct rtable *geneve_get_v4_rt(struct sk_buff *skb, > static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb, > struct net_device *dev, > struct flowi6 *fl6, > - struct ip_tunnel_info *info) > + struct ip_tunnel_info *info, > + __be16 dport, __be16 sport) > { > struct geneve_dev *geneve = netdev_priv(dev); > struct geneve_sock *gs6 = geneve->sock6; > @@ -803,6 +807,8 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb, > memset(fl6, 0, sizeof(*fl6)); > fl6->flowi6_mark = skb->mark; > fl6->flowi6_proto = IPPROTO_UDP; > + fl6->fl6_dport = dport; > + fl6->fl6_sport = sport; > > if (info) { > fl6->daddr = info->key.u.ipv6.dst; > @@ -873,13 +879,13 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, > goto tx_error; > } > > - rt = geneve_get_v4_rt(skb, dev, &fl4, info); > + sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); > + rt = geneve_get_v4_rt(skb, dev, &fl4, info, geneve->dst_port, sport); > if (IS_ERR(rt)) { > err = PTR_ERR(rt); > goto tx_error; > } > > - sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); > skb_reset_mac_header(skb); > > if (info) { > @@ -958,13 +964,13 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, > } > } > > - dst = geneve_get_v6_dst(skb, dev, &fl6, info); > + sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); > + dst = geneve_get_v6_dst(skb, dev, &fl6, info, geneve->dst_port, sport); > if (IS_ERR(dst)) { > err = PTR_ERR(dst); > goto tx_error; > } > > - sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); > skb_reset_mac_header(skb); > > if (info) { > @@ -1053,6 +1059,7 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) > { > struct ip_tunnel_info *info = skb_tunnel_info(skb); > struct geneve_dev *geneve = netdev_priv(dev); > + __be16 sport; > struct rtable *rt; > struct flowi4 fl4; > #if IS_ENABLED(CONFIG_IPV6) > @@ -1061,7 +1068,10 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) > #endif > > if (ip_tunnel_info_af(info) == AF_INET) { > - rt = geneve_get_v4_rt(skb, dev, &fl4, info); > + sport = udp_flow_src_port(geneve->net, skb, > + 1, USHRT_MAX, true); > + rt = geneve_get_v4_rt(skb, dev, &fl4, info, geneve->dst_port, > + sport); > if (IS_ERR(rt)) > return PTR_ERR(rt); > > @@ -1069,7 +1079,10 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) > info->key.u.ipv4.src = fl4.saddr; > #if IS_ENABLED(CONFIG_IPV6) > } else if (ip_tunnel_info_af(info) == AF_INET6) { > - dst = geneve_get_v6_dst(skb, dev, &fl6, info); > + sport = udp_flow_src_port(geneve->net, skb, > + 1, USHRT_MAX, true); > + dst = geneve_get_v6_dst(skb, dev, &fl6, info, geneve->dst_port, > + sport); > if (IS_ERR(dst)) > return PTR_ERR(dst); > > @@ -1080,8 +1093,7 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) > return -EINVAL; > } > > - info->key.tp_src = udp_flow_src_port(geneve->net, skb, > - 1, USHRT_MAX, true); > + info->key.tp_src = sport; > info->key.tp_dst = geneve->dst_port; > return 0; > } > -- > 2.25.1 > Acked-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
Applied to Xenial/master-next Thanks Ian On 2020-11-04 13:07:53 , William Breathitt Gray wrote: > From: Mark Gray <mark.d.gray@redhat.com> > > This patch adds transport ports information for route lookup so that > IPsec can select Geneve tunnel traffic to do encryption. This is > needed for OVS/OVN IPsec with encrypted Geneve tunnels. > > This can be tested by configuring a host-host VPN using an IKE > daemon and specifying port numbers. For example, for an > Openswan-type configuration, the following parameters should be > configured on both hosts and IPsec set up as-per normal: > > $ cat /etc/ipsec.conf > > conn in > ... > left=$IP1 > right=$IP2 > ... > leftprotoport=udp/6081 > rightprotoport=udp > ... > conn out > ... > left=$IP1 > right=$IP2 > ... > leftprotoport=udp > rightprotoport=udp/6081 > ... > > The tunnel can then be setup using "ip" on both hosts (but > changing the relevant IP addresses): > > $ ip link add tun type geneve id 1000 remote $IP2 > $ ip addr add 192.168.0.1/24 dev tun > $ ip link set tun up > > This can then be tested by pinging from $IP1: > > $ ping 192.168.0.2 > > Without this patch the traffic is unencrypted on the wire. > > Fixes: 2d07dc79fe04 ("geneve: add initial netdev driver for GENEVE tunnels") > Signed-off-by: Qiuyu Xiao <qiuyu.xiao.qyx@gmail.com> > Signed-off-by: Mark Gray <mark.d.gray@redhat.com> > Reviewed-by: Greg Rose <gvrose8192@gmail.com> > Signed-off-by: David S. Miller <davem@davemloft.net> > > CVE-2020-25645 > > (backported from commit 34beb21594519ce64a55a498c2fe7d567bc1ca20) > [ vilhelmgray: context adjustments ] > Signed-off-by: William Breathitt Gray <william.gray@canonical.com> > --- > drivers/net/geneve.c | 32 ++++++++++++++++++++++---------- > 1 file changed, 22 insertions(+), 10 deletions(-) > > diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c > index c9e0fa325218..d47dd1be86de 100644 > --- a/drivers/net/geneve.c > +++ b/drivers/net/geneve.c > @@ -750,7 +750,8 @@ free_dst: > static struct rtable *geneve_get_v4_rt(struct sk_buff *skb, > struct net_device *dev, > struct flowi4 *fl4, > - struct ip_tunnel_info *info) > + struct ip_tunnel_info *info, > + __be16 dport, __be16 sport) > { > struct geneve_dev *geneve = netdev_priv(dev); > struct rtable *rt = NULL; > @@ -759,6 +760,8 @@ static struct rtable *geneve_get_v4_rt(struct sk_buff *skb, > memset(fl4, 0, sizeof(*fl4)); > fl4->flowi4_mark = skb->mark; > fl4->flowi4_proto = IPPROTO_UDP; > + fl4->fl4_dport = dport; > + fl4->fl4_sport = sport; > > if (info) { > fl4->daddr = info->key.u.ipv4.dst; > @@ -793,7 +796,8 @@ static struct rtable *geneve_get_v4_rt(struct sk_buff *skb, > static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb, > struct net_device *dev, > struct flowi6 *fl6, > - struct ip_tunnel_info *info) > + struct ip_tunnel_info *info, > + __be16 dport, __be16 sport) > { > struct geneve_dev *geneve = netdev_priv(dev); > struct geneve_sock *gs6 = geneve->sock6; > @@ -803,6 +807,8 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb, > memset(fl6, 0, sizeof(*fl6)); > fl6->flowi6_mark = skb->mark; > fl6->flowi6_proto = IPPROTO_UDP; > + fl6->fl6_dport = dport; > + fl6->fl6_sport = sport; > > if (info) { > fl6->daddr = info->key.u.ipv6.dst; > @@ -873,13 +879,13 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, > goto tx_error; > } > > - rt = geneve_get_v4_rt(skb, dev, &fl4, info); > + sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); > + rt = geneve_get_v4_rt(skb, dev, &fl4, info, geneve->dst_port, sport); > if (IS_ERR(rt)) { > err = PTR_ERR(rt); > goto tx_error; > } > > - sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); > skb_reset_mac_header(skb); > > if (info) { > @@ -958,13 +964,13 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, > } > } > > - dst = geneve_get_v6_dst(skb, dev, &fl6, info); > + sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); > + dst = geneve_get_v6_dst(skb, dev, &fl6, info, geneve->dst_port, sport); > if (IS_ERR(dst)) { > err = PTR_ERR(dst); > goto tx_error; > } > > - sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); > skb_reset_mac_header(skb); > > if (info) { > @@ -1053,6 +1059,7 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) > { > struct ip_tunnel_info *info = skb_tunnel_info(skb); > struct geneve_dev *geneve = netdev_priv(dev); > + __be16 sport; > struct rtable *rt; > struct flowi4 fl4; > #if IS_ENABLED(CONFIG_IPV6) > @@ -1061,7 +1068,10 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) > #endif > > if (ip_tunnel_info_af(info) == AF_INET) { > - rt = geneve_get_v4_rt(skb, dev, &fl4, info); > + sport = udp_flow_src_port(geneve->net, skb, > + 1, USHRT_MAX, true); > + rt = geneve_get_v4_rt(skb, dev, &fl4, info, geneve->dst_port, > + sport); > if (IS_ERR(rt)) > return PTR_ERR(rt); > > @@ -1069,7 +1079,10 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) > info->key.u.ipv4.src = fl4.saddr; > #if IS_ENABLED(CONFIG_IPV6) > } else if (ip_tunnel_info_af(info) == AF_INET6) { > - dst = geneve_get_v6_dst(skb, dev, &fl6, info); > + sport = udp_flow_src_port(geneve->net, skb, > + 1, USHRT_MAX, true); > + dst = geneve_get_v6_dst(skb, dev, &fl6, info, geneve->dst_port, > + sport); > if (IS_ERR(dst)) > return PTR_ERR(dst); > > @@ -1080,8 +1093,7 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) > return -EINVAL; > } > > - info->key.tp_src = udp_flow_src_port(geneve->net, skb, > - 1, USHRT_MAX, true); > + info->key.tp_src = sport; > info->key.tp_dst = geneve->dst_port; > return 0; > } > -- > 2.25.1 > > > -- > kernel-team mailing list > kernel-team@lists.ubuntu.com > https://lists.ubuntu.com/mailman/listinfo/kernel-team
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index c9e0fa325218..d47dd1be86de 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -750,7 +750,8 @@ free_dst: static struct rtable *geneve_get_v4_rt(struct sk_buff *skb, struct net_device *dev, struct flowi4 *fl4, - struct ip_tunnel_info *info) + struct ip_tunnel_info *info, + __be16 dport, __be16 sport) { struct geneve_dev *geneve = netdev_priv(dev); struct rtable *rt = NULL; @@ -759,6 +760,8 @@ static struct rtable *geneve_get_v4_rt(struct sk_buff *skb, memset(fl4, 0, sizeof(*fl4)); fl4->flowi4_mark = skb->mark; fl4->flowi4_proto = IPPROTO_UDP; + fl4->fl4_dport = dport; + fl4->fl4_sport = sport; if (info) { fl4->daddr = info->key.u.ipv4.dst; @@ -793,7 +796,8 @@ static struct rtable *geneve_get_v4_rt(struct sk_buff *skb, static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb, struct net_device *dev, struct flowi6 *fl6, - struct ip_tunnel_info *info) + struct ip_tunnel_info *info, + __be16 dport, __be16 sport) { struct geneve_dev *geneve = netdev_priv(dev); struct geneve_sock *gs6 = geneve->sock6; @@ -803,6 +807,8 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb, memset(fl6, 0, sizeof(*fl6)); fl6->flowi6_mark = skb->mark; fl6->flowi6_proto = IPPROTO_UDP; + fl6->fl6_dport = dport; + fl6->fl6_sport = sport; if (info) { fl6->daddr = info->key.u.ipv6.dst; @@ -873,13 +879,13 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, goto tx_error; } - rt = geneve_get_v4_rt(skb, dev, &fl4, info); + sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); + rt = geneve_get_v4_rt(skb, dev, &fl4, info, geneve->dst_port, sport); if (IS_ERR(rt)) { err = PTR_ERR(rt); goto tx_error; } - sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); skb_reset_mac_header(skb); if (info) { @@ -958,13 +964,13 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, } } - dst = geneve_get_v6_dst(skb, dev, &fl6, info); + sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); + dst = geneve_get_v6_dst(skb, dev, &fl6, info, geneve->dst_port, sport); if (IS_ERR(dst)) { err = PTR_ERR(dst); goto tx_error; } - sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); skb_reset_mac_header(skb); if (info) { @@ -1053,6 +1059,7 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) { struct ip_tunnel_info *info = skb_tunnel_info(skb); struct geneve_dev *geneve = netdev_priv(dev); + __be16 sport; struct rtable *rt; struct flowi4 fl4; #if IS_ENABLED(CONFIG_IPV6) @@ -1061,7 +1068,10 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) #endif if (ip_tunnel_info_af(info) == AF_INET) { - rt = geneve_get_v4_rt(skb, dev, &fl4, info); + sport = udp_flow_src_port(geneve->net, skb, + 1, USHRT_MAX, true); + rt = geneve_get_v4_rt(skb, dev, &fl4, info, geneve->dst_port, + sport); if (IS_ERR(rt)) return PTR_ERR(rt); @@ -1069,7 +1079,10 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) info->key.u.ipv4.src = fl4.saddr; #if IS_ENABLED(CONFIG_IPV6) } else if (ip_tunnel_info_af(info) == AF_INET6) { - dst = geneve_get_v6_dst(skb, dev, &fl6, info); + sport = udp_flow_src_port(geneve->net, skb, + 1, USHRT_MAX, true); + dst = geneve_get_v6_dst(skb, dev, &fl6, info, geneve->dst_port, + sport); if (IS_ERR(dst)) return PTR_ERR(dst); @@ -1080,8 +1093,7 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) return -EINVAL; } - info->key.tp_src = udp_flow_src_port(geneve->net, skb, - 1, USHRT_MAX, true); + info->key.tp_src = sport; info->key.tp_dst = geneve->dst_port; return 0; }