diff options
author | Elena Reshetova <elena.reshetova@intel.com> | 2017-11-17 18:29:39 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-17 19:10:03 -0500 |
commit | d4f0284a5969fd7809ec8df710eb10598b701638 (patch) | |
tree | a38d9b3bbf2722d859a374dbe2cf06a97fa13273 /fs/nilfs2 | |
parent | 31ccb1f7ba3cfe29631587d451cf5bb8ab593550 (diff) |
fs, nilfs: convert nilfs_root.count from atomic_t to refcount_t
atomic_t variables are currently used to implement reference counters
with the following properties:
- counter is initialized to 1 using atomic_set()
- a resource is freed upon counter reaching zero
- once counter reaches zero, its further
increments aren't allowed
- counter schema uses basic atomic operations
(set, inc, inc_not_zero, dec_and_test, etc.)
Such atomic variables should be converted to a newly provided refcount_t
type and API that prevents accidental counter overflows and underflows.
This is important since overflows and underflows can lead to
use-after-free situation and be exploitable.
The variable nilfs_root.count is used as pure reference counter.
Convert it to refcount_t and fix up the operations.
Link: http://lkml.kernel.org/r/1509367935-3086-3-git-send-email-konishi.ryusuke@lab.ntt.co.jp
Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Suggested-by: Kees Cook <keescook@chromium.org>
Reviewed-by: David Windsor <dwindsor@gmail.com>
Reviewed-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/nilfs2')
-rw-r--r-- | fs/nilfs2/the_nilfs.c | 8 | ||||
-rw-r--r-- | 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 2dd75bf619ad..afebb5067cec 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) | |||
737 | } else if (cno > root->cno) { | 737 | } else if (cno > root->cno) { |
738 | n = n->rb_right; | 738 | n = n->rb_right; |
739 | } else { | 739 | } else { |
740 | atomic_inc(&root->count); | 740 | refcount_inc(&root->count); |
741 | spin_unlock(&nilfs->ns_cptree_lock); | 741 | spin_unlock(&nilfs->ns_cptree_lock); |
742 | return root; | 742 | return root; |
743 | } | 743 | } |
@@ -776,7 +776,7 @@ nilfs_find_or_create_root(struct the_nilfs *nilfs, __u64 cno) | |||
776 | } else if (cno > root->cno) { | 776 | } else if (cno > root->cno) { |
777 | p = &(*p)->rb_right; | 777 | p = &(*p)->rb_right; |
778 | } else { | 778 | } else { |
779 | atomic_inc(&root->count); | 779 | refcount_inc(&root->count); |
780 | spin_unlock(&nilfs->ns_cptree_lock); | 780 | spin_unlock(&nilfs->ns_cptree_lock); |
781 | kfree(new); | 781 | kfree(new); |
782 | return root; | 782 | return root; |
@@ -786,7 +786,7 @@ nilfs_find_or_create_root(struct the_nilfs *nilfs, __u64 cno) | |||
786 | new->cno = cno; | 786 | new->cno = cno; |
787 | new->ifile = NULL; | 787 | new->ifile = NULL; |
788 | new->nilfs = nilfs; | 788 | new->nilfs = nilfs; |
789 | atomic_set(&new->count, 1); | 789 | refcount_set(&new->count, 1); |
790 | atomic64_set(&new->inodes_count, 0); | 790 | atomic64_set(&new->inodes_count, 0); |
791 | atomic64_set(&new->blocks_count, 0); | 791 | atomic64_set(&new->blocks_count, 0); |
792 | 792 | ||
@@ -806,7 +806,7 @@ nilfs_find_or_create_root(struct the_nilfs *nilfs, __u64 cno) | |||
806 | 806 | ||
807 | void nilfs_put_root(struct nilfs_root *root) | 807 | void nilfs_put_root(struct nilfs_root *root) |
808 | { | 808 | { |
809 | if (atomic_dec_and_test(&root->count)) { | 809 | if (refcount_dec_and_test(&root->count)) { |
810 | struct the_nilfs *nilfs = root->nilfs; | 810 | struct the_nilfs *nilfs = root->nilfs; |
811 | 811 | ||
812 | nilfs_sysfs_delete_snapshot_group(root); | 812 | nilfs_sysfs_delete_snapshot_group(root); |
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index b305c6f033e7..883d732b0259 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/blkdev.h> | 27 | #include <linux/blkdev.h> |
28 | #include <linux/backing-dev.h> | 28 | #include <linux/backing-dev.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/refcount.h> | ||
30 | 31 | ||
31 | struct nilfs_sc_info; | 32 | struct nilfs_sc_info; |
32 | struct nilfs_sysfs_dev_subgroups; | 33 | struct nilfs_sysfs_dev_subgroups; |
@@ -246,7 +247,7 @@ struct nilfs_root { | |||
246 | __u64 cno; | 247 | __u64 cno; |
247 | struct rb_node rb_node; | 248 | struct rb_node rb_node; |
248 | 249 | ||
249 | atomic_t count; | 250 | refcount_t count; |
250 | struct the_nilfs *nilfs; | 251 | struct the_nilfs *nilfs; |
251 | struct inode *ifile; | 252 | struct inode *ifile; |
252 | 253 | ||
@@ -299,7 +300,7 @@ void nilfs_swap_super_block(struct the_nilfs *); | |||
299 | 300 | ||
300 | static inline void nilfs_get_root(struct nilfs_root *root) | 301 | static inline void nilfs_get_root(struct nilfs_root *root) |
301 | { | 302 | { |
302 | atomic_inc(&root->count); | 303 | refcount_inc(&root->count); |
303 | } | 304 | } |
304 | 305 | ||
305 | static inline int nilfs_valid_fs(struct the_nilfs *nilfs) | 306 | static inline int nilfs_valid_fs(struct the_nilfs *nilfs) |