aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv4/af_inet.c14
-rw-r--r--net/ipv4/tcp.c13
-rw-r--r--net/ipv6/ipv6_sockglue.c8
3 files changed, 31 insertions, 4 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 8d157157bf8..318d4674faa 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 804458712d8..f6a2d9223d0 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 c28e5c28744..ec59344478d 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