Skip to content

Commit

Permalink
igmp: avoid drop_monitor false positives
Browse files Browse the repository at this point in the history
igmp should call consume_skb() for all correctly processed packets,
to avoid false dropwatch/drop_monitor false positives.

Reported-by: Shawn Bohrer <sbohrer@rgmadvisors.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Eric Dumazet authored and David S. Miller committed Sep 7, 2012
1 parent e966c8e commit d679c53
Showing 1 changed file with 19 additions and 11 deletions.
30 changes: 19 additions & 11 deletions net/ipv4/igmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -815,14 +815,15 @@ static int igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __be32 *srcs)
return 1;
}

static void igmp_heard_report(struct in_device *in_dev, __be32 group)
/* return true if packet was dropped */
static bool igmp_heard_report(struct in_device *in_dev, __be32 group)
{
struct ip_mc_list *im;

/* Timers are only set for non-local groups */

if (group == IGMP_ALL_HOSTS)
return;
return false;

rcu_read_lock();
for_each_pmc_rcu(in_dev, im) {
Expand All @@ -832,9 +833,11 @@ static void igmp_heard_report(struct in_device *in_dev, __be32 group)
}
}
rcu_read_unlock();
return false;
}

static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
/* return true if packet was dropped */
static bool igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
int len)
{
struct igmphdr *ih = igmp_hdr(skb);
Expand Down Expand Up @@ -866,7 +869,7 @@ static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
/* clear deleted report items */
igmpv3_clear_delrec(in_dev);
} else if (len < 12) {
return; /* ignore bogus packet; freed by caller */
return true; /* ignore bogus packet; freed by caller */
} else if (IGMP_V1_SEEN(in_dev)) {
/* This is a v3 query with v1 queriers present */
max_delay = IGMP_Query_Response_Interval;
Expand All @@ -883,13 +886,13 @@ static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
max_delay = 1; /* can't mod w/ 0 */
} else { /* v3 */
if (!pskb_may_pull(skb, sizeof(struct igmpv3_query)))
return;
return true;

ih3 = igmpv3_query_hdr(skb);
if (ih3->nsrcs) {
if (!pskb_may_pull(skb, sizeof(struct igmpv3_query)
+ ntohs(ih3->nsrcs)*sizeof(__be32)))
return;
return true;
ih3 = igmpv3_query_hdr(skb);
}

Expand All @@ -901,9 +904,9 @@ static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
in_dev->mr_qrv = ih3->qrv;
if (!group) { /* general query */
if (ih3->nsrcs)
return; /* no sources allowed */
return false; /* no sources allowed */
igmp_gq_start_timer(in_dev);
return;
return false;
}
/* mark sources to include, if group & source-specific */
mark = ih3->nsrcs != 0;
Expand Down Expand Up @@ -939,6 +942,7 @@ static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
igmp_mod_timer(im, max_delay);
}
rcu_read_unlock();
return false;
}

/* called in rcu_read_lock() section */
Expand All @@ -948,6 +952,7 @@ int igmp_rcv(struct sk_buff *skb)
struct igmphdr *ih;
struct in_device *in_dev = __in_dev_get_rcu(skb->dev);
int len = skb->len;
bool dropped = true;

if (in_dev == NULL)
goto drop;
Expand All @@ -969,7 +974,7 @@ int igmp_rcv(struct sk_buff *skb)
ih = igmp_hdr(skb);
switch (ih->type) {
case IGMP_HOST_MEMBERSHIP_QUERY:
igmp_heard_query(in_dev, skb, len);
dropped = igmp_heard_query(in_dev, skb, len);
break;
case IGMP_HOST_MEMBERSHIP_REPORT:
case IGMPV2_HOST_MEMBERSHIP_REPORT:
Expand All @@ -979,7 +984,7 @@ int igmp_rcv(struct sk_buff *skb)
/* don't rely on MC router hearing unicast reports */
if (skb->pkt_type == PACKET_MULTICAST ||
skb->pkt_type == PACKET_BROADCAST)
igmp_heard_report(in_dev, ih->group);
dropped = igmp_heard_report(in_dev, ih->group);
break;
case IGMP_PIM:
#ifdef CONFIG_IP_PIMSM_V1
Expand All @@ -997,7 +1002,10 @@ int igmp_rcv(struct sk_buff *skb)
}

drop:
kfree_skb(skb);
if (dropped)
kfree_skb(skb);
else
consume_skb(skb);
return 0;
}

Expand Down

0 comments on commit d679c53

Please sign in to comment.