[IPSEC]: Fix length check in xfrm_parse_spi
[cascardo/linux.git] / net / xfrm / xfrm_input.c
index ee15bda..cb97fda 100644 (file)
@@ -49,31 +49,34 @@ EXPORT_SYMBOL(secpath_dup);
 int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq)
 {
        int offset, offset_seq;
+       int hlen;
 
        switch (nexthdr) {
        case IPPROTO_AH:
+               hlen = sizeof(struct ip_auth_hdr);
                offset = offsetof(struct ip_auth_hdr, spi);
                offset_seq = offsetof(struct ip_auth_hdr, seq_no);
                break;
        case IPPROTO_ESP:
+               hlen = sizeof(struct ip_esp_hdr);
                offset = offsetof(struct ip_esp_hdr, spi);
                offset_seq = offsetof(struct ip_esp_hdr, seq_no);
                break;
        case IPPROTO_COMP:
                if (!pskb_may_pull(skb, sizeof(struct ip_comp_hdr)))
                        return -EINVAL;
-               *spi = htonl(ntohs(*(__be16*)(skb->h.raw + 2)));
+               *spi = htonl(ntohs(*(__be16*)(skb_transport_header(skb) + 2)));
                *seq = 0;
                return 0;
        default:
                return 1;
        }
 
-       if (!pskb_may_pull(skb, 16))
+       if (!pskb_may_pull(skb, hlen))
                return -EINVAL;
 
-       *spi = *(__be32*)(skb->h.raw + offset);
-       *seq = *(__be32*)(skb->h.raw + offset_seq);
+       *spi = *(__be32*)(skb_transport_header(skb) + offset);
+       *seq = *(__be32*)(skb_transport_header(skb) + offset_seq);
        return 0;
 }
 EXPORT_SYMBOL(xfrm_parse_spi);
@@ -83,5 +86,5 @@ void __init xfrm_input_init(void)
        secpath_cachep = kmem_cache_create("secpath_cache",
                                           sizeof(struct sec_path),
                                           0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
-                                          NULL, NULL);
+                                          NULL);
 }