On 2018-07-03 22:01:40 [+0200], To linux-kernel@vger.kernel.org wrote: > 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.
Ingo, Andrew: who of you two feels most comfortable to apply this one (and 6/6 of this series, both `userns')? If none, who would you suggest? > Cc: Andrew Morton <a...@linux-foundation.org> > Suggested-by: Peter Zijlstra <pet...@infradead.org> > Acked-by: Peter Zijlstra (Intel) <pet...@infradead.org> > Signed-off-by: Sebastian Andrzej Siewior <bige...@linutronix.de> > --- > include/linux/sched/user.h | 5 +++-- > kernel/user.c | 8 ++++---- > 2 files changed, 7 insertions(+), 6 deletions(-) > > diff --git a/include/linux/sched/user.h b/include/linux/sched/user.h > index 96fe289c4c6e..39ad98c09c58 100644 > --- a/include/linux/sched/user.h > +++ b/include/linux/sched/user.h > @@ -4,6 +4,7 @@ > > #include <linux/uidgid.h> > #include <linux/atomic.h> > +#include <linux/refcount.h> > #include <linux/ratelimit.h> > > struct key; > @@ -12,7 +13,7 @@ struct key; > * Some day this will be a full-fledged user tracking system.. > */ > struct user_struct { > - atomic_t __count; /* reference count */ > + refcount_t __count; /* reference count */ > atomic_t processes; /* How many processes does this user have? */ > atomic_t sigpending; /* How many pending signals does this user > have? */ > #ifdef CONFIG_FANOTIFY > @@ -59,7 +60,7 @@ extern struct user_struct root_user; > extern struct user_struct * alloc_uid(kuid_t); > static inline struct user_struct *get_uid(struct user_struct *u) > { > - atomic_inc(&u->__count); > + refcount_inc(&u->__count); > return u; > } > extern void free_uid(struct user_struct *); > diff --git a/kernel/user.c b/kernel/user.c > index 36288d840675..5f65ef195259 100644 > --- a/kernel/user.c > +++ b/kernel/user.c > @@ -96,7 +96,7 @@ static DEFINE_SPINLOCK(uidhash_lock); > > /* root_user.__count is 1, for init task cred */ > struct user_struct root_user = { > - .__count = ATOMIC_INIT(1), > + .__count = REFCOUNT_INIT(1), > .processes = ATOMIC_INIT(1), > .sigpending = ATOMIC_INIT(0), > .locked_shm = 0, > @@ -123,7 +123,7 @@ static struct user_struct *uid_hash_find(kuid_t uid, > struct hlist_head *hashent) > > hlist_for_each_entry(user, hashent, uidhash_node) { > if (uid_eq(user->uid, uid)) { > - atomic_inc(&user->__count); > + refcount_inc(&user->__count); > return user; > } > } > @@ -170,7 +170,7 @@ void free_uid(struct user_struct *up) > return; > > local_irq_save(flags); > - if (atomic_dec_and_lock(&up->__count, &uidhash_lock)) > + if (refcount_dec_and_lock(&up->__count, &uidhash_lock)) > free_user(up, flags); > else > local_irq_restore(flags); > @@ -191,7 +191,7 @@ struct user_struct *alloc_uid(kuid_t uid) > goto out_unlock; > > new->uid = uid; > - atomic_set(&new->__count, 1); > + refcount_set(&new->__count, 1); > ratelimit_state_init(&new->ratelimit, HZ, 100); > ratelimit_set_flags(&new->ratelimit, RATELIMIT_MSG_ON_RELEASE); > > -- > 2.18.0 Sebastian