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  |  4 ++--
 fs/afs/proc.c      |  2 +-
 fs/afs/vlocation.c | 16 ++++++++--------
 3 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index e77fd4d..50cd1a6 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -246,7 +246,7 @@ struct afs_cache_vhash {
  * AFS volume location record
  */
 struct afs_vlocation {
-       atomic_t                usage;
+       refcount_t              usage;
        time_t                  time_of_death;  /* time at which put reduced 
usage to 0 */
        struct list_head        link;           /* link in cell volume location 
list */
        struct list_head        grave;          /* link in master graveyard 
list */
@@ -641,7 +641,7 @@ extern int afs_vl_get_entry_by_id(struct in_addr *, struct 
key *,
 /*
  * vlocation.c
  */
-#define afs_get_vlocation(V) do { atomic_inc(&(V)->usage); } while(0)
+#define afs_get_vlocation(V) do { refcount_inc(&(V)->usage); } while(0)
 
 extern int __init afs_vlocation_update_init(void);
 extern struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *,
diff --git a/fs/afs/proc.c b/fs/afs/proc.c
index 7eec16d..dc195ed 100644
--- a/fs/afs/proc.c
+++ b/fs/afs/proc.c
@@ -461,7 +461,7 @@ static int afs_proc_cell_volumes_show(struct seq_file *m, 
void *v)
 
        /* display one cell per line on subsequent lines */
        seq_printf(m, "%3d %s %08x %08x %08x %s\n",
-                  atomic_read(&vlocation->usage),
+                  refcount_read(&vlocation->usage),
                   afs_vlocation_states[vlocation->state],
                   vlocation->vldb.vid[0],
                   vlocation->vldb.vid[1],
diff --git a/fs/afs/vlocation.c b/fs/afs/vlocation.c
index d7d8dd8..da27a00 100644
--- a/fs/afs/vlocation.c
+++ b/fs/afs/vlocation.c
@@ -176,7 +176,7 @@ static struct afs_vlocation *afs_vlocation_alloc(struct 
afs_cell *cell,
        if (vl) {
                vl->cell = cell;
                vl->state = AFS_VL_NEW;
-               atomic_set(&vl->usage, 1);
+               refcount_set(&vl->usage, 1);
                INIT_LIST_HEAD(&vl->link);
                INIT_LIST_HEAD(&vl->grave);
                INIT_LIST_HEAD(&vl->update);
@@ -432,7 +432,7 @@ struct afs_vlocation *afs_vlocation_lookup(struct afs_cell 
*cell,
 found_in_memory:
        /* found in memory */
        _debug("found in memory");
-       atomic_inc(&vl->usage);
+       refcount_inc(&vl->usage);
        spin_unlock(&cell->vl_lock);
        if (!list_empty(&vl->grave)) {
                spin_lock(&afs_vlocation_graveyard_lock);
@@ -495,15 +495,15 @@ void afs_put_vlocation(struct afs_vlocation *vl)
 
        _enter("%s", vl->vldb.name);
 
-       ASSERTCMP(atomic_read(&vl->usage), >, 0);
+       ASSERTCMP(refcount_read(&vl->usage), >, 0);
 
-       if (likely(!atomic_dec_and_test(&vl->usage))) {
+       if (likely(!refcount_dec_and_test(&vl->usage))) {
                _leave("");
                return;
        }
 
        spin_lock(&afs_vlocation_graveyard_lock);
-       if (atomic_read(&vl->usage) == 0) {
+       if (refcount_read(&vl->usage) == 0) {
                _debug("buried");
                list_move_tail(&vl->grave, &afs_vlocation_graveyard);
                vl->time_of_death = get_seconds();
@@ -566,7 +566,7 @@ static void afs_vlocation_reaper(struct work_struct *work)
                }
 
                spin_lock(&vl->cell->vl_lock);
-               if (atomic_read(&vl->usage) > 0) {
+               if (refcount_read(&vl->usage) > 0) {
                        _debug("no reap");
                        list_del_init(&vl->grave);
                } else {
@@ -641,7 +641,7 @@ static void afs_vlocation_updater(struct work_struct *work)
 
                vl = list_entry(afs_vlocation_updates.next,
                                struct afs_vlocation, update);
-               if (atomic_read(&vl->usage) > 0)
+               if (refcount_read(&vl->usage) > 0)
                        break;
                list_del_init(&vl->update);
        }
@@ -656,7 +656,7 @@ static void afs_vlocation_updater(struct work_struct *work)
        }
 
        list_del_init(&vl->update);
-       atomic_inc(&vl->usage);
+       refcount_inc(&vl->usage);
        spin_unlock(&afs_vlocation_updates_lock);
 
        /* we can now perform the update */
-- 
2.7.4

Reply via email to