Commit 418e897e authored by Willem de Bruijn's avatar Willem de Bruijn Committed by David S. Miller
Browse files

gso: validate gso_type on ipip style tunnels



Commit 121d57af ("gso: validate gso_type in GSO handlers") added
gso_type validation to existing gso_segment callback functions, to
filter out illegal and potentially dangerous SKB_GSO_DODGY packets.

Convert tunnels that now call inet_gso_segment and ipv6_gso_segment
directly to have their own callbacks and extend validation to these.

Signed-off-by: default avatarWillem de Bruijn <willemb@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 203ef5f1
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -1385,6 +1385,15 @@ out:
}
EXPORT_SYMBOL(inet_gso_segment);

static struct sk_buff *ipip_gso_segment(struct sk_buff *skb,
					netdev_features_t features)
{
	if (!(skb_shinfo(skb)->gso_type & SKB_GSO_IPXIP4))
		return ERR_PTR(-EINVAL);

	return inet_gso_segment(skb, features);
}

INDIRECT_CALLABLE_DECLARE(struct sk_buff *tcp4_gro_receive(struct list_head *,
							   struct sk_buff *));
INDIRECT_CALLABLE_DECLARE(struct sk_buff *udp4_gro_receive(struct list_head *,
@@ -1861,7 +1870,7 @@ static struct packet_offload ip_packet_offload __read_mostly = {

static const struct net_offload ipip_offload = {
	.callbacks = {
		.gso_segment	= inet_gso_segment,
		.gso_segment	= ipip_gso_segment,
		.gro_receive	= ipip_gro_receive,
		.gro_complete	= ipip_gro_complete,
	},
+30 −3
Original line number Diff line number Diff line
@@ -383,9 +383,36 @@ static struct packet_offload ipv6_packet_offload __read_mostly = {
	},
};

static struct sk_buff *sit_gso_segment(struct sk_buff *skb,
				       netdev_features_t features)
{
	if (!(skb_shinfo(skb)->gso_type & SKB_GSO_IPXIP4))
		return ERR_PTR(-EINVAL);

	return ipv6_gso_segment(skb, features);
}

static struct sk_buff *ip4ip6_gso_segment(struct sk_buff *skb,
					  netdev_features_t features)
{
	if (!(skb_shinfo(skb)->gso_type & SKB_GSO_IPXIP6))
		return ERR_PTR(-EINVAL);

	return inet_gso_segment(skb, features);
}

static struct sk_buff *ip6ip6_gso_segment(struct sk_buff *skb,
					  netdev_features_t features)
{
	if (!(skb_shinfo(skb)->gso_type & SKB_GSO_IPXIP6))
		return ERR_PTR(-EINVAL);

	return ipv6_gso_segment(skb, features);
}

static const struct net_offload sit_offload = {
	.callbacks = {
		.gso_segment	= ipv6_gso_segment,
		.gso_segment	= sit_gso_segment,
		.gro_receive    = sit_ip6ip6_gro_receive,
		.gro_complete   = sit_gro_complete,
	},
@@ -393,7 +420,7 @@ static const struct net_offload sit_offload = {

static const struct net_offload ip4ip6_offload = {
	.callbacks = {
		.gso_segment	= inet_gso_segment,
		.gso_segment	= ip4ip6_gso_segment,
		.gro_receive    = ip4ip6_gro_receive,
		.gro_complete   = ip4ip6_gro_complete,
	},
@@ -401,7 +428,7 @@ static const struct net_offload ip4ip6_offload = {

static const struct net_offload ip6ip6_offload = {
	.callbacks = {
		.gso_segment	= ipv6_gso_segment,
		.gso_segment	= ip6ip6_gso_segment,
		.gro_receive    = sit_ip6ip6_gro_receive,
		.gro_complete   = ip6ip6_gro_complete,
	},