Browse Source

net: convert netpoll_info.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>
Reshetova, Elena 8 years ago
parent
commit
433cea4d9b
2 changed files with 5 additions and 4 deletions
  1. 2 1
      include/linux/netpoll.h
  2. 3 3
      net/core/netpoll.c

+ 2 - 1
include/linux/netpoll.h

@@ -11,6 +11,7 @@
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
 #include <linux/rcupdate.h>
 #include <linux/rcupdate.h>
 #include <linux/list.h>
 #include <linux/list.h>
+#include <linux/refcount.h>
 
 
 union inet_addr {
 union inet_addr {
 	__u32		all[4];
 	__u32		all[4];
@@ -34,7 +35,7 @@ struct netpoll {
 };
 };
 
 
 struct netpoll_info {
 struct netpoll_info {
-	atomic_t refcnt;
+	refcount_t refcnt;
 
 
 	struct semaphore dev_lock;
 	struct semaphore dev_lock;
 
 

+ 3 - 3
net/core/netpoll.c

@@ -632,7 +632,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev)
 		skb_queue_head_init(&npinfo->txq);
 		skb_queue_head_init(&npinfo->txq);
 		INIT_DELAYED_WORK(&npinfo->tx_work, queue_process);
 		INIT_DELAYED_WORK(&npinfo->tx_work, queue_process);
 
 
-		atomic_set(&npinfo->refcnt, 1);
+		refcount_set(&npinfo->refcnt, 1);
 
 
 		ops = np->dev->netdev_ops;
 		ops = np->dev->netdev_ops;
 		if (ops->ndo_netpoll_setup) {
 		if (ops->ndo_netpoll_setup) {
@@ -642,7 +642,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev)
 		}
 		}
 	} else {
 	} else {
 		npinfo = rtnl_dereference(ndev->npinfo);
 		npinfo = rtnl_dereference(ndev->npinfo);
-		atomic_inc(&npinfo->refcnt);
+		refcount_inc(&npinfo->refcnt);
 	}
 	}
 
 
 	npinfo->netpoll = np;
 	npinfo->netpoll = np;
@@ -821,7 +821,7 @@ void __netpoll_cleanup(struct netpoll *np)
 
 
 	synchronize_srcu(&netpoll_srcu);
 	synchronize_srcu(&netpoll_srcu);
 
 
-	if (atomic_dec_and_test(&npinfo->refcnt)) {
+	if (refcount_dec_and_test(&npinfo->refcnt)) {
 		const struct net_device_ops *ops;
 		const struct net_device_ops *ops;
 
 
 		ops = np->dev->netdev_ops;
 		ops = np->dev->netdev_ops;