All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] fs genetic refcounter conversions
@ 2017-03-01 10:42 Elena Reshetova
  2017-03-01 10:42 ` [PATCH 1/5] fs: convert mb_cache_entry.e_refcnt from atomic_t to refcount_t Elena Reshetova
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Elena Reshetova @ 2017-03-01 10:42 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, peterz, gregkh, viro, jlayton, bfields, ebiederm,
	john.hammond, Elena Reshetova

Now when new refcount_t type and API are finally merged
(see include/linux/refcount.h), the following
patches convert various refcounters in the generic fs code from atomic_t
to refcount_t. By doing this we prevent intentional or accidental
underflows or overflows that can led to use-after-free vulnerabilities.

The below patches are fully independent and can be cherry-picked separately.
Since we convert all kernel subsystems in the same fashion, resulting
in about 300 patches, we have to group them for sending at least in some
fashion to be manageable. Please excuse the long cc list.

Run-time tested using xfstests with xfs and ext4 filesystems.
refcount WARNs were on and no issues related to changes were encounted
during running the tests.

Elena Reshetova (5):
  fs: convert mb_cache_entry.e_refcnt from atomic_t to refcount_t
  fs: convert posix_acl.a_refcount from atomic_t to refcount_t
  fs: convert mnt_namespace.count from atomic_t to refcount_t
  fs: convert super_block.s_active from atomic_t to refcount_t
  fs: convert userfaultfd_ctx.refcount from atomic_t to refcount_t

 drivers/staging/lustre/lustre/llite/llite_lib.c |  2 +-
 fs/cifs/cifsfs.c                                |  2 +-
 fs/devpts/inode.c                               |  2 +-
 fs/f2fs/acl.c                                   |  2 +-
 fs/gfs2/super.c                                 |  2 +-
 fs/kernfs/mount.c                               |  2 +-
 fs/mbcache.c                                    | 16 ++++++++--------
 fs/mount.h                                      |  5 +++--
 fs/namespace.c                                  |  8 ++++----
 fs/nfs/super.c                                  |  4 ++--
 fs/posix_acl.c                                  |  6 +++---
 fs/super.c                                      | 10 +++++-----
 fs/userfaultfd.c                                | 11 ++++++-----
 include/linux/fs.h                              |  3 ++-
 include/linux/mbcache.h                         |  6 +++---
 include/linux/posix_acl.h                       |  7 ++++---
 16 files changed, 46 insertions(+), 42 deletions(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/5] fs: convert mb_cache_entry.e_refcnt from atomic_t to refcount_t
  2017-03-01 10:42 [PATCH 0/5] fs genetic refcounter conversions Elena Reshetova
@ 2017-03-01 10:42 ` Elena Reshetova
  2017-03-01 10:42 ` [PATCH 2/5] fs: convert posix_acl.a_refcount " Elena Reshetova
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Elena Reshetova @ 2017-03-01 10:42 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, peterz, gregkh, viro, jlayton, bfields, ebiederm,
	john.hammond, Elena Reshetova, Hans Liljestrand, Kees Cook,
	David Windsor

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>
---
 fs/mbcache.c            | 16 ++++++++--------
 include/linux/mbcache.h |  6 +++---
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/fs/mbcache.c b/fs/mbcache.c
index b19be429d..57a82de 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -89,7 +89,7 @@ int mb_cache_entry_create(struct mb_cache *cache, gfp_t mask, u32 key,
 
 	INIT_LIST_HEAD(&entry->e_list);
 	/* One ref for hash, one ref returned */
-	atomic_set(&entry->e_refcnt, 1);
+	refcount_set(&entry->e_refcnt, 1);
 	entry->e_key = key;
 	entry->e_block = block;
 	entry->e_reusable = reusable;
@@ -108,7 +108,7 @@ int mb_cache_entry_create(struct mb_cache *cache, gfp_t mask, u32 key,
 	spin_lock(&cache->c_list_lock);
 	list_add_tail(&entry->e_list, &cache->c_list);
 	/* Grab ref for LRU list */
-	atomic_inc(&entry->e_refcnt);
+	refcount_inc(&entry->e_refcnt);
 	cache->c_entry_count++;
 	spin_unlock(&cache->c_list_lock);
 
@@ -140,7 +140,7 @@ static struct mb_cache_entry *__entry_find(struct mb_cache *cache,
 		entry = hlist_bl_entry(node, struct mb_cache_entry,
 				       e_hash_list);
 		if (entry->e_key == key && entry->e_reusable) {
-			atomic_inc(&entry->e_refcnt);
+			refcount_inc(&entry->e_refcnt);
 			goto out;
 		}
 		node = node->next;
@@ -203,7 +203,7 @@ struct mb_cache_entry *mb_cache_entry_get(struct mb_cache *cache, u32 key,
 	hlist_bl_lock(head);
 	hlist_bl_for_each_entry(entry, node, head, e_hash_list) {
 		if (entry->e_key == key && entry->e_block == block) {
-			atomic_inc(&entry->e_refcnt);
+			refcount_inc(&entry->e_refcnt);
 			goto out;
 		}
 	}
@@ -239,7 +239,7 @@ void mb_cache_entry_delete_block(struct mb_cache *cache, u32 key,
 			if (!list_empty(&entry->e_list)) {
 				list_del_init(&entry->e_list);
 				cache->c_entry_count--;
-				atomic_dec(&entry->e_refcnt);
+				refcount_dec(&entry->e_refcnt);
 			}
 			spin_unlock(&cache->c_list_lock);
 			mb_cache_entry_put(cache, entry);
@@ -300,7 +300,7 @@ static unsigned long mb_cache_shrink(struct mb_cache *cache,
 		hlist_bl_lock(head);
 		if (!hlist_bl_unhashed(&entry->e_hash_list)) {
 			hlist_bl_del_init(&entry->e_hash_list);
-			atomic_dec(&entry->e_refcnt);
+			refcount_dec(&entry->e_refcnt);
 		}
 		hlist_bl_unlock(head);
 		if (mb_cache_entry_put(cache, entry))
@@ -397,11 +397,11 @@ void mb_cache_destroy(struct mb_cache *cache)
 	list_for_each_entry_safe(entry, next, &cache->c_list, e_list) {
 		if (!hlist_bl_unhashed(&entry->e_hash_list)) {
 			hlist_bl_del_init(&entry->e_hash_list);
-			atomic_dec(&entry->e_refcnt);
+			refcount_dec(&entry->e_refcnt);
 		} else
 			WARN_ON(1);
 		list_del(&entry->e_list);
-		WARN_ON(atomic_read(&entry->e_refcnt) != 1);
+		WARN_ON(refcount_read(&entry->e_refcnt) != 1);
 		mb_cache_entry_put(cache, entry);
 	}
 	kfree(cache->c_hash);
diff --git a/include/linux/mbcache.h b/include/linux/mbcache.h
index 86c9a8b..251e268 100644
--- a/include/linux/mbcache.h
+++ b/include/linux/mbcache.h
@@ -4,7 +4,7 @@
 #include <linux/hash.h>
 #include <linux/list_bl.h>
 #include <linux/list.h>
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/fs.h>
 
 struct mb_cache;
@@ -14,7 +14,7 @@ struct mb_cache_entry {
 	struct list_head	e_list;
 	/* Hash table list - protected by hash chain bitlock */
 	struct hlist_bl_node	e_hash_list;
-	atomic_t		e_refcnt;
+	refcount_t		e_refcnt;
 	/* Key in hash - stable during lifetime of the entry */
 	u32			e_key;
 	u32			e_referenced:1;
@@ -32,7 +32,7 @@ void __mb_cache_entry_free(struct mb_cache_entry *entry);
 static inline int mb_cache_entry_put(struct mb_cache *cache,
 				     struct mb_cache_entry *entry)
 {
-	if (!atomic_dec_and_test(&entry->e_refcnt))
+	if (!refcount_dec_and_test(&entry->e_refcnt))
 		return 0;
 	__mb_cache_entry_free(entry);
 	return 1;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/5] fs: convert posix_acl.a_refcount from atomic_t to refcount_t
  2017-03-01 10:42 [PATCH 0/5] fs genetic refcounter conversions Elena Reshetova
  2017-03-01 10:42 ` [PATCH 1/5] fs: convert mb_cache_entry.e_refcnt from atomic_t to refcount_t Elena Reshetova
@ 2017-03-01 10:42 ` Elena Reshetova
  2017-03-01 10:42 ` [PATCH 3/5] fs: convert mnt_namespace.count " Elena Reshetova
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Elena Reshetova @ 2017-03-01 10:42 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, peterz, gregkh, viro, jlayton, bfields, ebiederm,
	john.hammond, Elena Reshetova, Hans Liljestrand, Kees Cook,
	David Windsor

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>
---
 fs/f2fs/acl.c             | 2 +-
 fs/posix_acl.c            | 6 +++---
 include/linux/posix_acl.h | 7 ++++---
 3 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
index 8f48769..b9fc36d 100644
--- a/fs/f2fs/acl.c
+++ b/fs/f2fs/acl.c
@@ -266,7 +266,7 @@ static struct posix_acl *f2fs_acl_clone(const struct posix_acl *acl,
 				sizeof(struct posix_acl_entry);
 		clone = kmemdup(acl, size, flags);
 		if (clone)
-			atomic_set(&clone->a_refcount, 1);
+			refcount_set(&clone->a_refcount, 1);
 	}
 	return clone;
 }
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index c9d48dc..07161b9 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -42,7 +42,7 @@ struct posix_acl *get_cached_acl(struct inode *inode, int type)
 		rcu_read_lock();
 		acl = rcu_dereference(*p);
 		if (!acl || is_uncached_acl(acl) ||
-		    atomic_inc_not_zero(&acl->a_refcount))
+		    refcount_inc_not_zero(&acl->a_refcount))
 			break;
 		rcu_read_unlock();
 		cpu_relax();
@@ -163,7 +163,7 @@ EXPORT_SYMBOL(get_acl);
 void
 posix_acl_init(struct posix_acl *acl, int count)
 {
-	atomic_set(&acl->a_refcount, 1);
+	refcount_set(&acl->a_refcount, 1);
 	acl->a_count = count;
 }
 EXPORT_SYMBOL(posix_acl_init);
@@ -196,7 +196,7 @@ posix_acl_clone(const struct posix_acl *acl, gfp_t flags)
 		           sizeof(struct posix_acl_entry);
 		clone = kmemdup(acl, size, flags);
 		if (clone)
-			atomic_set(&clone->a_refcount, 1);
+			refcount_set(&clone->a_refcount, 1);
 	}
 	return clone;
 }
diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h
index 5a9a739..e3a4fc9 100644
--- a/include/linux/posix_acl.h
+++ b/include/linux/posix_acl.h
@@ -11,6 +11,7 @@
 #include <linux/bug.h>
 #include <linux/slab.h>
 #include <linux/rcupdate.h>
+#include <linux/refcount.h>
 #include <uapi/linux/posix_acl.h>
 
 struct posix_acl_entry {
@@ -23,7 +24,7 @@ struct posix_acl_entry {
 };
 
 struct posix_acl {
-	atomic_t		a_refcount;
+	refcount_t		a_refcount;
 	struct rcu_head		a_rcu;
 	unsigned int		a_count;
 	struct posix_acl_entry	a_entries[0];
@@ -40,7 +41,7 @@ static inline struct posix_acl *
 posix_acl_dup(struct posix_acl *acl)
 {
 	if (acl)
-		atomic_inc(&acl->a_refcount);
+		refcount_inc(&acl->a_refcount);
 	return acl;
 }
 
@@ -50,7 +51,7 @@ posix_acl_dup(struct posix_acl *acl)
 static inline void
 posix_acl_release(struct posix_acl *acl)
 {
-	if (acl && atomic_dec_and_test(&acl->a_refcount))
+	if (acl && refcount_dec_and_test(&acl->a_refcount))
 		kfree_rcu(acl, a_rcu);
 }
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/5] fs: convert mnt_namespace.count from atomic_t to refcount_t
  2017-03-01 10:42 [PATCH 0/5] fs genetic refcounter conversions Elena Reshetova
  2017-03-01 10:42 ` [PATCH 1/5] fs: convert mb_cache_entry.e_refcnt from atomic_t to refcount_t Elena Reshetova
  2017-03-01 10:42 ` [PATCH 2/5] fs: convert posix_acl.a_refcount " Elena Reshetova
@ 2017-03-01 10:42 ` Elena Reshetova
  2017-03-01 10:42 ` [PATCH 4/5] fs: convert super_block.s_active " Elena Reshetova
  2017-03-01 10:42 ` [PATCH 5/5] fs: convert userfaultfd_ctx.refcount " Elena Reshetova
  4 siblings, 0 replies; 6+ messages in thread
From: Elena Reshetova @ 2017-03-01 10:42 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, peterz, gregkh, viro, jlayton, bfields, ebiederm,
	john.hammond, Elena Reshetova, Hans Liljestrand, Kees Cook,
	David Windsor

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>
---
 fs/mount.h     | 5 +++--
 fs/namespace.c | 4 ++--
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/fs/mount.h b/fs/mount.h
index 2826543..106240d 100644
--- a/fs/mount.h
+++ b/fs/mount.h
@@ -3,9 +3,10 @@
 #include <linux/poll.h>
 #include <linux/ns_common.h>
 #include <linux/fs_pin.h>
+#include <linux/refcount.h>
 
 struct mnt_namespace {
-	atomic_t		count;
+	refcount_t		count;
 	struct ns_common	ns;
 	struct mount *	root;
 	struct list_head	list;
@@ -110,7 +111,7 @@ static inline void detach_mounts(struct dentry *dentry)
 
 static inline void get_mnt_ns(struct mnt_namespace *ns)
 {
-	atomic_inc(&ns->count);
+	refcount_inc(&ns->count);
 }
 
 extern seqlock_t mount_lock;
diff --git a/fs/namespace.c b/fs/namespace.c
index 8bfad42..85cc8ca 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2888,7 +2888,7 @@ static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns)
 	}
 	new_ns->ns.ops = &mntns_operations;
 	new_ns->seq = atomic64_add_return(1, &mnt_ns_seq);
-	atomic_set(&new_ns->count, 1);
+	refcount_set(&new_ns->count, 1);
 	new_ns->root = NULL;
 	INIT_LIST_HEAD(&new_ns->list);
 	init_waitqueue_head(&new_ns->poll);
@@ -3278,7 +3278,7 @@ void __init mnt_init(void)
 
 void put_mnt_ns(struct mnt_namespace *ns)
 {
-	if (!atomic_dec_and_test(&ns->count))
+	if (!refcount_dec_and_test(&ns->count))
 		return;
 	drop_collected_mounts(&ns->root->mnt);
 	free_mnt_ns(ns);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 4/5] fs: convert super_block.s_active from atomic_t to refcount_t
  2017-03-01 10:42 [PATCH 0/5] fs genetic refcounter conversions Elena Reshetova
                   ` (2 preceding siblings ...)
  2017-03-01 10:42 ` [PATCH 3/5] fs: convert mnt_namespace.count " Elena Reshetova
@ 2017-03-01 10:42 ` Elena Reshetova
  2017-03-01 10:42 ` [PATCH 5/5] fs: convert userfaultfd_ctx.refcount " Elena Reshetova
  4 siblings, 0 replies; 6+ messages in thread
From: Elena Reshetova @ 2017-03-01 10:42 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, peterz, gregkh, viro, jlayton, bfields, ebiederm,
	john.hammond, Elena Reshetova, Hans Liljestrand, Kees Cook,
	David Windsor

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>
---
 drivers/staging/lustre/lustre/llite/llite_lib.c |  2 +-
 fs/cifs/cifsfs.c                                |  2 +-
 fs/devpts/inode.c                               |  2 +-
 fs/gfs2/super.c                                 |  2 +-
 fs/kernfs/mount.c                               |  2 +-
 fs/namespace.c                                  |  4 ++--
 fs/nfs/super.c                                  |  4 ++--
 fs/super.c                                      | 10 +++++-----
 include/linux/fs.h                              |  3 ++-
 9 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c
index b229cbc..46d7b2a 100644
--- a/drivers/staging/lustre/lustre/llite/llite_lib.c
+++ b/drivers/staging/lustre/lustre/llite/llite_lib.c
@@ -1995,7 +1995,7 @@ void ll_umount_begin(struct super_block *sb)
 	struct l_wait_info lwi;
 
 	CDEBUG(D_VFSTRACE, "VFS Op: superblock %p count %d active %d\n", sb,
-	       sb->s_count, atomic_read(&sb->s_active));
+	       sb->s_count, refcount_read(&sb->s_active));
 
 	obd = class_exp2obd(sbi->ll_md_exp);
 	if (!obd) {
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 15e1db8..73d29b7 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -101,7 +101,7 @@ cifs_sb_active(struct super_block *sb)
 	struct cifs_sb_info *server = CIFS_SB(sb);
 
 	if (atomic_inc_return(&server->active) == 1)
-		atomic_inc(&sb->s_active);
+		refcount_inc(&sb->s_active);
 }
 
 void
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 108df2e..fba89ab 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -164,7 +164,7 @@ struct pts_fs_info *devpts_acquire(struct file *filp)
 	/*
 	 * pty code needs to hold extra references in case of last /dev/tty close
 	 */
-	atomic_inc(&sb->s_active);
+	refcount_inc(&sb->s_active);
 	result = DEVPTS_SB(sb);
 
 out:
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index e3ee387..49af2ef 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -954,7 +954,7 @@ void gfs2_freeze_func(struct work_struct *work)
 	struct gfs2_sbd *sdp = container_of(work, struct gfs2_sbd, sd_freeze_work);
 	struct super_block *sb = sdp->sd_vfs;
 
-	atomic_inc(&sb->s_active);
+	refcount_inc(&sb->s_active);
 	error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, 0,
 				   &freeze_gh);
 	if (error) {
diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c
index d5b149a..8d61bcf 100644
--- a/fs/kernfs/mount.c
+++ b/fs/kernfs/mount.c
@@ -319,7 +319,7 @@ struct super_block *kernfs_pin_sb(struct kernfs_root *root, const void *ns)
 	list_for_each_entry(info, &root->supers, node) {
 		if (info->ns == ns) {
 			sb = info->sb;
-			if (!atomic_inc_not_zero(&info->sb->s_active))
+			if (!refcount_inc_not_zero(&info->sb->s_active))
 				sb = ERR_PTR(-EINVAL);
 			break;
 		}
diff --git a/fs/namespace.c b/fs/namespace.c
index 85cc8ca..9a6107f 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1051,7 +1051,7 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root,
 	    (!(flag & CL_EXPIRE) || list_empty(&old->mnt_expire)))
 		mnt->mnt.mnt_flags |= MNT_LOCKED;
 
-	atomic_inc(&sb->s_active);
+	refcount_inc(&sb->s_active);
 	mnt->mnt.mnt_sb = sb;
 	mnt->mnt.mnt_root = dget(root);
 	mnt->mnt_mountpoint = mnt->mnt.mnt_root;
@@ -3015,7 +3015,7 @@ struct dentry *mount_subtree(struct vfsmount *mnt, const char *name)
 
 	/* trade a vfsmount reference for active sb one */
 	s = path.mnt->mnt_sb;
-	atomic_inc(&s->s_active);
+	refcount_inc(&s->s_active);
 	mntput(path.mnt);
 	/* lock the sucker */
 	down_write(&s->s_umount);
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 6bca178..58e4b51 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -412,10 +412,10 @@ bool nfs_sb_active(struct super_block *sb)
 {
 	struct nfs_server *server = NFS_SB(sb);
 
-	if (!atomic_inc_not_zero(&sb->s_active))
+	if (!refcount_inc_not_zero(&sb->s_active))
 		return false;
 	if (atomic_inc_return(&server->active) != 1)
-		atomic_dec(&sb->s_active);
+		refcount_dec(&sb->s_active);
 	return true;
 }
 EXPORT_SYMBOL_GPL(nfs_sb_active);
diff --git a/fs/super.c b/fs/super.c
index b8b6a08..7e1511c 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -240,7 +240,7 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags,
 	 */
 	down_write_nested(&s->s_umount, SINGLE_DEPTH_NESTING);
 	s->s_count = 1;
-	atomic_set(&s->s_active, 1);
+	refcount_set(&s->s_active, 1);
 	mutex_init(&s->s_vfs_rename_mutex);
 	lockdep_set_class(&s->s_vfs_rename_mutex, &type->s_vfs_rename_key);
 	mutex_init(&s->s_dquot.dqio_mutex);
@@ -303,7 +303,7 @@ static void put_super(struct super_block *sb)
 void deactivate_locked_super(struct super_block *s)
 {
 	struct file_system_type *fs = s->s_type;
-	if (atomic_dec_and_test(&s->s_active)) {
+	if (refcount_dec_and_test(&s->s_active)) {
 		cleancache_invalidate_fs(s);
 		unregister_shrinker(&s->s_shrink);
 		fs->kill_sb(s);
@@ -335,7 +335,7 @@ EXPORT_SYMBOL(deactivate_locked_super);
  */
 void deactivate_super(struct super_block *s)
 {
-        if (!atomic_add_unless(&s->s_active, -1, 1)) {
+	if (!refcount_dec_not_one(&s->s_active)) {
 		down_write(&s->s_umount);
 		deactivate_locked_super(s);
 	}
@@ -361,7 +361,7 @@ static int grab_super(struct super_block *s) __releases(sb_lock)
 	s->s_count++;
 	spin_unlock(&sb_lock);
 	down_write(&s->s_umount);
-	if ((s->s_flags & MS_BORN) && atomic_inc_not_zero(&s->s_active)) {
+	if ((s->s_flags & MS_BORN) && refcount_inc_not_zero(&s->s_active)) {
 		put_super(s);
 		return 1;
 	}
@@ -1385,7 +1385,7 @@ int freeze_super(struct super_block *sb)
 {
 	int ret;
 
-	atomic_inc(&sb->s_active);
+	refcount_inc(&sb->s_active);
 	down_write(&sb->s_umount);
 	if (sb->s_writers.frozen != SB_UNFROZEN) {
 		deactivate_locked_super(sb);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 79fc59b..6b83a08 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -31,6 +31,7 @@
 #include <linux/workqueue.h>
 #include <linux/percpu-rwsem.h>
 #include <linux/delayed_call.h>
+#include <linux/refcount.h>
 
 #include <asm/byteorder.h>
 #include <uapi/linux/fs.h>
@@ -1308,7 +1309,7 @@ struct super_block {
 	struct dentry		*s_root;
 	struct rw_semaphore	s_umount;
 	int			s_count;
-	atomic_t		s_active;
+	refcount_t		s_active;
 #ifdef CONFIG_SECURITY
 	void                    *s_security;
 #endif
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 5/5] fs: convert userfaultfd_ctx.refcount from atomic_t to refcount_t
  2017-03-01 10:42 [PATCH 0/5] fs genetic refcounter conversions Elena Reshetova
                   ` (3 preceding siblings ...)
  2017-03-01 10:42 ` [PATCH 4/5] fs: convert super_block.s_active " Elena Reshetova
@ 2017-03-01 10:42 ` Elena Reshetova
  4 siblings, 0 replies; 6+ messages in thread
From: Elena Reshetova @ 2017-03-01 10:42 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, peterz, gregkh, viro, jlayton, bfields, ebiederm,
	john.hammond, Elena Reshetova, Hans Liljestrand, Kees Cook,
	David Windsor

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>
---
 fs/userfaultfd.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index 3c421d0..06c334a 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -28,6 +28,7 @@
 #include <linux/ioctl.h>
 #include <linux/security.h>
 #include <linux/hugetlb.h>
+#include <linux/refcount.h>
 
 static struct kmem_cache *userfaultfd_ctx_cachep __read_mostly;
 
@@ -52,7 +53,7 @@ struct userfaultfd_ctx {
 	/* a refile sequence protected by fault_pending_wqh lock */
 	struct seqcount refile_seq;
 	/* pseudo fd refcounting */
-	atomic_t refcount;
+	refcount_t refcount;
 	/* userfaultfd syscall flags */
 	unsigned int flags;
 	/* features requested from the userspace */
@@ -142,7 +143,7 @@ static int userfaultfd_wake_function(wait_queue_t *wq, unsigned mode,
  */
 static void userfaultfd_ctx_get(struct userfaultfd_ctx *ctx)
 {
-	if (!atomic_inc_not_zero(&ctx->refcount))
+	if (!refcount_inc_not_zero(&ctx->refcount))
 		BUG();
 }
 
@@ -156,7 +157,7 @@ static void userfaultfd_ctx_get(struct userfaultfd_ctx *ctx)
  */
 static void userfaultfd_ctx_put(struct userfaultfd_ctx *ctx)
 {
-	if (atomic_dec_and_test(&ctx->refcount)) {
+	if (refcount_dec_and_test(&ctx->refcount)) {
 		VM_BUG_ON(spin_is_locked(&ctx->fault_pending_wqh.lock));
 		VM_BUG_ON(waitqueue_active(&ctx->fault_pending_wqh));
 		VM_BUG_ON(spin_is_locked(&ctx->fault_wqh.lock));
@@ -607,7 +608,7 @@ int dup_userfaultfd(struct vm_area_struct *vma, struct list_head *fcs)
 			return -ENOMEM;
 		}
 
-		atomic_set(&ctx->refcount, 1);
+		refcount_set(&ctx->refcount, 1);
 		ctx->flags = octx->flags;
 		ctx->state = UFFD_STATE_RUNNING;
 		ctx->features = octx->features;
@@ -1840,7 +1841,7 @@ static struct file *userfaultfd_file_create(int flags)
 	if (!ctx)
 		goto out;
 
-	atomic_set(&ctx->refcount, 1);
+	refcount_set(&ctx->refcount, 1);
 	ctx->flags = flags;
 	ctx->features = 0;
 	ctx->state = UFFD_STATE_WAIT_API;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2017-03-01 10:43 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-01 10:42 [PATCH 0/5] fs genetic refcounter conversions Elena Reshetova
2017-03-01 10:42 ` [PATCH 1/5] fs: convert mb_cache_entry.e_refcnt from atomic_t to refcount_t Elena Reshetova
2017-03-01 10:42 ` [PATCH 2/5] fs: convert posix_acl.a_refcount " Elena Reshetova
2017-03-01 10:42 ` [PATCH 3/5] fs: convert mnt_namespace.count " Elena Reshetova
2017-03-01 10:42 ` [PATCH 4/5] fs: convert super_block.s_active " Elena Reshetova
2017-03-01 10:42 ` [PATCH 5/5] fs: convert userfaultfd_ctx.refcount " Elena Reshetova

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.