* [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 02/10] fs, cachefiles: convert cachefiles_object.usage " Elena Reshetova
` (8 subsequent siblings)
9 siblings, 0 replies; 11+ 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] 11+ 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 ` [PATCH 01/10] fs, kernfs: convert kernfs_node.count from atomic_t to refcount_t 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
` (7 subsequent siblings)
9 siblings, 0 replies; 11+ 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] 11+ 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 01/10] fs, kernfs: convert kernfs_node.count from atomic_t to refcount_t Elena Reshetova
2017-03-02 10:43 ` [PATCH 02/10] fs, cachefiles: convert cachefiles_object.usage " 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
` (6 subsequent siblings)
9 siblings, 0 replies; 11+ 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] 11+ 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
` (2 preceding siblings ...)
2017-03-02 10:43 ` [PATCH 03/10] fs, proc: convert proc_dir_entry.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
` (5 subsequent siblings)
9 siblings, 0 replies; 11+ 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] 11+ 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
` (3 preceding siblings ...)
2017-03-02 10:43 ` [PATCH 04/10] fs, nilfs: convert nilfs_root.count " 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
` (4 subsequent siblings)
9 siblings, 0 replies; 11+ 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] 11+ 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
` (4 preceding siblings ...)
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
` (3 subsequent siblings)
9 siblings, 0 replies; 11+ 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] 11+ 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
` (5 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 ` [PATCH 08/10] fs, fsnotify: convert fsnotify_group.refcnt " Elena Reshetova
` (2 subsequent siblings)
9 siblings, 0 replies; 11+ 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] 11+ 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
` (6 preceding siblings ...)
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 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
9 siblings, 0 replies; 11+ 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] 11+ 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
` (7 preceding siblings ...)
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 10/10] fs, cifs: convert tcon_link.tl_count " Elena Reshetova
9 siblings, 0 replies; 11+ 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] 11+ 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
` (8 preceding siblings ...)
2017-03-02 10:43 ` [PATCH 09/10] fs, fsnotify: convert fsnotify_mark.refcnt " Elena Reshetova
@ 2017-03-02 10:43 ` Elena Reshetova
9 siblings, 0 replies; 11+ 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] 11+ messages in thread