Commit ba3b62bb authored by David Stevens's avatar David Stevens Committed by David S. Miller

[IPV4/IPV6]: Fix IGMP device refcount leaks, with help from yoshfuji@linux-ipv6.org.

parent 7976f8f6
...@@ -178,7 +178,7 @@ static void igmp_gq_start_timer(struct in_device *in_dev) ...@@ -178,7 +178,7 @@ static void igmp_gq_start_timer(struct in_device *in_dev)
in_dev->mr_gq_running = 1; in_dev->mr_gq_running = 1;
if (!mod_timer(&in_dev->mr_gq_timer, jiffies+tv+2)) if (!mod_timer(&in_dev->mr_gq_timer, jiffies+tv+2))
atomic_inc(&in_dev->refcnt); in_dev_hold(in_dev);
} }
static void igmp_ifc_start_timer(struct in_device *in_dev, int delay) static void igmp_ifc_start_timer(struct in_device *in_dev, int delay)
...@@ -186,7 +186,7 @@ static void igmp_ifc_start_timer(struct in_device *in_dev, int delay) ...@@ -186,7 +186,7 @@ static void igmp_ifc_start_timer(struct in_device *in_dev, int delay)
int tv = net_random() % delay; int tv = net_random() % delay;
if (!mod_timer(&in_dev->mr_ifc_timer, jiffies+tv+2)) if (!mod_timer(&in_dev->mr_ifc_timer, jiffies+tv+2))
atomic_inc(&in_dev->refcnt); in_dev_hold(in_dev);
} }
static void igmp_mod_timer(struct ip_mc_list *im, int max_delay) static void igmp_mod_timer(struct ip_mc_list *im, int max_delay)
...@@ -670,6 +670,7 @@ static void igmp_gq_timer_expire(unsigned long data) ...@@ -670,6 +670,7 @@ static void igmp_gq_timer_expire(unsigned long data)
in_dev->mr_gq_running = 0; in_dev->mr_gq_running = 0;
igmpv3_send_report(in_dev, 0); igmpv3_send_report(in_dev, 0);
__in_dev_put(in_dev);
} }
static void igmp_ifc_timer_expire(unsigned long data) static void igmp_ifc_timer_expire(unsigned long data)
...@@ -681,6 +682,7 @@ static void igmp_ifc_timer_expire(unsigned long data) ...@@ -681,6 +682,7 @@ static void igmp_ifc_timer_expire(unsigned long data)
in_dev->mr_ifc_count--; in_dev->mr_ifc_count--;
igmp_ifc_start_timer(in_dev, IGMP_Unsolicited_Report_Interval); igmp_ifc_start_timer(in_dev, IGMP_Unsolicited_Report_Interval);
} }
__in_dev_put(in_dev);
} }
static void igmp_ifc_event(struct in_device *in_dev) static void igmp_ifc_event(struct in_device *in_dev)
...@@ -782,7 +784,7 @@ static void igmp_heard_query(struct in_device *in_dev, struct igmphdr *ih, ...@@ -782,7 +784,7 @@ static void igmp_heard_query(struct in_device *in_dev, struct igmphdr *ih,
/* cancel the interface change timer */ /* cancel the interface change timer */
in_dev->mr_ifc_count = 0; in_dev->mr_ifc_count = 0;
if (del_timer(&in_dev->mr_ifc_timer)) if (del_timer(&in_dev->mr_ifc_timer))
atomic_dec(&in_dev->refcnt); __in_dev_put(in_dev);
/* clear deleted report items */ /* clear deleted report items */
igmpv3_clear_delrec(in_dev); igmpv3_clear_delrec(in_dev);
} else if (len < 12) { } else if (len < 12) {
...@@ -1197,10 +1199,10 @@ void ip_mc_down(struct in_device *in_dev) ...@@ -1197,10 +1199,10 @@ void ip_mc_down(struct in_device *in_dev)
#ifdef CONFIG_IP_MULTICAST #ifdef CONFIG_IP_MULTICAST
in_dev->mr_ifc_count = 0; in_dev->mr_ifc_count = 0;
if (del_timer(&in_dev->mr_ifc_timer)) if (del_timer(&in_dev->mr_ifc_timer))
atomic_dec(&in_dev->refcnt); __in_dev_put(in_dev);
in_dev->mr_gq_running = 0; in_dev->mr_gq_running = 0;
if (del_timer(&in_dev->mr_gq_timer)) if (del_timer(&in_dev->mr_gq_timer))
atomic_dec(&in_dev->refcnt); __in_dev_put(in_dev);
#endif #endif
for (i=in_dev->mc_list; i; i=i->next) for (i=in_dev->mc_list; i; i=i->next)
......
...@@ -1904,6 +1904,7 @@ static void mld_gq_timer_expire(unsigned long data) ...@@ -1904,6 +1904,7 @@ static void mld_gq_timer_expire(unsigned long data)
idev->mc_gq_running = 0; idev->mc_gq_running = 0;
mld_send_report(idev, 0); mld_send_report(idev, 0);
__in6_dev_put(idev);
} }
static void mld_ifc_timer_expire(unsigned long data) static void mld_ifc_timer_expire(unsigned long data)
...@@ -1916,6 +1917,7 @@ static void mld_ifc_timer_expire(unsigned long data) ...@@ -1916,6 +1917,7 @@ static void mld_ifc_timer_expire(unsigned long data)
if (idev->mc_ifc_count) if (idev->mc_ifc_count)
mld_ifc_start_timer(idev, idev->mc_maxdelay); mld_ifc_start_timer(idev, idev->mc_maxdelay);
} }
__in6_dev_put(idev);
} }
static void mld_ifc_event(struct inet6_dev *idev) static void mld_ifc_event(struct inet6_dev *idev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment