diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2006-07-03 22:38:35 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-07-03 22:38:35 -0400 |
commit | bbcf467dab42ea3c85f368df346c82af2fbba665 (patch) | |
tree | e9fe30c1be9c6a3773454bad3eefaabf4f5bee48 | |
parent | 6ce1669fdb6b0a0faf9b2e2ba08048b520c57841 (diff) |
[NET]: Verify gso_type too in gso_segment
We don't want nasty Xen guests to pass a TCPv6 packet in with gso_type set
to TCPv4 or even UDP (or a packet that's both TCP and UDP).
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv4/af_inet.c | 14 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 13 | ||||
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 8 |
3 files changed, 31 insertions, 4 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 8d157157bf8e..318d4674faa1 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -1106,7 +1106,15 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features) | |||
1106 | int ihl; | 1106 | int ihl; |
1107 | int id; | 1107 | int id; |
1108 | 1108 | ||
1109 | if (!pskb_may_pull(skb, sizeof(*iph))) | 1109 | if (unlikely(skb_shinfo(skb)->gso_type & |
1110 | ~(SKB_GSO_TCPV4 | | ||
1111 | SKB_GSO_UDP | | ||
1112 | SKB_GSO_DODGY | | ||
1113 | SKB_GSO_TCP_ECN | | ||
1114 | 0))) | ||
1115 | goto out; | ||
1116 | |||
1117 | if (unlikely(!pskb_may_pull(skb, sizeof(*iph)))) | ||
1110 | goto out; | 1118 | goto out; |
1111 | 1119 | ||
1112 | iph = skb->nh.iph; | 1120 | iph = skb->nh.iph; |
@@ -1114,7 +1122,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features) | |||
1114 | if (ihl < sizeof(*iph)) | 1122 | if (ihl < sizeof(*iph)) |
1115 | goto out; | 1123 | goto out; |
1116 | 1124 | ||
1117 | if (!pskb_may_pull(skb, ihl)) | 1125 | if (unlikely(!pskb_may_pull(skb, ihl))) |
1118 | goto out; | 1126 | goto out; |
1119 | 1127 | ||
1120 | skb->h.raw = __skb_pull(skb, ihl); | 1128 | skb->h.raw = __skb_pull(skb, ihl); |
@@ -1125,7 +1133,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features) | |||
1125 | 1133 | ||
1126 | rcu_read_lock(); | 1134 | rcu_read_lock(); |
1127 | ops = rcu_dereference(inet_protos[proto]); | 1135 | ops = rcu_dereference(inet_protos[proto]); |
1128 | if (ops && ops->gso_segment) | 1136 | if (likely(ops && ops->gso_segment)) |
1129 | segs = ops->gso_segment(skb, features); | 1137 | segs = ops->gso_segment(skb, features); |
1130 | rcu_read_unlock(); | 1138 | rcu_read_unlock(); |
1131 | 1139 | ||
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 804458712d88..f6a2d9223d07 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -2170,8 +2170,19 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) | |||
2170 | 2170 | ||
2171 | if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) { | 2171 | if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) { |
2172 | /* Packet is from an untrusted source, reset gso_segs. */ | 2172 | /* Packet is from an untrusted source, reset gso_segs. */ |
2173 | int mss = skb_shinfo(skb)->gso_size; | 2173 | int type = skb_shinfo(skb)->gso_type; |
2174 | int mss; | ||
2175 | |||
2176 | if (unlikely(type & | ||
2177 | ~(SKB_GSO_TCPV4 | | ||
2178 | SKB_GSO_DODGY | | ||
2179 | SKB_GSO_TCP_ECN | | ||
2180 | SKB_GSO_TCPV6 | | ||
2181 | 0) || | ||
2182 | !(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))) | ||
2183 | goto out; | ||
2174 | 2184 | ||
2185 | mss = skb_shinfo(skb)->gso_size; | ||
2175 | skb_shinfo(skb)->gso_segs = (skb->len + mss - 1) / mss; | 2186 | skb_shinfo(skb)->gso_segs = (skb->len + mss - 1) / mss; |
2176 | 2187 | ||
2177 | segs = NULL; | 2188 | segs = NULL; |
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index c28e5c287447..ec59344478d2 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -64,6 +64,14 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features) | |||
64 | struct inet6_protocol *ops; | 64 | struct inet6_protocol *ops; |
65 | int proto; | 65 | int proto; |
66 | 66 | ||
67 | if (unlikely(skb_shinfo(skb)->gso_type & | ||
68 | ~(SKB_GSO_UDP | | ||
69 | SKB_GSO_DODGY | | ||
70 | SKB_GSO_TCP_ECN | | ||
71 | SKB_GSO_TCPV6 | | ||
72 | 0))) | ||
73 | goto out; | ||
74 | |||
67 | if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) | 75 | if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) |
68 | goto out; | 76 | goto out; |
69 | 77 | ||