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 <[email protected]>
Signed-off-by: Hans Liljestrand <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: David Windsor <[email protected]>
---
 fs/afs/internal.h |  6 +++---
 fs/afs/proc.c     |  2 +-
 fs/afs/server.c   | 20 ++++++++++----------
 3 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 50cd1a6..127567c 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -270,7 +270,7 @@ struct afs_vlocation {
  * AFS fileserver record
  */
 struct afs_server {
-       atomic_t                usage;
+       refcount_t              usage;
        time_t                  time_of_death;  /* time at which put reduced 
usage to 0 */
        struct in_addr          addr;           /* server address */
        struct afs_cell         *cell;          /* cell in which server resides 
*/
@@ -612,8 +612,8 @@ extern spinlock_t afs_server_peer_lock;
 
 #define afs_get_server(S)                                      \
 do {                                                           \
-       _debug("GET SERVER %d", atomic_read(&(S)->usage));      \
-       atomic_inc(&(S)->usage);                                \
+       _debug("GET SERVER %d", refcount_read(&(S)->usage));    \
+       refcount_inc(&(S)->usage);                              \
 } while(0)
 
 extern struct afs_server *afs_lookup_server(struct afs_cell *,
diff --git a/fs/afs/proc.c b/fs/afs/proc.c
index dc195ed..57bf6fb 100644
--- a/fs/afs/proc.c
+++ b/fs/afs/proc.c
@@ -647,7 +647,7 @@ static int afs_proc_cell_servers_show(struct seq_file *m, 
void *v)
        /* display one cell per line on subsequent lines */
        sprintf(ipaddr, "%pI4", &server->addr);
        seq_printf(m, "%3d %-15.15s %5d\n",
-                  atomic_read(&server->usage), ipaddr, server->fs_state);
+                  refcount_read(&server->usage), ipaddr, server->fs_state);
 
        return 0;
 }
diff --git a/fs/afs/server.c b/fs/afs/server.c
index d4066ab..958f63b 100644
--- a/fs/afs/server.c
+++ b/fs/afs/server.c
@@ -75,7 +75,7 @@ static struct afs_server *afs_alloc_server(struct afs_cell 
*cell,
 
        server = kzalloc(sizeof(struct afs_server), GFP_KERNEL);
        if (server) {
-               atomic_set(&server->usage, 1);
+               refcount_set(&server->usage, 1);
                server->cell = cell;
 
                INIT_LIST_HEAD(&server->link);
@@ -91,7 +91,7 @@ static struct afs_server *afs_alloc_server(struct afs_cell 
*cell,
 
                memcpy(&server->addr, addr, sizeof(struct in_addr));
                server->addr.s_addr = addr->s_addr;
-               _leave(" = %p{%d}", server, atomic_read(&server->usage));
+               _leave(" = %p{%d}", server, refcount_read(&server->usage));
        } else {
                _leave(" = NULL [nomem]");
        }
@@ -140,7 +140,7 @@ struct afs_server *afs_lookup_server(struct afs_cell *cell,
        list_add_tail(&server->link, &cell->servers);
 
        write_unlock(&cell->servers_lock);
-       _leave(" = %p{%d}", server, atomic_read(&server->usage));
+       _leave(" = %p{%d}", server, refcount_read(&server->usage));
        return server;
 
        /* found a matching server quickly */
@@ -154,7 +154,7 @@ struct afs_server *afs_lookup_server(struct afs_cell *cell,
                list_del_init(&server->grave);
                spin_unlock(&afs_server_graveyard_lock);
        }
-       _leave(" = %p{%d}", server, atomic_read(&server->usage));
+       _leave(" = %p{%d}", server, refcount_read(&server->usage));
        return server;
 
        /* found a matching server on the second pass */
@@ -226,13 +226,13 @@ void afs_put_server(struct afs_server *server)
        if (!server)
                return;
 
-       _enter("%p{%d}", server, atomic_read(&server->usage));
+       _enter("%p{%d}", server, refcount_read(&server->usage));
 
-       _debug("PUT SERVER %d", atomic_read(&server->usage));
+       _debug("PUT SERVER %d", refcount_read(&server->usage));
 
-       ASSERTCMP(atomic_read(&server->usage), >, 0);
+       ASSERTCMP(refcount_read(&server->usage), >, 0);
 
-       if (likely(!atomic_dec_and_test(&server->usage))) {
+       if (likely(!refcount_dec_and_test(&server->usage))) {
                _leave("");
                return;
        }
@@ -240,7 +240,7 @@ void afs_put_server(struct afs_server *server)
        afs_flush_callback_breaks(server);
 
        spin_lock(&afs_server_graveyard_lock);
-       if (atomic_read(&server->usage) == 0) {
+       if (refcount_read(&server->usage) == 0) {
                list_move_tail(&server->grave, &afs_server_graveyard);
                server->time_of_death = get_seconds();
                queue_delayed_work(afs_wq, &afs_server_reaper,
@@ -296,7 +296,7 @@ static void afs_reap_server(struct work_struct *work)
 
                write_lock(&server->cell->servers_lock);
                write_lock(&afs_servers_lock);
-               if (atomic_read(&server->usage) > 0) {
+               if (refcount_read(&server->usage) > 0) {
                        list_del_init(&server->grave);
                } else {
                        list_move_tail(&server->grave, &corpses);
-- 
2.7.4

Reply via email to