diff options
author | Elena Reshetova <elena.reshetova@intel.com> | 2017-10-20 06:26:01 -0400 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2017-10-31 12:54:56 -0400 |
commit | 7761daa6a1599fa5479b8da367470f632a1927e0 (patch) | |
tree | f1ed23c310e76b1a78447268f9d16c153bb32721 | |
parent | 9cf90cef362d44b2f3fcdb7d0694849a6308b620 (diff) |
fsnotify: convert fsnotify_group.refcnt 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 fsnotify_group.refcnt is used as pure reference counter.
Convert it to refcount_t and fix up the operations.
Suggested-by: Kees Cook <keescook@chromium.org>
Reviewed-by: David Windsor <dwindsor@gmail.com>
Reviewed-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
Signed-off-by: Jan Kara <jack@suse.cz>
-rw-r--r-- | fs/notify/group.c | 6 | ||||
-rw-r--r-- | 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 32357534de18..b7a4b6a69efa 100644 --- a/fs/notify/group.c +++ b/fs/notify/group.c | |||
@@ -107,7 +107,7 @@ void fsnotify_destroy_group(struct fsnotify_group *group) | |||
107 | */ | 107 | */ |
108 | void fsnotify_get_group(struct fsnotify_group *group) | 108 | void fsnotify_get_group(struct fsnotify_group *group) |
109 | { | 109 | { |
110 | atomic_inc(&group->refcnt); | 110 | refcount_inc(&group->refcnt); |
111 | } | 111 | } |
112 | 112 | ||
113 | /* | 113 | /* |
@@ -115,7 +115,7 @@ void fsnotify_get_group(struct fsnotify_group *group) | |||
115 | */ | 115 | */ |
116 | void fsnotify_put_group(struct fsnotify_group *group) | 116 | void fsnotify_put_group(struct fsnotify_group *group) |
117 | { | 117 | { |
118 | if (atomic_dec_and_test(&group->refcnt)) | 118 | if (refcount_dec_and_test(&group->refcnt)) |
119 | fsnotify_final_destroy_group(group); | 119 | fsnotify_final_destroy_group(group); |
120 | } | 120 | } |
121 | 121 | ||
@@ -131,7 +131,7 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops) | |||
131 | return ERR_PTR(-ENOMEM); | 131 | return ERR_PTR(-ENOMEM); |
132 | 132 | ||
133 | /* set to 0 when there a no external references to this group */ | 133 | /* set to 0 when there a no external references to this group */ |
134 | atomic_set(&group->refcnt, 1); | 134 | refcount_set(&group->refcnt, 1); |
135 | atomic_set(&group->num_marks, 0); | 135 | atomic_set(&group->num_marks, 0); |
136 | atomic_set(&group->user_waits, 0); | 136 | atomic_set(&group->user_waits, 0); |
137 | 137 | ||
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index c6c69318752b..20a57bac38f2 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
18 | #include <linux/atomic.h> | 18 | #include <linux/atomic.h> |
19 | #include <linux/user_namespace.h> | 19 | #include <linux/user_namespace.h> |
20 | #include <linux/refcount.h> | ||
20 | 21 | ||
21 | /* | 22 | /* |
22 | * IN_* from inotfy.h lines up EXACTLY with FS_*, this is so we can easily | 23 | * IN_* from inotfy.h lines up EXACTLY with FS_*, this is so we can easily |
@@ -135,7 +136,7 @@ struct fsnotify_group { | |||
135 | * inotify_init() and the refcnt will hit 0 only when that fd has been | 136 | * inotify_init() and the refcnt will hit 0 only when that fd has been |
136 | * closed. | 137 | * closed. |
137 | */ | 138 | */ |
138 | atomic_t refcnt; /* things with interest in this group */ | 139 | refcount_t refcnt; /* things with interest in this group */ |
139 | 140 | ||
140 | const struct fsnotify_ops *ops; /* how this group handles things */ | 141 | const struct fsnotify_ops *ops; /* how this group handles things */ |
141 | 142 | ||