kernel: convert cgroup_namespace.count from atomic_t to refcount_t
authorElena Reshetova <elena.reshetova@intel.com>
Mon, 20 Feb 2017 10:19:00 +0000 (12:19 +0200)
committerTejun Heo <tj@kernel.org>
Mon, 6 Mar 2017 19:55:22 +0000 (14:55 -0500)
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 <ishkamiel@gmail.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: David Windsor <dwindsor@gmail.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
include/linux/cgroup.h
kernel/cgroup/cgroup.c
kernel/cgroup/namespace.c

index f6b43fbb141c9ad03c1e05880e8c2228743d076e..44129793c7b8be92f92b5ffd35b43dbadb8c1988 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/ns_common.h>
 #include <linux/nsproxy.h>
 #include <linux/user_namespace.h>
+#include <linux/refcount.h>
 
 #include <linux/cgroup-defs.h>
 
@@ -640,7 +641,7 @@ static inline void cgroup_sk_free(struct sock_cgroup_data *skcd) {}
 #endif /* CONFIG_CGROUP_DATA */
 
 struct cgroup_namespace {
-       atomic_t                count;
+       refcount_t              count;
        struct ns_common        ns;
        struct user_namespace   *user_ns;
        struct ucounts          *ucounts;
@@ -675,12 +676,12 @@ copy_cgroup_ns(unsigned long flags, struct user_namespace *user_ns,
 static inline void get_cgroup_ns(struct cgroup_namespace *ns)
 {
        if (ns)
-               atomic_inc(&ns->count);
+               refcount_inc(&ns->count);
 }
 
 static inline void put_cgroup_ns(struct cgroup_namespace *ns)
 {
-       if (ns && atomic_dec_and_test(&ns->count))
+       if (ns && refcount_dec_and_test(&ns->count))
                free_cgroup_ns(ns);
 }
 
index 0125589c742841ddbff14639c1ded5e0590b00b4..8ee78688e36dd6004f100556f78d38cf16277ef1 100644 (file)
@@ -189,7 +189,7 @@ static u16 have_canfork_callback __read_mostly;
 
 /* cgroup namespace for init task */
 struct cgroup_namespace init_cgroup_ns = {
-       .count          = { .counter = 2, },
+       .count          = REFCOUNT_INIT(2),
        .user_ns        = &init_user_ns,
        .ns.ops         = &cgroupns_operations,
        .ns.inum        = PROC_CGROUP_INIT_INO,
index 96d38dab6fb2f7fdad9e64236572562c9c43ff36..66129eb4371d124f97c2a3233549be3673bd93ca 100644 (file)
@@ -31,7 +31,7 @@ static struct cgroup_namespace *alloc_cgroup_ns(void)
                kfree(new_ns);
                return ERR_PTR(ret);
        }
-       atomic_set(&new_ns->count, 1);
+       refcount_set(&new_ns->count, 1);
        new_ns->ns.ops = &cgroupns_operations;
        return new_ns;
 }