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

