84 lines
2.7 KiB
Diff
84 lines
2.7 KiB
Diff
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
|
Date: Mon, 7 May 2018 17:09:42 +0200
|
|
Subject: [PATCH] userns: use refcount_t for reference counting instead
|
|
atomic_t
|
|
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.18/older/patches-4.18.5-rt3.tar.xz
|
|
|
|
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.
|
|
|
|
Suggested-by: Peter Zijlstra <peterz@infradead.org>
|
|
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
|
---
|
|
include/linux/sched/user.h | 5 +++--
|
|
kernel/user.c | 8 ++++----
|
|
2 files changed, 7 insertions(+), 6 deletions(-)
|
|
|
|
--- 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 *);
|
|
--- 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
|
|
|
|
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);
|
|
|