diff options
Diffstat (limited to 'drivers/net/geneve.c')
| -rw-r--r-- | drivers/net/geneve.c | 31 | 
1 files changed, 27 insertions, 4 deletions
| diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 4ac0373326ef..1ab94b5f9bbf 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -461,6 +461,7 @@ static struct socket *geneve_create_sock(struct net *net, bool ipv6,  	if (err < 0)  		return ERR_PTR(err); +	udp_allow_gso(sock->sk);  	return sock;  } @@ -891,6 +892,9 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,  	__be16 sport;  	int err; +	if (!pskb_inet_may_pull(skb)) +		return -EINVAL; +  	sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);  	rt = geneve_get_v4_rt(skb, dev, gs4, &fl4, info,  			      geneve->cfg.info.key.tp_dst, sport); @@ -908,8 +912,16 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,  		info = skb_tunnel_info(skb);  		if (info) { -			info->key.u.ipv4.dst = fl4.saddr; -			info->key.u.ipv4.src = fl4.daddr; +			struct ip_tunnel_info *unclone; + +			unclone = skb_tunnel_info_unclone(skb); +			if (unlikely(!unclone)) { +				dst_release(&rt->dst); +				return -ENOMEM; +			} + +			unclone->key.u.ipv4.dst = fl4.saddr; +			unclone->key.u.ipv4.src = fl4.daddr;  		}  		if (!pskb_may_pull(skb, ETH_HLEN)) { @@ -977,6 +989,9 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,  	__be16 sport;  	int err; +	if (!pskb_inet_may_pull(skb)) +		return -EINVAL; +  	sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);  	dst = geneve_get_v6_dst(skb, dev, gs6, &fl6, info,  				geneve->cfg.info.key.tp_dst, sport); @@ -993,8 +1008,16 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,  		struct ip_tunnel_info *info = skb_tunnel_info(skb);  		if (info) { -			info->key.u.ipv6.dst = fl6.saddr; -			info->key.u.ipv6.src = fl6.daddr; +			struct ip_tunnel_info *unclone; + +			unclone = skb_tunnel_info_unclone(skb); +			if (unlikely(!unclone)) { +				dst_release(dst); +				return -ENOMEM; +			} + +			unclone->key.u.ipv6.dst = fl6.saddr; +			unclone->key.u.ipv6.src = fl6.daddr;  		}  		if (!pskb_may_pull(skb, ETH_HLEN)) { | 
