All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/10] various fs subsystems refcounter conversions
@ 2017-03-02 10:43 Elena Reshetova
  2017-03-02 10:43 ` [PATCH 02/10] fs, cachefiles: convert cachefiles_object.usage from atomic_t to refcount_t Elena Reshetova
                   ` (6 more replies)
  0 siblings, 7 replies; 16+ messages in thread
From: Elena Reshetova @ 2017-03-02 10:43 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, linux-nilfs, linux-cachefs, linux-cifs, peterz,
	gregkh, viro, dhowells, sfrench, eparis, konishi.ryusuke, john,
	rlove, paul, 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 different fs susystems 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.

Elena Reshetova (10):
  fs, kernfs: convert kernfs_node.count from atomic_t to refcount_t
  fs, cachefiles: convert cachefiles_object.usage from atomic_t to
    refcount_t
  fs, proc: convert proc_dir_entry.count from atomic_t to refcount_t
  fs, nilfs: convert nilfs_root.count from atomic_t to refcount_t
  fs, hfs: convert hfs_bnode.refcnt from atomic_t to refcount_t
  fs, fscache: convert fscache_cache_tag.usage from atomic_t to
    refcount_t
  fs, fscache: convert fscache_operation.usage from atomic_t to
    refcount_t
  fs, fsnotify: convert fsnotify_group.refcnt from atomic_t to
    refcount_t
  fs, fsnotify: convert fsnotify_mark.refcnt from atomic_t to refcount_t
  fs, cifs: convert tcon_link.tl_count from atomic_t to refcount_t

 fs/cachefiles/bind.c             |  2 +-
 fs/cachefiles/interface.c        | 18 +++++++++---------
 fs/cachefiles/internal.h         |  3 ++-
 fs/cachefiles/namei.c            |  2 +-
 fs/cachefiles/rdwr.c             |  2 +-
 fs/cifs/cifsglob.h               |  5 +++--
 fs/cifs/connect.c                |  8 ++++----
 fs/fscache/cache.c               |  8 ++++----
 fs/fscache/operation.c           | 38 +++++++++++++++++++-------------------
 fs/fscache/page.c                |  2 +-
 fs/hfs/bnode.c                   | 14 +++++++-------
 fs/hfs/btree.c                   |  4 ++--
 fs/hfs/btree.h                   |  3 ++-
 fs/hfs/inode.c                   |  4 ++--
 fs/hfsplus/bnode.c               | 14 +++++++-------
 fs/hfsplus/btree.c               |  4 ++--
 fs/hfsplus/hfsplus_fs.h          |  3 ++-
 fs/hfsplus/inode.c               |  4 ++--
 fs/kernfs/dir.c                  | 12 +++++-------
 fs/nilfs2/the_nilfs.c            |  8 ++++----
 fs/nilfs2/the_nilfs.h            |  5 +++--
 fs/notify/group.c                |  6 +++---
 fs/notify/inotify/inotify_user.c |  4 ++--
 fs/notify/mark.c                 |  6 +++---
 fs/proc/generic.c                |  4 ++--
 fs/proc/internal.h               |  5 +++--
 fs/proc/root.c                   |  2 +-
 include/linux/fscache-cache.h    |  7 ++++---
 include/linux/fsnotify_backend.h |  5 +++--
 include/linux/kernfs.h           |  3 ++-
 kernel/audit_tree.c              |  2 +-
 31 files changed, 107 insertions(+), 100 deletions(-)

-- 
2.7.4

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

* [PATCH 01/10] fs, kernfs: convert kernfs_node.count from atomic_t to refcount_t
  2017-03-02 10:43 [PATCH 00/10] various fs subsystems refcounter conversions Elena Reshetova
@ 2017-03-02 10:43     ` Elena Reshetova
  2017-03-02 10:43 ` [PATCH 03/10] fs, proc: convert proc_dir_entry.count " Elena Reshetova
                       ` (5 subsequent siblings)
  6 siblings, 0 replies; 16+ messages in thread
From: Elena Reshetova @ 2017-03-02 10:43 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-nilfs-u79uwXL29TY76Z2rM5mHXA,
	linux-cachefs-H+wXaHxf7aLQT0dZR+AlfA,
	linux-cifs-u79uwXL29TY76Z2rM5mHXA, peterz-wEGCiKHe2LqWVfeAwA7xHQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
	dhowells-H+wXaHxf7aLQT0dZR+AlfA, sfrench-eUNUBHrolfbYtjvyW6yDsg,
	eparis-FjpueFixGhCM4zKIHC2jIg,
	konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg,
	john-jueV0HHMeujJJrXXpGQQMAC/G2K4zDHf,
	rlove-L7G0xEPcOZbYtjvyW6yDsg, paul-r2n+y4ga6xFZroRs9YW3xA,
	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-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Hans Liljestrand <ishkamiel-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Kees Cook <keescook-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
Signed-off-by: David Windsor <dwindsor-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 fs/kernfs/dir.c        | 12 +++++-------
 include/linux/kernfs.h |  3 ++-
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index db5900aaa..2a07de1 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -489,10 +489,8 @@ static void kernfs_drain(struct kernfs_node *kn)
  */
 void kernfs_get(struct kernfs_node *kn)
 {
-	if (kn) {
-		WARN_ON(!atomic_read(&kn->count));
-		atomic_inc(&kn->count);
-	}
+	if (kn)
+		refcount_inc(&kn->count);
 }
 EXPORT_SYMBOL_GPL(kernfs_get);
 
@@ -507,7 +505,7 @@ void kernfs_put(struct kernfs_node *kn)
 	struct kernfs_node *parent;
 	struct kernfs_root *root;
 
-	if (!kn || !atomic_dec_and_test(&kn->count))
+	if (!kn || !refcount_dec_and_test(&kn->count))
 		return;
 	root = kernfs_root(kn);
  repeat:
@@ -538,7 +536,7 @@ void kernfs_put(struct kernfs_node *kn)
 
 	kn = parent;
 	if (kn) {
-		if (atomic_dec_and_test(&kn->count))
+		if (refcount_dec_and_test(&kn->count))
 			goto repeat;
 	} else {
 		/* just released the root kn, free @root too */
@@ -635,7 +633,7 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root,
 		goto err_out2;
 	kn->ino = ret;
 
-	atomic_set(&kn->count, 1);
+	refcount_set(&kn->count, 1);
 	atomic_set(&kn->active, KN_DEACTIVATED_BIAS);
 	RB_CLEAR_NODE(&kn->rb);
 
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
index a9b11b8..baabbaf 100644
--- a/include/linux/kernfs.h
+++ b/include/linux/kernfs.h
@@ -15,6 +15,7 @@
 #include <linux/lockdep.h>
 #include <linux/rbtree.h>
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/wait.h>
 
 struct file;
@@ -105,7 +106,7 @@ struct kernfs_elem_attr {
  * active reference.
  */
 struct kernfs_node {
-	atomic_t		count;
+	refcount_t		count;
 	atomic_t		active;
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 	struct lockdep_map	dep_map;
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 01/10] fs, kernfs: convert kernfs_node.count from atomic_t to refcount_t
@ 2017-03-02 10:43     ` Elena Reshetova
  0 siblings, 0 replies; 16+ messages in thread
From: Elena Reshetova @ 2017-03-02 10:43 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, linux-nilfs, linux-cachefs, linux-cifs, peterz,
	gregkh, viro, dhowells, sfrench, eparis, konishi.ryusuke, john,
	rlove, paul, 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/kernfs/dir.c        | 12 +++++-------
 include/linux/kernfs.h |  3 ++-
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index db5900aaa..2a07de1 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -489,10 +489,8 @@ static void kernfs_drain(struct kernfs_node *kn)
  */
 void kernfs_get(struct kernfs_node *kn)
 {
-	if (kn) {
-		WARN_ON(!atomic_read(&kn->count));
-		atomic_inc(&kn->count);
-	}
+	if (kn)
+		refcount_inc(&kn->count);
 }
 EXPORT_SYMBOL_GPL(kernfs_get);
 
@@ -507,7 +505,7 @@ void kernfs_put(struct kernfs_node *kn)
 	struct kernfs_node *parent;
 	struct kernfs_root *root;
 
-	if (!kn || !atomic_dec_and_test(&kn->count))
+	if (!kn || !refcount_dec_and_test(&kn->count))
 		return;
 	root = kernfs_root(kn);
  repeat:
@@ -538,7 +536,7 @@ void kernfs_put(struct kernfs_node *kn)
 
 	kn = parent;
 	if (kn) {
-		if (atomic_dec_and_test(&kn->count))
+		if (refcount_dec_and_test(&kn->count))
 			goto repeat;
 	} else {
 		/* just released the root kn, free @root too */
@@ -635,7 +633,7 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root,
 		goto err_out2;
 	kn->ino = ret;
 
-	atomic_set(&kn->count, 1);
+	refcount_set(&kn->count, 1);
 	atomic_set(&kn->active, KN_DEACTIVATED_BIAS);
 	RB_CLEAR_NODE(&kn->rb);
 
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
index a9b11b8..baabbaf 100644
--- a/include/linux/kernfs.h
+++ b/include/linux/kernfs.h
@@ -15,6 +15,7 @@
 #include <linux/lockdep.h>
 #include <linux/rbtree.h>
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/wait.h>
 
 struct file;
@@ -105,7 +106,7 @@ struct kernfs_elem_attr {
  * active reference.
  */
 struct kernfs_node {
-	atomic_t		count;
+	refcount_t		count;
 	atomic_t		active;
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 	struct lockdep_map	dep_map;
-- 
2.7.4

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

* [PATCH 02/10] fs, cachefiles: convert cachefiles_object.usage from atomic_t to refcount_t
  2017-03-02 10:43 [PATCH 00/10] various fs subsystems refcounter conversions Elena Reshetova
@ 2017-03-02 10:43 ` Elena Reshetova
  2017-03-02 10:43 ` [PATCH 03/10] fs, proc: convert proc_dir_entry.count " Elena Reshetova
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 16+ messages in thread
From: Elena Reshetova @ 2017-03-02 10:43 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, linux-nilfs, linux-cachefs, linux-cifs, peterz,
	gregkh, viro, dhowells, sfrench, eparis, konishi.ryusuke, john,
	rlove, paul, 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/cachefiles/bind.c      |  2 +-
 fs/cachefiles/interface.c | 18 +++++++++---------
 fs/cachefiles/internal.h  |  3 ++-
 fs/cachefiles/namei.c     |  2 +-
 4 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/fs/cachefiles/bind.c b/fs/cachefiles/bind.c
index 3ff867f..341864e 100644
--- a/fs/cachefiles/bind.c
+++ b/fs/cachefiles/bind.c
@@ -109,7 +109,7 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
 
 	ASSERTCMP(fsdef->backer, ==, NULL);
 
-	atomic_set(&fsdef->usage, 1);
+	refcount_set(&fsdef->usage, 1);
 	fsdef->type = FSCACHE_COOKIE_TYPE_INDEX;
 
 	_debug("- fsdef %p", fsdef);
diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c
index e7f16a7..d3f87c3 100644
--- a/fs/cachefiles/interface.c
+++ b/fs/cachefiles/interface.c
@@ -51,7 +51,7 @@ static struct fscache_object *cachefiles_alloc_object(
 	ASSERTCMP(object->backer, ==, NULL);
 
 	BUG_ON(test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags));
-	atomic_set(&object->usage, 1);
+	refcount_set(&object->usage, 1);
 
 	fscache_object_init(&object->fscache, cookie, &cache->cache);
 
@@ -182,13 +182,13 @@ struct fscache_object *cachefiles_grab_object(struct fscache_object *_object)
 	struct cachefiles_object *object =
 		container_of(_object, struct cachefiles_object, fscache);
 
-	_enter("{OBJ%x,%d}", _object->debug_id, atomic_read(&object->usage));
+	_enter("{OBJ%x,%d}", _object->debug_id, refcount_read(&object->usage));
 
 #ifdef CACHEFILES_DEBUG_SLAB
-	ASSERT((atomic_read(&object->usage) & 0xffff0000) != 0x6b6b0000);
+	ASSERT((refcount_read(&object->usage) & 0xffff0000) != 0x6b6b0000);
 #endif
 
-	atomic_inc(&object->usage);
+	refcount_inc(&object->usage);
 	return &object->fscache;
 }
 
@@ -261,13 +261,13 @@ static void cachefiles_drop_object(struct fscache_object *_object)
 	object = container_of(_object, struct cachefiles_object, fscache);
 
 	_enter("{OBJ%x,%d}",
-	       object->fscache.debug_id, atomic_read(&object->usage));
+	       object->fscache.debug_id, refcount_read(&object->usage));
 
 	cache = container_of(object->fscache.cache,
 			     struct cachefiles_cache, cache);
 
 #ifdef CACHEFILES_DEBUG_SLAB
-	ASSERT((atomic_read(&object->usage) & 0xffff0000) != 0x6b6b0000);
+	ASSERT((refcount_read(&object->usage) & 0xffff0000) != 0x6b6b0000);
 #endif
 
 	/* We need to tidy the object up if we did in fact manage to open it.
@@ -319,16 +319,16 @@ static void cachefiles_put_object(struct fscache_object *_object)
 	object = container_of(_object, struct cachefiles_object, fscache);
 
 	_enter("{OBJ%x,%d}",
-	       object->fscache.debug_id, atomic_read(&object->usage));
+	       object->fscache.debug_id, refcount_read(&object->usage));
 
 #ifdef CACHEFILES_DEBUG_SLAB
-	ASSERT((atomic_read(&object->usage) & 0xffff0000) != 0x6b6b0000);
+	ASSERT((refcount_read(&object->usage) & 0xffff0000) != 0x6b6b0000);
 #endif
 
 	ASSERTIFCMP(object->fscache.parent,
 		    object->fscache.parent->n_children, >, 0);
 
-	if (atomic_dec_and_test(&object->usage)) {
+	if (refcount_dec_and_test(&object->usage)) {
 		_debug("- kill object OBJ%x", object->fscache.debug_id);
 
 		ASSERT(!test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags));
diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h
index cd1effe..61771e6 100644
--- a/fs/cachefiles/internal.h
+++ b/fs/cachefiles/internal.h
@@ -21,6 +21,7 @@
 #include <linux/wait.h>
 #include <linux/workqueue.h>
 #include <linux/security.h>
+#include <linux/refcount.h>
 
 struct cachefiles_cache;
 struct cachefiles_object;
@@ -43,7 +44,7 @@ struct cachefiles_object {
 	loff_t				i_size;		/* object size */
 	unsigned long			flags;
 #define CACHEFILES_OBJECT_ACTIVE	0		/* T if marked active */
-	atomic_t			usage;		/* object usage count */
+	refcount_t			usage;		/* object usage count */
 	uint8_t				type;		/* object type */
 	uint8_t				new;		/* T if object new */
 	spinlock_t			work_lock;
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c
index 41df8a2..e3bc512 100644
--- a/fs/cachefiles/namei.c
+++ b/fs/cachefiles/namei.c
@@ -197,7 +197,7 @@ static int cachefiles_mark_object_active(struct cachefiles_cache *cache,
 		cachefiles_printk_object(object, xobject);
 		BUG();
 	}
-	atomic_inc(&xobject->usage);
+	refcount_inc(&xobject->usage);
 	write_unlock(&cache->active_lock);
 
 	if (test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags)) {
-- 
2.7.4

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

* [PATCH 03/10] fs, proc: convert proc_dir_entry.count from atomic_t to refcount_t
  2017-03-02 10:43 [PATCH 00/10] various fs subsystems refcounter conversions Elena Reshetova
  2017-03-02 10:43 ` [PATCH 02/10] fs, cachefiles: convert cachefiles_object.usage from atomic_t to refcount_t Elena Reshetova
@ 2017-03-02 10:43 ` Elena Reshetova
  2017-03-02 10:43 ` [PATCH 04/10] fs, nilfs: convert nilfs_root.count " Elena Reshetova
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 16+ messages in thread
From: Elena Reshetova @ 2017-03-02 10:43 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, linux-nilfs, linux-cachefs, linux-cifs, peterz,
	gregkh, viro, dhowells, sfrench, eparis, konishi.ryusuke, john,
	rlove, paul, 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/proc/generic.c  | 4 ++--
 fs/proc/internal.h | 5 +++--
 fs/proc/root.c     | 2 +-
 3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index ee27feb..0850766 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -388,7 +388,7 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
 	ent->mode = mode;
 	ent->nlink = nlink;
 	ent->subdir = RB_ROOT;
-	atomic_set(&ent->count, 1);
+	refcount_set(&ent->count, 1);
 	spin_lock_init(&ent->pde_unload_lock);
 	INIT_LIST_HEAD(&ent->pde_openers);
 	proc_set_user(ent, (*parent)->uid, (*parent)->gid);
@@ -540,7 +540,7 @@ static void free_proc_entry(struct proc_dir_entry *de)
 
 void pde_put(struct proc_dir_entry *pde)
 {
-	if (atomic_dec_and_test(&pde->count))
+	if (refcount_dec_and_test(&pde->count))
 		free_proc_entry(pde);
 }
 
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index e93cdc6..7b5fa12 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -13,6 +13,7 @@
 #include <linux/proc_ns.h>
 #include <linux/spinlock.h>
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/binfmts.h>
 
 struct ctl_table_header;
@@ -41,7 +42,7 @@ struct proc_dir_entry {
 	struct rb_root subdir;
 	struct rb_node subdir_node;
 	void *data;
-	atomic_t count;		/* use count */
+	refcount_t count;	/* use count */
 	atomic_t in_use;	/* number of callers into module in progress; */
 			/* negative -> it's going away RSN */
 	struct completion *pde_unload_completion;
@@ -175,7 +176,7 @@ extern int proc_readdir_de(struct proc_dir_entry *, struct file *, struct dir_co
 
 static inline struct proc_dir_entry *pde_get(struct proc_dir_entry *pde)
 {
-	atomic_inc(&pde->count);
+	refcount_inc(&pde->count);
 	return pde;
 }
 extern void pde_put(struct proc_dir_entry *);
diff --git a/fs/proc/root.c b/fs/proc/root.c
index fb1955c..882bcb5 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -204,7 +204,7 @@ struct proc_dir_entry proc_root = {
 	.namelen	= 5, 
 	.mode		= S_IFDIR | S_IRUGO | S_IXUGO, 
 	.nlink		= 2, 
-	.count		= ATOMIC_INIT(1),
+	.count		= REFCOUNT_INIT(1),
 	.proc_iops	= &proc_root_inode_operations, 
 	.proc_fops	= &proc_root_operations,
 	.parent		= &proc_root,
-- 
2.7.4

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

* [PATCH 04/10] fs, nilfs: convert nilfs_root.count from atomic_t to refcount_t
  2017-03-02 10:43 [PATCH 00/10] various fs subsystems refcounter conversions Elena Reshetova
  2017-03-02 10:43 ` [PATCH 02/10] fs, cachefiles: convert cachefiles_object.usage from atomic_t to refcount_t Elena Reshetova
  2017-03-02 10:43 ` [PATCH 03/10] fs, proc: convert proc_dir_entry.count " Elena Reshetova
@ 2017-03-02 10:43 ` Elena Reshetova
       [not found] ` <1488451397-3365-1-git-send-email-elena.reshetova-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 16+ messages in thread
From: Elena Reshetova @ 2017-03-02 10:43 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, linux-nilfs, linux-cachefs, linux-cifs, peterz,
	gregkh, viro, dhowells, sfrench, eparis, konishi.ryusuke, john,
	rlove, paul, 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/nilfs2/the_nilfs.c | 8 ++++----
 fs/nilfs2/the_nilfs.h | 5 +++--
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index 2dd75bf..afebb50 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -737,7 +737,7 @@ struct nilfs_root *nilfs_lookup_root(struct the_nilfs *nilfs, __u64 cno)
 		} else if (cno > root->cno) {
 			n = n->rb_right;
 		} else {
-			atomic_inc(&root->count);
+			refcount_inc(&root->count);
 			spin_unlock(&nilfs->ns_cptree_lock);
 			return root;
 		}
@@ -776,7 +776,7 @@ nilfs_find_or_create_root(struct the_nilfs *nilfs, __u64 cno)
 		} else if (cno > root->cno) {
 			p = &(*p)->rb_right;
 		} else {
-			atomic_inc(&root->count);
+			refcount_inc(&root->count);
 			spin_unlock(&nilfs->ns_cptree_lock);
 			kfree(new);
 			return root;
@@ -786,7 +786,7 @@ nilfs_find_or_create_root(struct the_nilfs *nilfs, __u64 cno)
 	new->cno = cno;
 	new->ifile = NULL;
 	new->nilfs = nilfs;
-	atomic_set(&new->count, 1);
+	refcount_set(&new->count, 1);
 	atomic64_set(&new->inodes_count, 0);
 	atomic64_set(&new->blocks_count, 0);
 
@@ -806,7 +806,7 @@ nilfs_find_or_create_root(struct the_nilfs *nilfs, __u64 cno)
 
 void nilfs_put_root(struct nilfs_root *root)
 {
-	if (atomic_dec_and_test(&root->count)) {
+	if (refcount_dec_and_test(&root->count)) {
 		struct the_nilfs *nilfs = root->nilfs;
 
 		nilfs_sysfs_delete_snapshot_group(root);
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h
index b305c6f..883d732 100644
--- a/fs/nilfs2/the_nilfs.h
+++ b/fs/nilfs2/the_nilfs.h
@@ -27,6 +27,7 @@
 #include <linux/blkdev.h>
 #include <linux/backing-dev.h>
 #include <linux/slab.h>
+#include <linux/refcount.h>
 
 struct nilfs_sc_info;
 struct nilfs_sysfs_dev_subgroups;
@@ -246,7 +247,7 @@ struct nilfs_root {
 	__u64 cno;
 	struct rb_node rb_node;
 
-	atomic_t count;
+	refcount_t count;
 	struct the_nilfs *nilfs;
 	struct inode *ifile;
 
@@ -299,7 +300,7 @@ void nilfs_swap_super_block(struct the_nilfs *);
 
 static inline void nilfs_get_root(struct nilfs_root *root)
 {
-	atomic_inc(&root->count);
+	refcount_inc(&root->count);
 }
 
 static inline int nilfs_valid_fs(struct the_nilfs *nilfs)
-- 
2.7.4

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

* [PATCH 05/10] fs, hfs: convert hfs_bnode.refcnt from atomic_t to refcount_t
  2017-03-02 10:43 [PATCH 00/10] various fs subsystems refcounter conversions Elena Reshetova
@ 2017-03-02 10:43     ` Elena Reshetova
  2017-03-02 10:43 ` [PATCH 03/10] fs, proc: convert proc_dir_entry.count " Elena Reshetova
                       ` (5 subsequent siblings)
  6 siblings, 0 replies; 16+ messages in thread
From: Elena Reshetova @ 2017-03-02 10:43 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-nilfs-u79uwXL29TY76Z2rM5mHXA,
	linux-cachefs-H+wXaHxf7aLQT0dZR+AlfA,
	linux-cifs-u79uwXL29TY76Z2rM5mHXA, peterz-wEGCiKHe2LqWVfeAwA7xHQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
	dhowells-H+wXaHxf7aLQT0dZR+AlfA, sfrench-eUNUBHrolfbYtjvyW6yDsg,
	eparis-FjpueFixGhCM4zKIHC2jIg,
	konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg,
	john-jueV0HHMeujJJrXXpGQQMAC/G2K4zDHf,
	rlove-L7G0xEPcOZbYtjvyW6yDsg, paul-r2n+y4ga6xFZroRs9YW3xA,
	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-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Hans Liljestrand <ishkamiel-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Kees Cook <keescook-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
Signed-off-by: David Windsor <dwindsor-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 fs/hfs/bnode.c          | 14 +++++++-------
 fs/hfs/btree.c          |  4 ++--
 fs/hfs/btree.h          |  3 ++-
 fs/hfs/inode.c          |  4 ++--
 fs/hfsplus/bnode.c      | 14 +++++++-------
 fs/hfsplus/btree.c      |  4 ++--
 fs/hfsplus/hfsplus_fs.h |  3 ++-
 fs/hfsplus/inode.c      |  4 ++--
 8 files changed, 26 insertions(+), 24 deletions(-)

diff --git a/fs/hfs/bnode.c b/fs/hfs/bnode.c
index d77d844..7b822e4 100644
--- a/fs/hfs/bnode.c
+++ b/fs/hfs/bnode.c
@@ -257,7 +257,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
 	node->tree = tree;
 	node->this = cnid;
 	set_bit(HFS_BNODE_NEW, &node->flags);
-	atomic_set(&node->refcnt, 1);
+	refcount_set(&node->refcnt, 1);
 	hfs_dbg(BNODE_REFS, "new_node(%d:%d): 1\n",
 		node->tree->cnid, node->this);
 	init_waitqueue_head(&node->lock_wq);
@@ -302,7 +302,7 @@ void hfs_bnode_unhash(struct hfs_bnode *node)
 	struct hfs_bnode **p;
 
 	hfs_dbg(BNODE_REFS, "remove_node(%d:%d): %d\n",
-		node->tree->cnid, node->this, atomic_read(&node->refcnt));
+		node->tree->cnid, node->this, refcount_read(&node->refcnt));
 	for (p = &node->tree->node_hash[hfs_bnode_hash(node->this)];
 	     *p && *p != node; p = &(*p)->next_hash)
 		;
@@ -446,10 +446,10 @@ struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num)
 void hfs_bnode_get(struct hfs_bnode *node)
 {
 	if (node) {
-		atomic_inc(&node->refcnt);
+		refcount_inc(&node->refcnt);
 		hfs_dbg(BNODE_REFS, "get_node(%d:%d): %d\n",
 			node->tree->cnid, node->this,
-			atomic_read(&node->refcnt));
+			refcount_read(&node->refcnt));
 	}
 }
 
@@ -462,9 +462,9 @@ void hfs_bnode_put(struct hfs_bnode *node)
 
 		hfs_dbg(BNODE_REFS, "put_node(%d:%d): %d\n",
 			node->tree->cnid, node->this,
-			atomic_read(&node->refcnt));
-		BUG_ON(!atomic_read(&node->refcnt));
-		if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock))
+			refcount_read(&node->refcnt));
+		BUG_ON(!refcount_read(&node->refcnt));
+		if (!refcount_dec_and_lock(&node->refcnt, &tree->hash_lock))
 			return;
 		for (i = 0; i < tree->pages_per_bnode; i++) {
 			if (!node->page[i])
diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c
index 37cdd95..5758e5e 100644
--- a/fs/hfs/btree.c
+++ b/fs/hfs/btree.c
@@ -144,10 +144,10 @@ void hfs_btree_close(struct hfs_btree *tree)
 	for (i = 0; i < NODE_HASH_SIZE; i++) {
 		while ((node = tree->node_hash[i])) {
 			tree->node_hash[i] = node->next_hash;
-			if (atomic_read(&node->refcnt))
+			if (refcount_read(&node->refcnt))
 				pr_err("node %d:%d still has %d user(s)!\n",
 				       node->tree->cnid, node->this,
-				       atomic_read(&node->refcnt));
+				       refcount_read(&node->refcnt));
 			hfs_bnode_free(node);
 			tree->node_hash_cnt--;
 		}
diff --git a/fs/hfs/btree.h b/fs/hfs/btree.h
index f6bd266..99b5fd3 100644
--- a/fs/hfs/btree.h
+++ b/fs/hfs/btree.h
@@ -6,6 +6,7 @@
  * (C) 2003 Ardis Technologies <roman-2GSx/RAVpKG1Z/+hSey0Gg@public.gmane.org>
  */
 
+#include <linux/refcount.h>
 #include "hfs_fs.h"
 
 typedef int (*btree_keycmp)(const btree_key *, const btree_key *);
@@ -57,7 +58,7 @@ struct hfs_bnode {
 	struct hfs_bnode *next_hash;
 	unsigned long flags;
 	wait_queue_head_t lock_wq;
-	atomic_t refcnt;
+	refcount_t refcnt;
 	unsigned int page_offset;
 	struct page *page[0];
 };
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index f776acf..8ac61e4 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -98,7 +98,7 @@ static int hfs_releasepage(struct page *page, gfp_t mask)
 		node = hfs_bnode_findhash(tree, nidx);
 		if (!node)
 			;
-		else if (atomic_read(&node->refcnt))
+		else if (refcount_read(&node->refcnt))
 			res = 0;
 		if (res && node) {
 			hfs_bnode_unhash(node);
@@ -113,7 +113,7 @@ static int hfs_releasepage(struct page *page, gfp_t mask)
 			node = hfs_bnode_findhash(tree, nidx++);
 			if (!node)
 				continue;
-			if (atomic_read(&node->refcnt)) {
+			if (refcount_read(&node->refcnt)) {
 				res = 0;
 				break;
 			}
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
index ce014ce..9abaf14 100644
--- a/fs/hfsplus/bnode.c
+++ b/fs/hfsplus/bnode.c
@@ -422,7 +422,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
 	node->tree = tree;
 	node->this = cnid;
 	set_bit(HFS_BNODE_NEW, &node->flags);
-	atomic_set(&node->refcnt, 1);
+	refcount_set(&node->refcnt, 1);
 	hfs_dbg(BNODE_REFS, "new_node(%d:%d): 1\n",
 		node->tree->cnid, node->this);
 	init_waitqueue_head(&node->lock_wq);
@@ -468,7 +468,7 @@ void hfs_bnode_unhash(struct hfs_bnode *node)
 	struct hfs_bnode **p;
 
 	hfs_dbg(BNODE_REFS, "remove_node(%d:%d): %d\n",
-		node->tree->cnid, node->this, atomic_read(&node->refcnt));
+		node->tree->cnid, node->this, refcount_read(&node->refcnt));
 	for (p = &node->tree->node_hash[hfs_bnode_hash(node->this)];
 	     *p && *p != node; p = &(*p)->next_hash)
 		;
@@ -614,10 +614,10 @@ struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num)
 void hfs_bnode_get(struct hfs_bnode *node)
 {
 	if (node) {
-		atomic_inc(&node->refcnt);
+		refcount_inc(&node->refcnt);
 		hfs_dbg(BNODE_REFS, "get_node(%d:%d): %d\n",
 			node->tree->cnid, node->this,
-			atomic_read(&node->refcnt));
+			refcount_read(&node->refcnt));
 	}
 }
 
@@ -630,9 +630,9 @@ void hfs_bnode_put(struct hfs_bnode *node)
 
 		hfs_dbg(BNODE_REFS, "put_node(%d:%d): %d\n",
 			node->tree->cnid, node->this,
-			atomic_read(&node->refcnt));
-		BUG_ON(!atomic_read(&node->refcnt));
-		if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock))
+			refcount_read(&node->refcnt));
+		BUG_ON(!refcount_read(&node->refcnt));
+		if (!refcount_dec_and_lock(&node->refcnt, &tree->hash_lock))
 			return;
 		for (i = 0; i < tree->pages_per_bnode; i++) {
 			if (!node->page[i])
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
index d9d1a36..0823dca 100644
--- a/fs/hfsplus/btree.c
+++ b/fs/hfsplus/btree.c
@@ -265,11 +265,11 @@ void hfs_btree_close(struct hfs_btree *tree)
 	for (i = 0; i < NODE_HASH_SIZE; i++) {
 		while ((node = tree->node_hash[i])) {
 			tree->node_hash[i] = node->next_hash;
-			if (atomic_read(&node->refcnt))
+			if (refcount_read(&node->refcnt))
 				pr_crit("node %d:%d "
 						"still has %d user(s)!\n",
 					node->tree->cnid, node->this,
-					atomic_read(&node->refcnt));
+					refcount_read(&node->refcnt));
 			hfs_bnode_free(node);
 			tree->node_hash_cnt--;
 		}
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index a3f03b2..a895715 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -20,6 +20,7 @@
 #include <linux/mutex.h>
 #include <linux/buffer_head.h>
 #include <linux/blkdev.h>
+#include <linux/refcount.h>
 #include "hfsplus_raw.h"
 
 #define DBG_BNODE_REFS	0x00000001
@@ -115,7 +116,7 @@ struct hfs_bnode {
 	struct hfs_bnode *next_hash;
 	unsigned long flags;
 	wait_queue_head_t lock_wq;
-	atomic_t refcnt;
+	refcount_t refcnt;
 	unsigned int page_offset;
 	struct page *page[0];
 };
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 2e796f8..d1fbb4d 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -94,7 +94,7 @@ static int hfsplus_releasepage(struct page *page, gfp_t mask)
 		node = hfs_bnode_findhash(tree, nidx);
 		if (!node)
 			;
-		else if (atomic_read(&node->refcnt))
+		else if (refcount_read(&node->refcnt))
 			res = 0;
 		if (res && node) {
 			hfs_bnode_unhash(node);
@@ -110,7 +110,7 @@ static int hfsplus_releasepage(struct page *page, gfp_t mask)
 			node = hfs_bnode_findhash(tree, nidx++);
 			if (!node)
 				continue;
-			if (atomic_read(&node->refcnt)) {
+			if (refcount_read(&node->refcnt)) {
 				res = 0;
 				break;
 			}
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 05/10] fs, hfs: convert hfs_bnode.refcnt from atomic_t to refcount_t
@ 2017-03-02 10:43     ` Elena Reshetova
  0 siblings, 0 replies; 16+ messages in thread
From: Elena Reshetova @ 2017-03-02 10:43 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, linux-nilfs, linux-cachefs, linux-cifs, peterz,
	gregkh, viro, dhowells, sfrench, eparis, konishi.ryusuke, john,
	rlove, paul, 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/hfs/bnode.c          | 14 +++++++-------
 fs/hfs/btree.c          |  4 ++--
 fs/hfs/btree.h          |  3 ++-
 fs/hfs/inode.c          |  4 ++--
 fs/hfsplus/bnode.c      | 14 +++++++-------
 fs/hfsplus/btree.c      |  4 ++--
 fs/hfsplus/hfsplus_fs.h |  3 ++-
 fs/hfsplus/inode.c      |  4 ++--
 8 files changed, 26 insertions(+), 24 deletions(-)

diff --git a/fs/hfs/bnode.c b/fs/hfs/bnode.c
index d77d844..7b822e4 100644
--- a/fs/hfs/bnode.c
+++ b/fs/hfs/bnode.c
@@ -257,7 +257,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
 	node->tree = tree;
 	node->this = cnid;
 	set_bit(HFS_BNODE_NEW, &node->flags);
-	atomic_set(&node->refcnt, 1);
+	refcount_set(&node->refcnt, 1);
 	hfs_dbg(BNODE_REFS, "new_node(%d:%d): 1\n",
 		node->tree->cnid, node->this);
 	init_waitqueue_head(&node->lock_wq);
@@ -302,7 +302,7 @@ void hfs_bnode_unhash(struct hfs_bnode *node)
 	struct hfs_bnode **p;
 
 	hfs_dbg(BNODE_REFS, "remove_node(%d:%d): %d\n",
-		node->tree->cnid, node->this, atomic_read(&node->refcnt));
+		node->tree->cnid, node->this, refcount_read(&node->refcnt));
 	for (p = &node->tree->node_hash[hfs_bnode_hash(node->this)];
 	     *p && *p != node; p = &(*p)->next_hash)
 		;
@@ -446,10 +446,10 @@ struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num)
 void hfs_bnode_get(struct hfs_bnode *node)
 {
 	if (node) {
-		atomic_inc(&node->refcnt);
+		refcount_inc(&node->refcnt);
 		hfs_dbg(BNODE_REFS, "get_node(%d:%d): %d\n",
 			node->tree->cnid, node->this,
-			atomic_read(&node->refcnt));
+			refcount_read(&node->refcnt));
 	}
 }
 
@@ -462,9 +462,9 @@ void hfs_bnode_put(struct hfs_bnode *node)
 
 		hfs_dbg(BNODE_REFS, "put_node(%d:%d): %d\n",
 			node->tree->cnid, node->this,
-			atomic_read(&node->refcnt));
-		BUG_ON(!atomic_read(&node->refcnt));
-		if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock))
+			refcount_read(&node->refcnt));
+		BUG_ON(!refcount_read(&node->refcnt));
+		if (!refcount_dec_and_lock(&node->refcnt, &tree->hash_lock))
 			return;
 		for (i = 0; i < tree->pages_per_bnode; i++) {
 			if (!node->page[i])
diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c
index 37cdd95..5758e5e 100644
--- a/fs/hfs/btree.c
+++ b/fs/hfs/btree.c
@@ -144,10 +144,10 @@ void hfs_btree_close(struct hfs_btree *tree)
 	for (i = 0; i < NODE_HASH_SIZE; i++) {
 		while ((node = tree->node_hash[i])) {
 			tree->node_hash[i] = node->next_hash;
-			if (atomic_read(&node->refcnt))
+			if (refcount_read(&node->refcnt))
 				pr_err("node %d:%d still has %d user(s)!\n",
 				       node->tree->cnid, node->this,
-				       atomic_read(&node->refcnt));
+				       refcount_read(&node->refcnt));
 			hfs_bnode_free(node);
 			tree->node_hash_cnt--;
 		}
diff --git a/fs/hfs/btree.h b/fs/hfs/btree.h
index f6bd266..99b5fd3 100644
--- a/fs/hfs/btree.h
+++ b/fs/hfs/btree.h
@@ -6,6 +6,7 @@
  * (C) 2003 Ardis Technologies <roman@ardistech.com>
  */
 
+#include <linux/refcount.h>
 #include "hfs_fs.h"
 
 typedef int (*btree_keycmp)(const btree_key *, const btree_key *);
@@ -57,7 +58,7 @@ struct hfs_bnode {
 	struct hfs_bnode *next_hash;
 	unsigned long flags;
 	wait_queue_head_t lock_wq;
-	atomic_t refcnt;
+	refcount_t refcnt;
 	unsigned int page_offset;
 	struct page *page[0];
 };
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index f776acf..8ac61e4 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -98,7 +98,7 @@ static int hfs_releasepage(struct page *page, gfp_t mask)
 		node = hfs_bnode_findhash(tree, nidx);
 		if (!node)
 			;
-		else if (atomic_read(&node->refcnt))
+		else if (refcount_read(&node->refcnt))
 			res = 0;
 		if (res && node) {
 			hfs_bnode_unhash(node);
@@ -113,7 +113,7 @@ static int hfs_releasepage(struct page *page, gfp_t mask)
 			node = hfs_bnode_findhash(tree, nidx++);
 			if (!node)
 				continue;
-			if (atomic_read(&node->refcnt)) {
+			if (refcount_read(&node->refcnt)) {
 				res = 0;
 				break;
 			}
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
index ce014ce..9abaf14 100644
--- a/fs/hfsplus/bnode.c
+++ b/fs/hfsplus/bnode.c
@@ -422,7 +422,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
 	node->tree = tree;
 	node->this = cnid;
 	set_bit(HFS_BNODE_NEW, &node->flags);
-	atomic_set(&node->refcnt, 1);
+	refcount_set(&node->refcnt, 1);
 	hfs_dbg(BNODE_REFS, "new_node(%d:%d): 1\n",
 		node->tree->cnid, node->this);
 	init_waitqueue_head(&node->lock_wq);
@@ -468,7 +468,7 @@ void hfs_bnode_unhash(struct hfs_bnode *node)
 	struct hfs_bnode **p;
 
 	hfs_dbg(BNODE_REFS, "remove_node(%d:%d): %d\n",
-		node->tree->cnid, node->this, atomic_read(&node->refcnt));
+		node->tree->cnid, node->this, refcount_read(&node->refcnt));
 	for (p = &node->tree->node_hash[hfs_bnode_hash(node->this)];
 	     *p && *p != node; p = &(*p)->next_hash)
 		;
@@ -614,10 +614,10 @@ struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num)
 void hfs_bnode_get(struct hfs_bnode *node)
 {
 	if (node) {
-		atomic_inc(&node->refcnt);
+		refcount_inc(&node->refcnt);
 		hfs_dbg(BNODE_REFS, "get_node(%d:%d): %d\n",
 			node->tree->cnid, node->this,
-			atomic_read(&node->refcnt));
+			refcount_read(&node->refcnt));
 	}
 }
 
@@ -630,9 +630,9 @@ void hfs_bnode_put(struct hfs_bnode *node)
 
 		hfs_dbg(BNODE_REFS, "put_node(%d:%d): %d\n",
 			node->tree->cnid, node->this,
-			atomic_read(&node->refcnt));
-		BUG_ON(!atomic_read(&node->refcnt));
-		if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock))
+			refcount_read(&node->refcnt));
+		BUG_ON(!refcount_read(&node->refcnt));
+		if (!refcount_dec_and_lock(&node->refcnt, &tree->hash_lock))
 			return;
 		for (i = 0; i < tree->pages_per_bnode; i++) {
 			if (!node->page[i])
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
index d9d1a36..0823dca 100644
--- a/fs/hfsplus/btree.c
+++ b/fs/hfsplus/btree.c
@@ -265,11 +265,11 @@ void hfs_btree_close(struct hfs_btree *tree)
 	for (i = 0; i < NODE_HASH_SIZE; i++) {
 		while ((node = tree->node_hash[i])) {
 			tree->node_hash[i] = node->next_hash;
-			if (atomic_read(&node->refcnt))
+			if (refcount_read(&node->refcnt))
 				pr_crit("node %d:%d "
 						"still has %d user(s)!\n",
 					node->tree->cnid, node->this,
-					atomic_read(&node->refcnt));
+					refcount_read(&node->refcnt));
 			hfs_bnode_free(node);
 			tree->node_hash_cnt--;
 		}
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index a3f03b2..a895715 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -20,6 +20,7 @@
 #include <linux/mutex.h>
 #include <linux/buffer_head.h>
 #include <linux/blkdev.h>
+#include <linux/refcount.h>
 #include "hfsplus_raw.h"
 
 #define DBG_BNODE_REFS	0x00000001
@@ -115,7 +116,7 @@ struct hfs_bnode {
 	struct hfs_bnode *next_hash;
 	unsigned long flags;
 	wait_queue_head_t lock_wq;
-	atomic_t refcnt;
+	refcount_t refcnt;
 	unsigned int page_offset;
 	struct page *page[0];
 };
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 2e796f8..d1fbb4d 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -94,7 +94,7 @@ static int hfsplus_releasepage(struct page *page, gfp_t mask)
 		node = hfs_bnode_findhash(tree, nidx);
 		if (!node)
 			;
-		else if (atomic_read(&node->refcnt))
+		else if (refcount_read(&node->refcnt))
 			res = 0;
 		if (res && node) {
 			hfs_bnode_unhash(node);
@@ -110,7 +110,7 @@ static int hfsplus_releasepage(struct page *page, gfp_t mask)
 			node = hfs_bnode_findhash(tree, nidx++);
 			if (!node)
 				continue;
-			if (atomic_read(&node->refcnt)) {
+			if (refcount_read(&node->refcnt)) {
 				res = 0;
 				break;
 			}
-- 
2.7.4

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

* [PATCH 06/10] fs, fscache: convert fscache_cache_tag.usage from atomic_t to refcount_t
  2017-03-02 10:43 [PATCH 00/10] various fs subsystems refcounter conversions Elena Reshetova
                   ` (3 preceding siblings ...)
       [not found] ` <1488451397-3365-1-git-send-email-elena.reshetova-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
@ 2017-03-02 10:43 ` Elena Reshetova
  2017-03-02 10:43 ` [PATCH 09/10] fs, fsnotify: convert fsnotify_mark.refcnt " Elena Reshetova
  2017-03-02 10:43   ` Elena Reshetova
  6 siblings, 0 replies; 16+ messages in thread
From: Elena Reshetova @ 2017-03-02 10:43 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, linux-nilfs, linux-cachefs, linux-cifs, peterz,
	gregkh, viro, dhowells, sfrench, eparis, konishi.ryusuke, john,
	rlove, paul, 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/fscache/cache.c            | 8 ++++----
 include/linux/fscache-cache.h | 3 ++-
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/fs/fscache/cache.c b/fs/fscache/cache.c
index 56cce7f..ca6e282 100644
--- a/fs/fscache/cache.c
+++ b/fs/fscache/cache.c
@@ -33,7 +33,7 @@ struct fscache_cache_tag *__fscache_lookup_cache_tag(const char *name)
 
 	list_for_each_entry(tag, &fscache_cache_tag_list, link) {
 		if (strcmp(tag->name, name) == 0) {
-			atomic_inc(&tag->usage);
+			refcount_inc(&tag->usage);
 			up_read(&fscache_addremove_sem);
 			return tag;
 		}
@@ -47,7 +47,7 @@ struct fscache_cache_tag *__fscache_lookup_cache_tag(const char *name)
 		/* return a dummy tag if out of memory */
 		return ERR_PTR(-ENOMEM);
 
-	atomic_set(&xtag->usage, 1);
+	refcount_set(&xtag->usage, 1);
 	strcpy(xtag->name, name);
 
 	/* write lock, search again and add if still not present */
@@ -55,7 +55,7 @@ struct fscache_cache_tag *__fscache_lookup_cache_tag(const char *name)
 
 	list_for_each_entry(tag, &fscache_cache_tag_list, link) {
 		if (strcmp(tag->name, name) == 0) {
-			atomic_inc(&tag->usage);
+			refcount_inc(&tag->usage);
 			up_write(&fscache_addremove_sem);
 			kfree(xtag);
 			return tag;
@@ -75,7 +75,7 @@ void __fscache_release_cache_tag(struct fscache_cache_tag *tag)
 	if (tag != ERR_PTR(-ENOMEM)) {
 		down_write(&fscache_addremove_sem);
 
-		if (atomic_dec_and_test(&tag->usage))
+		if (refcount_dec_and_test(&tag->usage))
 			list_del_init(&tag->link);
 		else
 			tag = NULL;
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h
index 4c467ef..dcec7b3 100644
--- a/include/linux/fscache-cache.h
+++ b/include/linux/fscache-cache.h
@@ -21,6 +21,7 @@
 #include <linux/fscache.h>
 #include <linux/sched.h>
 #include <linux/workqueue.h>
+#include <linux/refcount.h>
 
 #define NR_MAXCACHES BITS_PER_LONG
 
@@ -37,7 +38,7 @@ struct fscache_cache_tag {
 	struct fscache_cache	*cache;		/* cache referred to by this tag */
 	unsigned long		flags;
 #define FSCACHE_TAG_RESERVED	0		/* T if tag is reserved for a cache */
-	atomic_t		usage;
+	refcount_t		usage;
 	char			name[0];	/* tag name */
 };
 
-- 
2.7.4

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

* [PATCH 07/10] fs, fscache: convert fscache_operation.usage from atomic_t to refcount_t
  2017-03-02 10:43 [PATCH 00/10] various fs subsystems refcounter conversions Elena Reshetova
@ 2017-03-02 10:43     ` Elena Reshetova
  2017-03-02 10:43 ` [PATCH 03/10] fs, proc: convert proc_dir_entry.count " Elena Reshetova
                       ` (5 subsequent siblings)
  6 siblings, 0 replies; 16+ messages in thread
From: Elena Reshetova @ 2017-03-02 10:43 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-nilfs-u79uwXL29TY76Z2rM5mHXA,
	linux-cachefs-H+wXaHxf7aLQT0dZR+AlfA,
	linux-cifs-u79uwXL29TY76Z2rM5mHXA, peterz-wEGCiKHe2LqWVfeAwA7xHQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
	dhowells-H+wXaHxf7aLQT0dZR+AlfA, sfrench-eUNUBHrolfbYtjvyW6yDsg,
	eparis-FjpueFixGhCM4zKIHC2jIg,
	konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg,
	john-jueV0HHMeujJJrXXpGQQMAC/G2K4zDHf,
	rlove-L7G0xEPcOZbYtjvyW6yDsg, paul-r2n+y4ga6xFZroRs9YW3xA,
	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-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Hans Liljestrand <ishkamiel-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Kees Cook <keescook-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
Signed-off-by: David Windsor <dwindsor-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 fs/cachefiles/rdwr.c          |  2 +-
 fs/fscache/operation.c        | 38 +++++++++++++++++++-------------------
 fs/fscache/page.c             |  2 +-
 include/linux/fscache-cache.h |  4 ++--
 4 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c
index afbdc41..c987de6 100644
--- a/fs/cachefiles/rdwr.c
+++ b/fs/cachefiles/rdwr.c
@@ -692,7 +692,7 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op,
 			     struct cachefiles_cache, cache);
 
 	_enter("{OBJ%x,%d},,%d,,",
-	       object->fscache.debug_id, atomic_read(&op->op.usage),
+	       object->fscache.debug_id, refcount_read(&op->op.usage),
 	       *nr_pages);
 
 	if (!object->backer)
diff --git a/fs/fscache/operation.c b/fs/fscache/operation.c
index de67745..eb84c95 100644
--- a/fs/fscache/operation.c
+++ b/fs/fscache/operation.c
@@ -38,7 +38,7 @@ void fscache_operation_init(struct fscache_operation *op,
 			    fscache_operation_release_t release)
 {
 	INIT_WORK(&op->work, fscache_op_work_func);
-	atomic_set(&op->usage, 1);
+	refcount_set(&op->usage, 1);
 	op->state = FSCACHE_OP_ST_INITIALISED;
 	op->debug_id = atomic_inc_return(&fscache_op_debug_id);
 	op->processor = processor;
@@ -60,19 +60,19 @@ EXPORT_SYMBOL(fscache_operation_init);
 void fscache_enqueue_operation(struct fscache_operation *op)
 {
 	_enter("{OBJ%x OP%x,%u}",
-	       op->object->debug_id, op->debug_id, atomic_read(&op->usage));
+	       op->object->debug_id, op->debug_id, refcount_read(&op->usage));
 
 	ASSERT(list_empty(&op->pend_link));
 	ASSERT(op->processor != NULL);
 	ASSERT(fscache_object_is_available(op->object));
-	ASSERTCMP(atomic_read(&op->usage), >, 0);
+	ASSERTCMP(refcount_read(&op->usage), >, 0);
 	ASSERTCMP(op->state, ==, FSCACHE_OP_ST_IN_PROGRESS);
 
 	fscache_stat(&fscache_n_op_enqueue);
 	switch (op->flags & FSCACHE_OP_TYPE) {
 	case FSCACHE_OP_ASYNC:
 		_debug("queue async");
-		atomic_inc(&op->usage);
+		refcount_inc(&op->usage);
 		if (!queue_work(fscache_op_wq, &op->work))
 			fscache_put_operation(op);
 		break;
@@ -156,7 +156,7 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
 	_enter("{OBJ%x OP%x},", object->debug_id, op->debug_id);
 
 	ASSERTCMP(op->state, ==, FSCACHE_OP_ST_INITIALISED);
-	ASSERTCMP(atomic_read(&op->usage), >, 0);
+	ASSERTCMP(refcount_read(&op->usage), >, 0);
 
 	spin_lock(&object->lock);
 	ASSERTCMP(object->n_ops, >=, object->n_in_progress);
@@ -183,11 +183,11 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
 		object->n_exclusive++;	/* reads and writes must wait */
 
 		if (object->n_in_progress > 0) {
-			atomic_inc(&op->usage);
+			refcount_inc(&op->usage);
 			list_add_tail(&op->pend_link, &object->pending_ops);
 			fscache_stat(&fscache_n_op_pend);
 		} else if (!list_empty(&object->pending_ops)) {
-			atomic_inc(&op->usage);
+			refcount_inc(&op->usage);
 			list_add_tail(&op->pend_link, &object->pending_ops);
 			fscache_stat(&fscache_n_op_pend);
 			fscache_start_operations(object);
@@ -203,7 +203,7 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
 		op->object = object;
 		object->n_ops++;
 		object->n_exclusive++;	/* reads and writes must wait */
-		atomic_inc(&op->usage);
+		refcount_inc(&op->usage);
 		list_add_tail(&op->pend_link, &object->pending_ops);
 		fscache_stat(&fscache_n_op_pend);
 		ret = 0;
@@ -238,10 +238,10 @@ int fscache_submit_op(struct fscache_object *object,
 	int ret;
 
 	_enter("{OBJ%x OP%x},{%u}",
-	       object->debug_id, op->debug_id, atomic_read(&op->usage));
+	       object->debug_id, op->debug_id, refcount_read(&op->usage));
 
 	ASSERTCMP(op->state, ==, FSCACHE_OP_ST_INITIALISED);
-	ASSERTCMP(atomic_read(&op->usage), >, 0);
+	ASSERTCMP(refcount_read(&op->usage), >, 0);
 
 	spin_lock(&object->lock);
 	ASSERTCMP(object->n_ops, >=, object->n_in_progress);
@@ -267,11 +267,11 @@ int fscache_submit_op(struct fscache_object *object,
 		object->n_ops++;
 
 		if (object->n_exclusive > 0) {
-			atomic_inc(&op->usage);
+			refcount_inc(&op->usage);
 			list_add_tail(&op->pend_link, &object->pending_ops);
 			fscache_stat(&fscache_n_op_pend);
 		} else if (!list_empty(&object->pending_ops)) {
-			atomic_inc(&op->usage);
+			refcount_inc(&op->usage);
 			list_add_tail(&op->pend_link, &object->pending_ops);
 			fscache_stat(&fscache_n_op_pend);
 			fscache_start_operations(object);
@@ -283,7 +283,7 @@ int fscache_submit_op(struct fscache_object *object,
 	} else if (flags & BIT(FSCACHE_OBJECT_IS_LOOKED_UP)) {
 		op->object = object;
 		object->n_ops++;
-		atomic_inc(&op->usage);
+		refcount_inc(&op->usage);
 		list_add_tail(&op->pend_link, &object->pending_ops);
 		fscache_stat(&fscache_n_op_pend);
 		ret = 0;
@@ -359,7 +359,7 @@ int fscache_cancel_op(struct fscache_operation *op,
 
 	ASSERTCMP(op->state, >=, FSCACHE_OP_ST_PENDING);
 	ASSERTCMP(op->state, !=, FSCACHE_OP_ST_CANCELLED);
-	ASSERTCMP(atomic_read(&op->usage), >, 0);
+	ASSERTCMP(refcount_read(&op->usage), >, 0);
 
 	spin_lock(&object->lock);
 
@@ -481,11 +481,11 @@ void fscache_put_operation(struct fscache_operation *op)
 	struct fscache_cache *cache;
 
 	_enter("{OBJ%x OP%x,%d}",
-	       op->object->debug_id, op->debug_id, atomic_read(&op->usage));
+	       op->object->debug_id, op->debug_id, refcount_read(&op->usage));
 
-	ASSERTCMP(atomic_read(&op->usage), >, 0);
+	ASSERTCMP(refcount_read(&op->usage), >, 0);
 
-	if (!atomic_dec_and_test(&op->usage))
+	if (!refcount_dec_and_test(&op->usage))
 		return;
 
 	_debug("PUT OP");
@@ -569,7 +569,7 @@ void fscache_operation_gc(struct work_struct *work)
 		       object->debug_id, op->debug_id);
 		fscache_stat(&fscache_n_op_gc);
 
-		ASSERTCMP(atomic_read(&op->usage), ==, 0);
+		ASSERTCMP(refcount_read(&op->usage), ==, 0);
 		ASSERTCMP(op->state, ==, FSCACHE_OP_ST_DEAD);
 
 		ASSERTCMP(object->n_ops, >, 0);
@@ -599,7 +599,7 @@ void fscache_op_work_func(struct work_struct *work)
 	unsigned long start;
 
 	_enter("{OBJ%x OP%x,%d}",
-	       op->object->debug_id, op->debug_id, atomic_read(&op->usage));
+	       op->object->debug_id, op->debug_id, refcount_read(&op->usage));
 
 	ASSERT(op->processor != NULL);
 	start = jiffies;
diff --git a/fs/fscache/page.c b/fs/fscache/page.c
index c8c4f79..352393c 100644
--- a/fs/fscache/page.c
+++ b/fs/fscache/page.c
@@ -774,7 +774,7 @@ static void fscache_write_op(struct fscache_operation *_op)
 	void *results[1];
 	int ret;
 
-	_enter("{OP%x,%d}", op->op.debug_id, atomic_read(&op->op.usage));
+	_enter("{OP%x,%d}", op->op.debug_id, refcount_read(&op->op.usage));
 
 	spin_lock(&object->lock);
 	cookie = object->cookie;
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h
index dcec7b3..0093158 100644
--- a/include/linux/fscache-cache.h
+++ b/include/linux/fscache-cache.h
@@ -103,7 +103,7 @@ struct fscache_operation {
 #define FSCACHE_OP_KEEP_FLAGS	0x00f0	/* flags to keep when repurposing an op */
 
 	enum fscache_operation_state state;
-	atomic_t		usage;
+	refcount_t		usage;
 	unsigned		debug_id;	/* debugging ID */
 
 	/* operation processor callback
@@ -161,7 +161,7 @@ typedef int (*fscache_pages_retrieval_func_t)(struct fscache_retrieval *op,
 static inline
 struct fscache_retrieval *fscache_get_retrieval(struct fscache_retrieval *op)
 {
-	atomic_inc(&op->op.usage);
+	refcount_inc(&op->op.usage);
 	return op;
 }
 
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 07/10] fs, fscache: convert fscache_operation.usage from atomic_t to refcount_t
@ 2017-03-02 10:43     ` Elena Reshetova
  0 siblings, 0 replies; 16+ messages in thread
From: Elena Reshetova @ 2017-03-02 10:43 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, linux-nilfs, linux-cachefs, linux-cifs, peterz,
	gregkh, viro, dhowells, sfrench, eparis, konishi.ryusuke, john,
	rlove, paul, 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/cachefiles/rdwr.c          |  2 +-
 fs/fscache/operation.c        | 38 +++++++++++++++++++-------------------
 fs/fscache/page.c             |  2 +-
 include/linux/fscache-cache.h |  4 ++--
 4 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c
index afbdc41..c987de6 100644
--- a/fs/cachefiles/rdwr.c
+++ b/fs/cachefiles/rdwr.c
@@ -692,7 +692,7 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op,
 			     struct cachefiles_cache, cache);
 
 	_enter("{OBJ%x,%d},,%d,,",
-	       object->fscache.debug_id, atomic_read(&op->op.usage),
+	       object->fscache.debug_id, refcount_read(&op->op.usage),
 	       *nr_pages);
 
 	if (!object->backer)
diff --git a/fs/fscache/operation.c b/fs/fscache/operation.c
index de67745..eb84c95 100644
--- a/fs/fscache/operation.c
+++ b/fs/fscache/operation.c
@@ -38,7 +38,7 @@ void fscache_operation_init(struct fscache_operation *op,
 			    fscache_operation_release_t release)
 {
 	INIT_WORK(&op->work, fscache_op_work_func);
-	atomic_set(&op->usage, 1);
+	refcount_set(&op->usage, 1);
 	op->state = FSCACHE_OP_ST_INITIALISED;
 	op->debug_id = atomic_inc_return(&fscache_op_debug_id);
 	op->processor = processor;
@@ -60,19 +60,19 @@ EXPORT_SYMBOL(fscache_operation_init);
 void fscache_enqueue_operation(struct fscache_operation *op)
 {
 	_enter("{OBJ%x OP%x,%u}",
-	       op->object->debug_id, op->debug_id, atomic_read(&op->usage));
+	       op->object->debug_id, op->debug_id, refcount_read(&op->usage));
 
 	ASSERT(list_empty(&op->pend_link));
 	ASSERT(op->processor != NULL);
 	ASSERT(fscache_object_is_available(op->object));
-	ASSERTCMP(atomic_read(&op->usage), >, 0);
+	ASSERTCMP(refcount_read(&op->usage), >, 0);
 	ASSERTCMP(op->state, ==, FSCACHE_OP_ST_IN_PROGRESS);
 
 	fscache_stat(&fscache_n_op_enqueue);
 	switch (op->flags & FSCACHE_OP_TYPE) {
 	case FSCACHE_OP_ASYNC:
 		_debug("queue async");
-		atomic_inc(&op->usage);
+		refcount_inc(&op->usage);
 		if (!queue_work(fscache_op_wq, &op->work))
 			fscache_put_operation(op);
 		break;
@@ -156,7 +156,7 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
 	_enter("{OBJ%x OP%x},", object->debug_id, op->debug_id);
 
 	ASSERTCMP(op->state, ==, FSCACHE_OP_ST_INITIALISED);
-	ASSERTCMP(atomic_read(&op->usage), >, 0);
+	ASSERTCMP(refcount_read(&op->usage), >, 0);
 
 	spin_lock(&object->lock);
 	ASSERTCMP(object->n_ops, >=, object->n_in_progress);
@@ -183,11 +183,11 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
 		object->n_exclusive++;	/* reads and writes must wait */
 
 		if (object->n_in_progress > 0) {
-			atomic_inc(&op->usage);
+			refcount_inc(&op->usage);
 			list_add_tail(&op->pend_link, &object->pending_ops);
 			fscache_stat(&fscache_n_op_pend);
 		} else if (!list_empty(&object->pending_ops)) {
-			atomic_inc(&op->usage);
+			refcount_inc(&op->usage);
 			list_add_tail(&op->pend_link, &object->pending_ops);
 			fscache_stat(&fscache_n_op_pend);
 			fscache_start_operations(object);
@@ -203,7 +203,7 @@ int fscache_submit_exclusive_op(struct fscache_object *object,
 		op->object = object;
 		object->n_ops++;
 		object->n_exclusive++;	/* reads and writes must wait */
-		atomic_inc(&op->usage);
+		refcount_inc(&op->usage);
 		list_add_tail(&op->pend_link, &object->pending_ops);
 		fscache_stat(&fscache_n_op_pend);
 		ret = 0;
@@ -238,10 +238,10 @@ int fscache_submit_op(struct fscache_object *object,
 	int ret;
 
 	_enter("{OBJ%x OP%x},{%u}",
-	       object->debug_id, op->debug_id, atomic_read(&op->usage));
+	       object->debug_id, op->debug_id, refcount_read(&op->usage));
 
 	ASSERTCMP(op->state, ==, FSCACHE_OP_ST_INITIALISED);
-	ASSERTCMP(atomic_read(&op->usage), >, 0);
+	ASSERTCMP(refcount_read(&op->usage), >, 0);
 
 	spin_lock(&object->lock);
 	ASSERTCMP(object->n_ops, >=, object->n_in_progress);
@@ -267,11 +267,11 @@ int fscache_submit_op(struct fscache_object *object,
 		object->n_ops++;
 
 		if (object->n_exclusive > 0) {
-			atomic_inc(&op->usage);
+			refcount_inc(&op->usage);
 			list_add_tail(&op->pend_link, &object->pending_ops);
 			fscache_stat(&fscache_n_op_pend);
 		} else if (!list_empty(&object->pending_ops)) {
-			atomic_inc(&op->usage);
+			refcount_inc(&op->usage);
 			list_add_tail(&op->pend_link, &object->pending_ops);
 			fscache_stat(&fscache_n_op_pend);
 			fscache_start_operations(object);
@@ -283,7 +283,7 @@ int fscache_submit_op(struct fscache_object *object,
 	} else if (flags & BIT(FSCACHE_OBJECT_IS_LOOKED_UP)) {
 		op->object = object;
 		object->n_ops++;
-		atomic_inc(&op->usage);
+		refcount_inc(&op->usage);
 		list_add_tail(&op->pend_link, &object->pending_ops);
 		fscache_stat(&fscache_n_op_pend);
 		ret = 0;
@@ -359,7 +359,7 @@ int fscache_cancel_op(struct fscache_operation *op,
 
 	ASSERTCMP(op->state, >=, FSCACHE_OP_ST_PENDING);
 	ASSERTCMP(op->state, !=, FSCACHE_OP_ST_CANCELLED);
-	ASSERTCMP(atomic_read(&op->usage), >, 0);
+	ASSERTCMP(refcount_read(&op->usage), >, 0);
 
 	spin_lock(&object->lock);
 
@@ -481,11 +481,11 @@ void fscache_put_operation(struct fscache_operation *op)
 	struct fscache_cache *cache;
 
 	_enter("{OBJ%x OP%x,%d}",
-	       op->object->debug_id, op->debug_id, atomic_read(&op->usage));
+	       op->object->debug_id, op->debug_id, refcount_read(&op->usage));
 
-	ASSERTCMP(atomic_read(&op->usage), >, 0);
+	ASSERTCMP(refcount_read(&op->usage), >, 0);
 
-	if (!atomic_dec_and_test(&op->usage))
+	if (!refcount_dec_and_test(&op->usage))
 		return;
 
 	_debug("PUT OP");
@@ -569,7 +569,7 @@ void fscache_operation_gc(struct work_struct *work)
 		       object->debug_id, op->debug_id);
 		fscache_stat(&fscache_n_op_gc);
 
-		ASSERTCMP(atomic_read(&op->usage), ==, 0);
+		ASSERTCMP(refcount_read(&op->usage), ==, 0);
 		ASSERTCMP(op->state, ==, FSCACHE_OP_ST_DEAD);
 
 		ASSERTCMP(object->n_ops, >, 0);
@@ -599,7 +599,7 @@ void fscache_op_work_func(struct work_struct *work)
 	unsigned long start;
 
 	_enter("{OBJ%x OP%x,%d}",
-	       op->object->debug_id, op->debug_id, atomic_read(&op->usage));
+	       op->object->debug_id, op->debug_id, refcount_read(&op->usage));
 
 	ASSERT(op->processor != NULL);
 	start = jiffies;
diff --git a/fs/fscache/page.c b/fs/fscache/page.c
index c8c4f79..352393c 100644
--- a/fs/fscache/page.c
+++ b/fs/fscache/page.c
@@ -774,7 +774,7 @@ static void fscache_write_op(struct fscache_operation *_op)
 	void *results[1];
 	int ret;
 
-	_enter("{OP%x,%d}", op->op.debug_id, atomic_read(&op->op.usage));
+	_enter("{OP%x,%d}", op->op.debug_id, refcount_read(&op->op.usage));
 
 	spin_lock(&object->lock);
 	cookie = object->cookie;
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h
index dcec7b3..0093158 100644
--- a/include/linux/fscache-cache.h
+++ b/include/linux/fscache-cache.h
@@ -103,7 +103,7 @@ struct fscache_operation {
 #define FSCACHE_OP_KEEP_FLAGS	0x00f0	/* flags to keep when repurposing an op */
 
 	enum fscache_operation_state state;
-	atomic_t		usage;
+	refcount_t		usage;
 	unsigned		debug_id;	/* debugging ID */
 
 	/* operation processor callback
@@ -161,7 +161,7 @@ typedef int (*fscache_pages_retrieval_func_t)(struct fscache_retrieval *op,
 static inline
 struct fscache_retrieval *fscache_get_retrieval(struct fscache_retrieval *op)
 {
-	atomic_inc(&op->op.usage);
+	refcount_inc(&op->op.usage);
 	return op;
 }
 
-- 
2.7.4

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

* [PATCH 08/10] fs, fsnotify: convert fsnotify_group.refcnt from atomic_t to refcount_t
  2017-03-02 10:43 [PATCH 00/10] various fs subsystems refcounter conversions Elena Reshetova
@ 2017-03-02 10:43     ` Elena Reshetova
  2017-03-02 10:43 ` [PATCH 03/10] fs, proc: convert proc_dir_entry.count " Elena Reshetova
                       ` (5 subsequent siblings)
  6 siblings, 0 replies; 16+ messages in thread
From: Elena Reshetova @ 2017-03-02 10:43 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-nilfs-u79uwXL29TY76Z2rM5mHXA,
	linux-cachefs-H+wXaHxf7aLQT0dZR+AlfA,
	linux-cifs-u79uwXL29TY76Z2rM5mHXA, peterz-wEGCiKHe2LqWVfeAwA7xHQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
	dhowells-H+wXaHxf7aLQT0dZR+AlfA, sfrench-eUNUBHrolfbYtjvyW6yDsg,
	eparis-FjpueFixGhCM4zKIHC2jIg,
	konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg,
	john-jueV0HHMeujJJrXXpGQQMAC/G2K4zDHf,
	rlove-L7G0xEPcOZbYtjvyW6yDsg, paul-r2n+y4ga6xFZroRs9YW3xA,
	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-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Hans Liljestrand <ishkamiel-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Kees Cook <keescook-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
Signed-off-by: David Windsor <dwindsor-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 fs/notify/group.c                | 6 +++---
 include/linux/fsnotify_backend.h | 3 ++-
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/fs/notify/group.c b/fs/notify/group.c
index fbe3cbe..81356c1 100644
--- a/fs/notify/group.c
+++ b/fs/notify/group.c
@@ -98,7 +98,7 @@ void fsnotify_destroy_group(struct fsnotify_group *group)
  */
 void fsnotify_get_group(struct fsnotify_group *group)
 {
-	atomic_inc(&group->refcnt);
+	refcount_inc(&group->refcnt);
 }
 
 /*
@@ -106,7 +106,7 @@ void fsnotify_get_group(struct fsnotify_group *group)
  */
 void fsnotify_put_group(struct fsnotify_group *group)
 {
-	if (atomic_dec_and_test(&group->refcnt))
+	if (refcount_dec_and_test(&group->refcnt))
 		fsnotify_final_destroy_group(group);
 }
 
@@ -122,7 +122,7 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
 		return ERR_PTR(-ENOMEM);
 
 	/* set to 0 when there a no external references to this group */
-	atomic_set(&group->refcnt, 1);
+	refcount_set(&group->refcnt, 1);
 	atomic_set(&group->num_marks, 0);
 
 	spin_lock_init(&group->notification_lock);
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index e6e689b..1f7aa16 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -17,6 +17,7 @@
 #include <linux/types.h>
 #include <linux/atomic.h>
 #include <linux/user_namespace.h>
+#include <linux/refcount.h>
 
 /*
  * IN_* from inotfy.h lines up EXACTLY with FS_*, this is so we can easily
@@ -131,7 +132,7 @@ struct fsnotify_group {
 	 * inotify_init() and the refcnt will hit 0 only when that fd has been
 	 * closed.
 	 */
-	atomic_t refcnt;		/* things with interest in this group */
+	refcount_t refcnt;		/* things with interest in this group */
 
 	const struct fsnotify_ops *ops;	/* how this group handles things */
 
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 08/10] fs, fsnotify: convert fsnotify_group.refcnt from atomic_t to refcount_t
@ 2017-03-02 10:43     ` Elena Reshetova
  0 siblings, 0 replies; 16+ messages in thread
From: Elena Reshetova @ 2017-03-02 10:43 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, linux-nilfs, linux-cachefs, linux-cifs, peterz,
	gregkh, viro, dhowells, sfrench, eparis, konishi.ryusuke, john,
	rlove, paul, 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/notify/group.c                | 6 +++---
 include/linux/fsnotify_backend.h | 3 ++-
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/fs/notify/group.c b/fs/notify/group.c
index fbe3cbe..81356c1 100644
--- a/fs/notify/group.c
+++ b/fs/notify/group.c
@@ -98,7 +98,7 @@ void fsnotify_destroy_group(struct fsnotify_group *group)
  */
 void fsnotify_get_group(struct fsnotify_group *group)
 {
-	atomic_inc(&group->refcnt);
+	refcount_inc(&group->refcnt);
 }
 
 /*
@@ -106,7 +106,7 @@ void fsnotify_get_group(struct fsnotify_group *group)
  */
 void fsnotify_put_group(struct fsnotify_group *group)
 {
-	if (atomic_dec_and_test(&group->refcnt))
+	if (refcount_dec_and_test(&group->refcnt))
 		fsnotify_final_destroy_group(group);
 }
 
@@ -122,7 +122,7 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
 		return ERR_PTR(-ENOMEM);
 
 	/* set to 0 when there a no external references to this group */
-	atomic_set(&group->refcnt, 1);
+	refcount_set(&group->refcnt, 1);
 	atomic_set(&group->num_marks, 0);
 
 	spin_lock_init(&group->notification_lock);
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index e6e689b..1f7aa16 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -17,6 +17,7 @@
 #include <linux/types.h>
 #include <linux/atomic.h>
 #include <linux/user_namespace.h>
+#include <linux/refcount.h>
 
 /*
  * IN_* from inotfy.h lines up EXACTLY with FS_*, this is so we can easily
@@ -131,7 +132,7 @@ struct fsnotify_group {
 	 * inotify_init() and the refcnt will hit 0 only when that fd has been
 	 * closed.
 	 */
-	atomic_t refcnt;		/* things with interest in this group */
+	refcount_t refcnt;		/* things with interest in this group */
 
 	const struct fsnotify_ops *ops;	/* how this group handles things */
 
-- 
2.7.4

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

* [PATCH 09/10] fs, fsnotify: convert fsnotify_mark.refcnt from atomic_t to refcount_t
  2017-03-02 10:43 [PATCH 00/10] various fs subsystems refcounter conversions Elena Reshetova
                   ` (4 preceding siblings ...)
  2017-03-02 10:43 ` [PATCH 06/10] fs, fscache: convert fscache_cache_tag.usage " Elena Reshetova
@ 2017-03-02 10:43 ` Elena Reshetova
  2017-03-02 10:43   ` Elena Reshetova
  6 siblings, 0 replies; 16+ messages in thread
From: Elena Reshetova @ 2017-03-02 10:43 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, linux-nilfs, linux-cachefs, linux-cifs, peterz,
	gregkh, viro, dhowells, sfrench, eparis, konishi.ryusuke, john,
	rlove, paul, 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/notify/inotify/inotify_user.c | 4 ++--
 fs/notify/mark.c                 | 6 +++---
 include/linux/fsnotify_backend.h | 2 +-
 kernel/audit_tree.c              | 2 +-
 4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index 1cf41c6..c878e3c 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -376,7 +376,7 @@ static struct inotify_inode_mark *inotify_idr_find_locked(struct fsnotify_group
 
 		fsnotify_get_mark(fsn_mark);
 		/* One ref for being in the idr, one ref we just took */
-		BUG_ON(atomic_read(&fsn_mark->refcnt) < 2);
+		BUG_ON(refcount_read(&fsn_mark->refcnt) < 2);
 	}
 
 	return i_mark;
@@ -465,7 +465,7 @@ static void inotify_remove_from_idr(struct fsnotify_group *group,
 	 * one ref held by the caller trying to kill us
 	 * one ref grabbed by inotify_idr_find
 	 */
-	if (unlikely(atomic_read(&i_mark->fsn_mark.refcnt) < 3)) {
+	if (unlikely(refcount_read(&i_mark->fsn_mark.refcnt) < 3)) {
 		printk(KERN_ERR "%s: i_mark=%p i_mark->wd=%d i_mark->group=%p"
 			" i_mark->inode=%p\n", __func__, i_mark, i_mark->wd,
 			i_mark->fsn_mark.group, i_mark->fsn_mark.inode);
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index 6043306..5dbe3a0 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -102,12 +102,12 @@ static DECLARE_DELAYED_WORK(reaper_work, fsnotify_mark_destroy_workfn);
 
 void fsnotify_get_mark(struct fsnotify_mark *mark)
 {
-	atomic_inc(&mark->refcnt);
+	refcount_inc(&mark->refcnt);
 }
 
 void fsnotify_put_mark(struct fsnotify_mark *mark)
 {
-	if (atomic_dec_and_test(&mark->refcnt)) {
+	if (refcount_dec_and_test(&mark->refcnt)) {
 		if (mark->group)
 			fsnotify_put_group(mark->group);
 		mark->free_mark(mark);
@@ -518,7 +518,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark,
 {
 	memset(mark, 0, sizeof(*mark));
 	spin_lock_init(&mark->lock);
-	atomic_set(&mark->refcnt, 1);
+	refcount_set(&mark->refcnt, 1);
 	mark->free_mark = free_mark;
 }
 
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 1f7aa16..d874f26 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -214,7 +214,7 @@ struct fsnotify_mark {
 	__u32 mask;
 	/* We hold one for presence in g_list. Also one ref for each 'thing'
 	 * in kernel that found and may be using this mark. */
-	atomic_t refcnt;
+	refcount_t refcnt;
 	/* Group this mark is for. Set on mark creation, stable until last ref
 	 * is dropped */
 	struct fsnotify_group *group;
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index 7b44195..9f64663 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -973,7 +973,7 @@ static void audit_tree_freeing_mark(struct fsnotify_mark *entry, struct fsnotify
 	 * We are guaranteed to have at least one reference to the mark from
 	 * either the inode or the caller of fsnotify_destroy_mark().
 	 */
-	BUG_ON(atomic_read(&entry->refcnt) < 1);
+	BUG_ON(refcount_read(&entry->refcnt) < 1);
 }
 
 static const struct fsnotify_ops audit_tree_ops = {
-- 
2.7.4

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

* [PATCH 10/10] fs, cifs: convert tcon_link.tl_count from atomic_t to refcount_t
  2017-03-02 10:43 [PATCH 00/10] various fs subsystems refcounter conversions Elena Reshetova
@ 2017-03-02 10:43   ` Elena Reshetova
  2017-03-02 10:43 ` [PATCH 03/10] fs, proc: convert proc_dir_entry.count " Elena Reshetova
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 16+ messages in thread
From: Elena Reshetova @ 2017-03-02 10:43 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-cifs, linux-nilfs, paul, rlove, peterz, gregkh,
	Hans Liljestrand, sfrench, linux-cachefs, viro, konishi.ryusuke,
	linux-fsdevel, eparis, David Windsor, john, Elena Reshetova,
	Kees Cook

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/cifs/cifsglob.h | 5 +++--
 fs/cifs/connect.c  | 8 ++++----
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 1a90bb3..bd27f92 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -28,6 +28,7 @@
 #include "cifsacl.h"
 #include <crypto/internal/hash.h>
 #include <linux/scatterlist.h>
+#include <linux/refcount.h>
 #include <uapi/linux/cifs/cifs_mount.h>
 #ifdef CONFIG_CIFS_SMB2
 #include "smb2pdu.h"
@@ -978,7 +979,7 @@ struct tcon_link {
 #define TCON_LINK_PENDING	1
 #define TCON_LINK_IN_TREE	2
 	unsigned long		tl_time;
-	atomic_t		tl_count;
+	refcount_t		tl_count;
 	struct cifs_tcon	*tl_tcon;
 };
 
@@ -996,7 +997,7 @@ static inline struct tcon_link *
 cifs_get_tlink(struct tcon_link *tlink)
 {
 	if (tlink && !IS_ERR(tlink))
-		atomic_inc(&tlink->tl_count);
+		refcount_inc(&tlink->tl_count);
 	return tlink;
 }
 
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 777ad9f..e0f37ab 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2839,7 +2839,7 @@ cifs_put_tlink(struct tcon_link *tlink)
 	if (!tlink || IS_ERR(tlink))
 		return;
 
-	if (!atomic_dec_and_test(&tlink->tl_count) ||
+	if (!refcount_dec_and_test(&tlink->tl_count) ||
 	    test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
 		tlink->tl_time = jiffies;
 		return;
@@ -4302,7 +4302,7 @@ cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
 		newtlink->tl_tcon = ERR_PTR(-EACCES);
 		set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
 		set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
-		cifs_get_tlink(newtlink);
+		refcount_set(&newtlink->tl_count, 1);
 
 		spin_lock(&cifs_sb->tlink_tree_lock);
 		/* was one inserted after previous search? */
@@ -4380,11 +4380,11 @@ cifs_prune_tlinks(struct work_struct *work)
 		tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
 
 		if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
-		    atomic_read(&tlink->tl_count) != 0 ||
+		    refcount_read(&tlink->tl_count) != 0 ||
 		    time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
 			continue;
 
-		cifs_get_tlink(tlink);
+		refcount_set(&tlink->tl_count, 1);
 		clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
 		rb_erase(tmp, root);
 
-- 
2.7.4

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

* [PATCH 10/10] fs, cifs: convert tcon_link.tl_count from atomic_t to refcount_t
@ 2017-03-02 10:43   ` Elena Reshetova
  0 siblings, 0 replies; 16+ messages in thread
From: Elena Reshetova @ 2017-03-02 10:43 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, linux-nilfs, linux-cachefs, linux-cifs, peterz,
	gregkh, viro, dhowells, sfrench, eparis, konishi.ryusuke, john,
	rlove, paul, 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/cifs/cifsglob.h | 5 +++--
 fs/cifs/connect.c  | 8 ++++----
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 1a90bb3..bd27f92 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -28,6 +28,7 @@
 #include "cifsacl.h"
 #include <crypto/internal/hash.h>
 #include <linux/scatterlist.h>
+#include <linux/refcount.h>
 #include <uapi/linux/cifs/cifs_mount.h>
 #ifdef CONFIG_CIFS_SMB2
 #include "smb2pdu.h"
@@ -978,7 +979,7 @@ struct tcon_link {
 #define TCON_LINK_PENDING	1
 #define TCON_LINK_IN_TREE	2
 	unsigned long		tl_time;
-	atomic_t		tl_count;
+	refcount_t		tl_count;
 	struct cifs_tcon	*tl_tcon;
 };
 
@@ -996,7 +997,7 @@ static inline struct tcon_link *
 cifs_get_tlink(struct tcon_link *tlink)
 {
 	if (tlink && !IS_ERR(tlink))
-		atomic_inc(&tlink->tl_count);
+		refcount_inc(&tlink->tl_count);
 	return tlink;
 }
 
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 777ad9f..e0f37ab 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2839,7 +2839,7 @@ cifs_put_tlink(struct tcon_link *tlink)
 	if (!tlink || IS_ERR(tlink))
 		return;
 
-	if (!atomic_dec_and_test(&tlink->tl_count) ||
+	if (!refcount_dec_and_test(&tlink->tl_count) ||
 	    test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
 		tlink->tl_time = jiffies;
 		return;
@@ -4302,7 +4302,7 @@ cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
 		newtlink->tl_tcon = ERR_PTR(-EACCES);
 		set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
 		set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
-		cifs_get_tlink(newtlink);
+		refcount_set(&newtlink->tl_count, 1);
 
 		spin_lock(&cifs_sb->tlink_tree_lock);
 		/* was one inserted after previous search? */
@@ -4380,11 +4380,11 @@ cifs_prune_tlinks(struct work_struct *work)
 		tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
 
 		if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
-		    atomic_read(&tlink->tl_count) != 0 ||
+		    refcount_read(&tlink->tl_count) != 0 ||
 		    time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
 			continue;
 
-		cifs_get_tlink(tlink);
+		refcount_set(&tlink->tl_count, 1);
 		clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
 		rb_erase(tmp, root);
 
-- 
2.7.4

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

end of thread, other threads:[~2017-03-02 12:26 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-02 10:43 [PATCH 00/10] various fs subsystems refcounter conversions Elena Reshetova
2017-03-02 10:43 ` [PATCH 02/10] fs, cachefiles: convert cachefiles_object.usage from atomic_t to refcount_t Elena Reshetova
2017-03-02 10:43 ` [PATCH 03/10] fs, proc: convert proc_dir_entry.count " Elena Reshetova
2017-03-02 10:43 ` [PATCH 04/10] fs, nilfs: convert nilfs_root.count " Elena Reshetova
     [not found] ` <1488451397-3365-1-git-send-email-elena.reshetova-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2017-03-02 10:43   ` [PATCH 01/10] fs, kernfs: convert kernfs_node.count " Elena Reshetova
2017-03-02 10:43     ` Elena Reshetova
2017-03-02 10:43   ` [PATCH 05/10] fs, hfs: convert hfs_bnode.refcnt " Elena Reshetova
2017-03-02 10:43     ` Elena Reshetova
2017-03-02 10:43   ` [PATCH 07/10] fs, fscache: convert fscache_operation.usage " Elena Reshetova
2017-03-02 10:43     ` Elena Reshetova
2017-03-02 10:43   ` [PATCH 08/10] fs, fsnotify: convert fsnotify_group.refcnt " Elena Reshetova
2017-03-02 10:43     ` Elena Reshetova
2017-03-02 10:43 ` [PATCH 06/10] fs, fscache: convert fscache_cache_tag.usage " Elena Reshetova
2017-03-02 10:43 ` [PATCH 09/10] fs, fsnotify: convert fsnotify_mark.refcnt " Elena Reshetova
2017-03-02 10:43 ` [PATCH 10/10] fs, cifs: convert tcon_link.tl_count " Elena Reshetova
2017-03-02 10:43   ` 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.