net, decnet: convert dn_fib_info.fib_clntref from atomic_t to refcount_t
authorReshetova, Elena <elena.reshetova@intel.com>
Tue, 4 Jul 2017 12:53:00 +0000 (15:53 +0300)
committerDavid S. Miller <davem@davemloft.net>
Tue, 4 Jul 2017 21:35:15 +0000 (22:35 +0100)
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>
include/net/dn_fib.h
net/decnet/dn_fib.c

index f2ca135ddcc979b07260c5d5996dc79bf7659536..81210a8b8d7c235c812a8f82973d64f4afcaf86b 100644 (file)
@@ -2,6 +2,7 @@
 #define _NET_DN_FIB_H
 
 #include <linux/netlink.h>
+#include <linux/refcount.h>
 
 extern const struct nla_policy rtm_dn_policy[];
 
@@ -28,7 +29,7 @@ struct dn_fib_info {
        struct dn_fib_info      *fib_next;
        struct dn_fib_info      *fib_prev;
        int                     fib_treeref;
-       atomic_t                fib_clntref;
+       refcount_t              fib_clntref;
        int                     fib_dead;
        unsigned int            fib_flags;
        int                     fib_protocol;
@@ -130,7 +131,7 @@ void dn_fib_free_info(struct dn_fib_info *fi);
 
 static inline void dn_fib_info_put(struct dn_fib_info *fi)
 {
-       if (atomic_dec_and_test(&fi->fib_clntref))
+       if (refcount_dec_and_test(&fi->fib_clntref))
                dn_fib_free_info(fi);
 }
 
index f9058ebeb635c2efff457bf73d7895129b443cde..f9f6fb3f3c5b3dd520263448a784a99925c87b09 100644 (file)
@@ -389,7 +389,7 @@ link_it:
        }
 
        fi->fib_treeref++;
-       atomic_inc(&fi->fib_clntref);
+       refcount_set(&fi->fib_clntref, 1);
        spin_lock(&dn_fib_info_lock);
        fi->fib_next = dn_fib_info_list;
        fi->fib_prev = NULL;
@@ -425,7 +425,7 @@ int dn_fib_semantic_match(int type, struct dn_fib_info *fi, const struct flowidn
                switch (type) {
                case RTN_NAT:
                        DN_FIB_RES_RESET(*res);
-                       atomic_inc(&fi->fib_clntref);
+                       refcount_inc(&fi->fib_clntref);
                        return 0;
                case RTN_UNICAST:
                case RTN_LOCAL:
@@ -438,7 +438,7 @@ int dn_fib_semantic_match(int type, struct dn_fib_info *fi, const struct flowidn
                        }
                        if (nhsel < fi->fib_nhs) {
                                res->nh_sel = nhsel;
-                               atomic_inc(&fi->fib_clntref);
+                               refcount_inc(&fi->fib_clntref);
                                return 0;
                        }
                        endfor_nexthops(fi);