On Fri 20-10-17 13:26:01, Elena Reshetova wrote: > 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@xxxxxxxxxxxx> > Reviewed-by: David Windsor <dwindsor@xxxxxxxxx> > Reviewed-by: Hans Liljestrand <ishkamiel@xxxxxxxxx> > Signed-off-by: Elena Reshetova <elena.reshetova@xxxxxxxxx> Thanks for the patch. I've added it to my tree. Honza > --- > 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 3235753..b7a4b6a 100644 > --- a/fs/notify/group.c > +++ b/fs/notify/group.c > @@ -107,7 +107,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); > } > > /* > @@ -115,7 +115,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); > } > > @@ -131,7 +131,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); > atomic_set(&group->user_waits, 0); > > diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h > index c6c6931..20a57ba 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 > @@ -135,7 +136,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 > -- Jan Kara <jack@xxxxxxxx> SUSE Labs, CR