summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorReshetova, Elena <elena.reshetova@intel.com>2017-06-30 06:08:02 -0400
committerDavid S. Miller <davem@davemloft.net>2017-07-01 10:39:08 -0400
commit8851ab526791530d00bbbd0952512d68684a44b8 (patch)
tree243643b2d0b72bed9947ec525be6f6142e2b6840
parent41c6d650f6537e55a1b53438c646fbc3f49176bf (diff)
net: convert ip_mc_list.refcnt from atomic_t to refcount_t
refcount_t type and corresponding API should be used instead of atomic_t when the variable is used as a reference counter. This allows to avoid accidental refcounter overflows that might lead to use-after-free situations. Signed-off-by: Elena Reshetova <elena.reshetova@intel.com> Signed-off-by: Hans Liljestrand <ishkamiel@gmail.com> Signed-off-by: Kees Cook <keescook@chromium.org> Signed-off-by: David Windsor <dwindsor@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/igmp.h3
-rw-r--r--net/ipv4/igmp.c10
2 files changed, 7 insertions, 6 deletions
diff --git a/include/linux/igmp.h b/include/linux/igmp.h
index 12f6fba6d21a..97caf1821de8 100644
--- a/include/linux/igmp.h
+++ b/include/linux/igmp.h
@@ -18,6 +18,7 @@
18#include <linux/skbuff.h> 18#include <linux/skbuff.h>
19#include <linux/timer.h> 19#include <linux/timer.h>
20#include <linux/in.h> 20#include <linux/in.h>
21#include <linux/refcount.h>
21#include <uapi/linux/igmp.h> 22#include <uapi/linux/igmp.h>
22 23
23static inline struct igmphdr *igmp_hdr(const struct sk_buff *skb) 24static inline struct igmphdr *igmp_hdr(const struct sk_buff *skb)
@@ -84,7 +85,7 @@ struct ip_mc_list {
84 struct ip_mc_list __rcu *next_hash; 85 struct ip_mc_list __rcu *next_hash;
85 struct timer_list timer; 86 struct timer_list timer;
86 int users; 87 int users;
87 atomic_t refcnt; 88 refcount_t refcnt;
88 spinlock_t lock; 89 spinlock_t lock;
89 char tm_running; 90 char tm_running;
90 char reporter; 91 char reporter;
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index c4032302d7cd..28f14afd0dd3 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -173,7 +173,7 @@ static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
173 173
174static void ip_ma_put(struct ip_mc_list *im) 174static void ip_ma_put(struct ip_mc_list *im)
175{ 175{
176 if (atomic_dec_and_test(&im->refcnt)) { 176 if (refcount_dec_and_test(&im->refcnt)) {
177 in_dev_put(im->interface); 177 in_dev_put(im->interface);
178 kfree_rcu(im, rcu); 178 kfree_rcu(im, rcu);
179 } 179 }
@@ -199,7 +199,7 @@ static void igmp_stop_timer(struct ip_mc_list *im)
199{ 199{
200 spin_lock_bh(&im->lock); 200 spin_lock_bh(&im->lock);
201 if (del_timer(&im->timer)) 201 if (del_timer(&im->timer))
202 atomic_dec(&im->refcnt); 202 refcount_dec(&im->refcnt);
203 im->tm_running = 0; 203 im->tm_running = 0;
204 im->reporter = 0; 204 im->reporter = 0;
205 im->unsolicit_count = 0; 205 im->unsolicit_count = 0;
@@ -213,7 +213,7 @@ static void igmp_start_timer(struct ip_mc_list *im, int max_delay)
213 213
214 im->tm_running = 1; 214 im->tm_running = 1;
215 if (!mod_timer(&im->timer, jiffies+tv+2)) 215 if (!mod_timer(&im->timer, jiffies+tv+2))
216 atomic_inc(&im->refcnt); 216 refcount_inc(&im->refcnt);
217} 217}
218 218
219static void igmp_gq_start_timer(struct in_device *in_dev) 219static void igmp_gq_start_timer(struct in_device *in_dev)
@@ -249,7 +249,7 @@ static void igmp_mod_timer(struct ip_mc_list *im, int max_delay)
249 spin_unlock_bh(&im->lock); 249 spin_unlock_bh(&im->lock);
250 return; 250 return;
251 } 251 }
252 atomic_dec(&im->refcnt); 252 refcount_dec(&im->refcnt);
253 } 253 }
254 igmp_start_timer(im, max_delay); 254 igmp_start_timer(im, max_delay);
255 spin_unlock_bh(&im->lock); 255 spin_unlock_bh(&im->lock);
@@ -1374,7 +1374,7 @@ void ip_mc_inc_group(struct in_device *in_dev, __be32 addr)
1374 /* initial mode is (EX, empty) */ 1374 /* initial mode is (EX, empty) */
1375 im->sfmode = MCAST_EXCLUDE; 1375 im->sfmode = MCAST_EXCLUDE;
1376 im->sfcount[MCAST_EXCLUDE] = 1; 1376 im->sfcount[MCAST_EXCLUDE] = 1;
1377 atomic_set(&im->refcnt, 1); 1377 refcount_set(&im->refcnt, 1);
1378 spin_lock_init(&im->lock); 1378 spin_lock_init(&im->lock);
1379#ifdef CONFIG_IP_MULTICAST 1379#ifdef CONFIG_IP_MULTICAST
1380 setup_timer(&im->timer, igmp_timer_expire, (unsigned long)im); 1380 setup_timer(&im->timer, igmp_timer_expire, (unsigned long)im);