Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6d742324 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'tnl-ipv4-ipv6'



Jiri Benc says:

====================
tunnels: fix incorrect IPv4/v6 headers interpretation

With tunneling, it is currently possible to get an IPv6 header and interpret
it as an IPv4 header, or to interpret an IPv6 address as an IPv4 address
(and vice versa). This leads to things like sending packets to incorrect
address, IPv6 flow label being interpreted as IP packet length, etc.

Fix several places where this can happen.

Most of this is net-next only. The third patch affects net, too, but it
doesn't seem there's anything in user space that sets the attribute at all
currently, thus net-next is fine.

Changelog:
v2: fixed geneve after incorrect rebase on top of Pravin's patches
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f6d3c192 a43a9ef6
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -623,10 +623,12 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev)

	if (geneve->collect_md) {
		info = skb_tunnel_info(skb);
		if (unlikely(info && info->mode != IP_TUNNEL_INFO_TX)) {
		if (unlikely(info && !(info->mode & IP_TUNNEL_INFO_TX))) {
			netdev_dbg(dev, "no tunnel metadata\n");
			goto tx_error;
		}
		if (info && ip_tunnel_info_af(info) != AF_INET)
			goto tx_error;
	}

	rt = geneve_get_rt(skb, dev, &fl4, info);
+4 −1
Original line number Diff line number Diff line
@@ -1903,6 +1903,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
				  dev->name);
			goto drop;
		}
		if (family != ip_tunnel_info_af(info))
			goto drop;

		dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port;
		vni = be64_to_cpu(info->key.tun_id);
@@ -2113,7 +2115,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
	}

	if (vxlan->flags & VXLAN_F_COLLECT_METADATA &&
	    info && info->mode == IP_TUNNEL_INFO_TX) {
	    info && info->mode & IP_TUNNEL_INFO_TX) {
		vxlan_xmit_one(skb, dev, NULL, false);
		return NETDEV_TX_OK;
	}
@@ -2528,6 +2530,7 @@ static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
		udp_conf.family = AF_INET6;
		udp_conf.use_udp6_rx_checksums =
		    !(flags & VXLAN_F_UDP_ZERO_CSUM6_RX);
		udp_conf.ipv6_v6only = 1;
	} else {
		udp_conf.family = AF_INET;
	}
+1 −1
Original line number Diff line number Diff line
@@ -59,7 +59,6 @@ static inline struct metadata_dst *tun_rx_dst(__be16 flags,
		return NULL;

	info = &tun_dst->u.tun_info;
	info->mode = IP_TUNNEL_INFO_RX;
	info->key.tun_flags = flags;
	info->key.tun_id = tunnel_id;
	info->key.tp_src = 0;
@@ -106,6 +105,7 @@ static inline struct metadata_dst *ipv6_tun_rx_dst(struct sk_buff *skb,
	info->key.u.ipv6.dst = ip6h->daddr;
	info->key.tos = ipv6_get_dsfield(ip6h);
	info->key.ttl = ip6h->hop_limit;
	info->mode = IP_TUNNEL_INFO_IPV6;
	return tun_dst;
}

+12 −7
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@
#include <linux/if_tunnel.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/socket.h>
#include <linux/types.h>
#include <linux/u64_stats_sync.h>
#include <net/dsfield.h>
@@ -50,13 +51,9 @@ struct ip_tunnel_key {
	__be16			tp_dst;
};

/* Indicates whether the tunnel info structure represents receive
 * or transmit tunnel parameters.
 */
enum {
	IP_TUNNEL_INFO_RX,
	IP_TUNNEL_INFO_TX,
};
/* Flags for ip_tunnel_info mode. */
#define IP_TUNNEL_INFO_TX	0x01	/* represents tx tunnel parameters */
#define IP_TUNNEL_INFO_IPV6	0x02	/* key contains IPv6 addresses */

struct ip_tunnel_info {
	struct ip_tunnel_key	key;
@@ -213,6 +210,8 @@ static inline void __ip_tunnel_info_init(struct ip_tunnel_info *tun_info,

	tun_info->options = opts;
	tun_info->options_len = opts_len;

	tun_info->mode = 0;
}

static inline void ip_tunnel_info_init(struct ip_tunnel_info *tun_info,
@@ -226,6 +225,12 @@ static inline void ip_tunnel_info_init(struct ip_tunnel_info *tun_info,
			      tun_id, tun_flags, opts, opts_len);
}

static inline unsigned short ip_tunnel_info_af(const struct ip_tunnel_info
					       *tun_info)
{
	return tun_info->mode & IP_TUNNEL_INFO_IPV6 ? AF_INET6 : AF_INET;
}

#ifdef CONFIG_INET

int ip_tunnel_init(struct net_device *dev);
+2 −1
Original line number Diff line number Diff line
@@ -31,7 +31,8 @@ struct udp_port_cfg {
	__be16			peer_udp_port;
	unsigned int		use_udp_checksums:1,
				use_udp6_tx_checksums:1,
				use_udp6_rx_checksums:1;
				use_udp6_rx_checksums:1,
				ipv6_v6only:1;
};

int udp_sock_create4(struct net *net, struct udp_port_cfg *cfg,
Loading