]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/ipv6/mcast.c
[MCAST] IPv6: Check packet size when process Multicast
[net-next-2.6.git] / net / ipv6 / mcast.c
index c4f2a0ef7489b08147f1f98baa776a33e23d0513..966b2372aaab46eb8b140d779b2e048a3defdaf5 100644 (file)
@@ -1087,7 +1087,7 @@ static void mld_marksources(struct ifmcaddr6 *pmc, int nsrcs,
 
 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;
@@ -1140,6 +1140,13 @@ int igmp6_event_query(struct sk_buff *skb)
                /* 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;
@@ -1156,7 +1163,15 @@ int igmp6_event_query(struct sk_buff *skb)
                        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;