[PATCH 13/19] kernel: convert group_info.usage from atomic_t to refcount_t
From: Elena Reshetova <elena.reshetova@intel.com>
Date: 2017-02-20 10:19:02
Also in:
linux-fsdevel, lkml
Subsystem:
credentials, the rest · Maintainers:
Paul Moore, Linus Torvalds
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. Signed-off-by: Elena Reshetova <elena.reshetova@intel.com> Signed-off-by: Hans Liljestrand <redacted> Signed-off-by: Kees Cook <redacted> Signed-off-by: David Windsor <redacted> --- include/linux/cred.h | 7 ++++--- kernel/cred.c | 2 +- kernel/groups.c | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/include/linux/cred.h b/include/linux/cred.h
index f0e70a1..c837f2d 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h@@ -17,6 +17,7 @@ #include <linux/key.h> #include <linux/selinux.h> #include <linux/atomic.h> +#include <linux/refcount.h> #include <linux/uidgid.h> struct user_struct;
@@ -27,7 +28,7 @@ struct inode; * COW Supplementary groups list */ struct group_info { - atomic_t usage; + refcount_t usage; int ngroups; kgid_t gid[0]; };
@@ -43,7 +44,7 @@ struct group_info { */ static inline struct group_info *get_group_info(struct group_info *gi) { - atomic_inc(&gi->usage); + refcount_inc(&gi->usage); return gi; }
@@ -53,7 +54,7 @@ static inline struct group_info *get_group_info(struct group_info *gi) */ #define put_group_info(group_info) \ do { \ - if (atomic_dec_and_test(&(group_info)->usage)) \ + if (refcount_dec_and_test(&(group_info)->usage)) \ groups_free(group_info); \ } while (0)
diff --git a/kernel/cred.c b/kernel/cred.c
index 5f264fb..3afeea6 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c@@ -35,7 +35,7 @@ do { \ static struct kmem_cache *cred_jar; /* init to 2 - one for init_task, one to ensure it is never freed */ -struct group_info init_groups = { .usage = ATOMIC_INIT(2) }; +struct group_info init_groups = { .usage = REFCOUNT_INIT(2) }; /* * The initial credentials for the initial task
diff --git a/kernel/groups.c b/kernel/groups.c
index 8dd7a61..455267f 100644
--- a/kernel/groups.c
+++ b/kernel/groups.c@@ -22,7 +22,7 @@ struct group_info *groups_alloc(int gidsetsize) if (!gi) return NULL; - atomic_set(&gi->usage, 1); + refcount_set(&gi->usage, 1); gi->ngroups = gidsetsize; return gi; }
--
2.7.4