int igmp6_event_query(struct sk_buff *skb)
 {
-       struct mld2_query *mlh2 = (struct mld2_query *) skb->h.raw;
+       struct mld2_query *mlh2 = NULL;
        struct ifmcaddr6 *ma;
        struct in6_addr *group;
        unsigned long max_delay;
                /* clear deleted report items */
                mld_clear_delrec(idev);
        } else if (len >= 28) {
+               int srcs_offset = sizeof(struct mld2_query) - 
+                                 sizeof(struct icmp6hdr);
+               if (!pskb_may_pull(skb, srcs_offset)) {
+                       in6_dev_put(idev);
+                       return -EINVAL;
+               }
+               mlh2 = (struct mld2_query *) skb->h.raw;
                max_delay = (MLDV2_MRC(ntohs(mlh2->mrc))*HZ)/1000;
                if (!max_delay)
                        max_delay = 1;
                        return 0;
                }
                /* mark sources to include, if group & source-specific */
-               mark = mlh2->nsrcs != 0;
+               if (mlh2->nsrcs != 0) {
+                       if (!pskb_may_pull(skb, srcs_offset + 
+                               mlh2->nsrcs * sizeof(struct in6_addr))) {
+                               in6_dev_put(idev);
+                               return -EINVAL;
+                       }
+                       mlh2 = (struct mld2_query *) skb->h.raw;
+                       mark = 1;
+               }
        } else {
                in6_dev_put(idev);
                return -EINVAL;