net: convert unix_address.refcnt from atomic_t to refcount_t
authorReshetova, Elena <elena.reshetova@intel.com>
Fri, 30 Jun 2017 10:08:05 +0000 (13:08 +0300)
committerDavid S. Miller <davem@davemloft.net>
Sat, 1 Jul 2017 14:39:08 +0000 (07:39 -0700)
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/af_unix.h
net/unix/af_unix.c

index fd60eccb59a67969eba53416a376a3c912d62d81..3a385e4767f031fb93d3558d935c9806699b4c74 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/socket.h>
 #include <linux/un.h>
 #include <linux/mutex.h>
+#include <linux/refcount.h>
 #include <net/sock.h>
 
 void unix_inflight(struct user_struct *user, struct file *fp);
@@ -21,7 +22,7 @@ extern spinlock_t unix_table_lock;
 extern struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE];
 
 struct unix_address {
-       atomic_t        refcnt;
+       refcount_t      refcnt;
        int             len;
        unsigned int    hash;
        struct sockaddr_un name[0];
index c88525403d2e91f9cc41a0e0574ad570d9190d7a..b9ee766054f6c906529c9f052bef7824e998617b 100644 (file)
@@ -212,7 +212,7 @@ EXPORT_SYMBOL_GPL(unix_peer_get);
 
 static inline void unix_release_addr(struct unix_address *addr)
 {
-       if (atomic_dec_and_test(&addr->refcnt))
+       if (refcount_dec_and_test(&addr->refcnt))
                kfree(addr);
 }
 
@@ -864,7 +864,7 @@ static int unix_autobind(struct socket *sock)
                goto out;
 
        addr->name->sun_family = AF_UNIX;
-       atomic_set(&addr->refcnt, 1);
+       refcount_set(&addr->refcnt, 1);
 
 retry:
        addr->len = sprintf(addr->name->sun_path+1, "%05x", ordernum) + 1 + sizeof(short);
@@ -1040,7 +1040,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        memcpy(addr->name, sunaddr, addr_len);
        addr->len = addr_len;
        addr->hash = hash ^ sk->sk_type;
-       atomic_set(&addr->refcnt, 1);
+       refcount_set(&addr->refcnt, 1);
 
        if (sun_path[0]) {
                addr->hash = UNIX_HASH_SIZE;
@@ -1335,7 +1335,7 @@ restart:
 
        /* copy address information from listening to new sock*/
        if (otheru->addr) {
-               atomic_inc(&otheru->addr->refcnt);
+               refcount_inc(&otheru->addr->refcnt);
                newu->addr = otheru->addr;
        }
        if (otheru->path.dentry) {