diff options
Diffstat (limited to 'net/ipv4/af_inet.c')
| -rw-r--r-- | net/ipv4/af_inet.c | 14 |
1 files changed, 11 insertions, 3 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 | ||
