diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/ipv4/ip_fragment.c | 19 |
1 files changed, 9 insertions, 10 deletions
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 448e68546827..8d5cc75dac88 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
| @@ -707,28 +707,27 @@ EXPORT_SYMBOL(ip_defrag); | |||
| 707 | 707 | ||
| 708 | struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user) | 708 | struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user) |
| 709 | { | 709 | { |
| 710 | const struct iphdr *iph; | 710 | struct iphdr iph; |
| 711 | u32 len; | 711 | u32 len; |
| 712 | 712 | ||
| 713 | if (skb->protocol != htons(ETH_P_IP)) | 713 | if (skb->protocol != htons(ETH_P_IP)) |
| 714 | return skb; | 714 | return skb; |
| 715 | 715 | ||
| 716 | if (!pskb_may_pull(skb, sizeof(struct iphdr))) | 716 | if (!skb_copy_bits(skb, 0, &iph, sizeof(iph))) |
| 717 | return skb; | 717 | return skb; |
| 718 | 718 | ||
| 719 | iph = ip_hdr(skb); | 719 | if (iph.ihl < 5 || iph.version != 4) |
| 720 | if (iph->ihl < 5 || iph->version != 4) | ||
| 721 | return skb; | 720 | return skb; |
| 722 | if (!pskb_may_pull(skb, iph->ihl*4)) | 721 | |
| 723 | return skb; | 722 | len = ntohs(iph.tot_len); |
| 724 | iph = ip_hdr(skb); | 723 | if (skb->len < len || len < (iph.ihl * 4)) |
| 725 | len = ntohs(iph->tot_len); | ||
| 726 | if (skb->len < len || len < (iph->ihl * 4)) | ||
| 727 | return skb; | 724 | return skb; |
| 728 | 725 | ||
| 729 | if (ip_is_fragment(ip_hdr(skb))) { | 726 | if (ip_is_fragment(&iph)) { |
| 730 | skb = skb_share_check(skb, GFP_ATOMIC); | 727 | skb = skb_share_check(skb, GFP_ATOMIC); |
| 731 | if (skb) { | 728 | if (skb) { |
| 729 | if (!pskb_may_pull(skb, iph.ihl*4)) | ||
| 730 | return skb; | ||
| 732 | if (pskb_trim_rcsum(skb, len)) | 731 | if (pskb_trim_rcsum(skb, len)) |
| 733 | return skb; | 732 | return skb; |
| 734 | memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); | 733 | memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); |
