ceph: convert ceph_cap_snap.nref from atomic_t to refcount_t
authorElena Reshetova <elena.reshetova@intel.com>
Fri, 3 Mar 2017 09:15:07 +0000 (11:15 +0200)
committerIlya Dryomov <idryomov@gmail.com>
Thu, 4 May 2017 07:19:18 +0000 (09:19 +0200)
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: Ilya Dryomov <idryomov@gmail.com>
fs/ceph/caps.c
fs/ceph/snap.c
fs/ceph/super.h

index 68c78be19d5b78ad181d15b6caf5cc075b6f9f99..60185434162afc86e7ea1c8d67f476b1516e1d2c 100644 (file)
@@ -1389,7 +1389,7 @@ static void __ceph_flush_snaps(struct ceph_inode_info *ci,
                first_tid = cf->tid + 1;
 
                capsnap = container_of(cf, struct ceph_cap_snap, cap_flush);
-               atomic_inc(&capsnap->nref);
+               refcount_inc(&capsnap->nref);
                spin_unlock(&ci->i_ceph_lock);
 
                dout("__flush_snaps %p capsnap %p tid %llu %s\n",
@@ -2202,7 +2202,7 @@ static void __kick_flushing_caps(struct ceph_mds_client *mdsc,
                             inode, capsnap, cf->tid,
                             ceph_cap_string(capsnap->dirty));
 
-                       atomic_inc(&capsnap->nref);
+                       refcount_inc(&capsnap->nref);
                        spin_unlock(&ci->i_ceph_lock);
 
                        ret = __send_flush_snap(inode, session, capsnap, cap->mseq,
index 8f8b41c2ef0f7d472afad0e1abcb4801ac11b221..dab5d6732345b218e12f9bf7d6fea1c5dac38d55 100644 (file)
@@ -519,7 +519,7 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci)
             capsnap->need_flush ? "" : "no_flush");
        ihold(inode);
 
-       atomic_set(&capsnap->nref, 1);
+       refcount_set(&capsnap->nref, 1);
        INIT_LIST_HEAD(&capsnap->ci_item);
 
        capsnap->follows = old_snapc->seq;
index fe6b9cfc4013e63c8b6f6ea3b9b3bd1d4eb89364..c68e6a045fb9e780dfb1cf044b316313d1bf75b6 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/writeback.h>
 #include <linux/slab.h>
 #include <linux/posix_acl.h>
+#include <linux/refcount.h>
 
 #include <linux/ceph/libceph.h>
 
@@ -162,7 +163,7 @@ struct ceph_cap_flush {
  * data before flushing the snapped state (tracked here) back to the MDS.
  */
 struct ceph_cap_snap {
-       atomic_t nref;
+       refcount_t nref;
        struct list_head ci_item;
 
        struct ceph_cap_flush cap_flush;
@@ -191,7 +192,7 @@ struct ceph_cap_snap {
 
 static inline void ceph_put_cap_snap(struct ceph_cap_snap *capsnap)
 {
-       if (atomic_dec_and_test(&capsnap->nref)) {
+       if (refcount_dec_and_test(&capsnap->nref)) {
                if (capsnap->xattr_blob)
                        ceph_buffer_put(capsnap->xattr_blob);
                kfree(capsnap);