Commit 4b9502e6 authored by Elena Reshetova's avatar Elena Reshetova Committed by Tejun Heo

kernel: convert css_set.refcount from atomic_t to refcount_t

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: default avatarElena Reshetova <elena.reshetova@intel.com>
Signed-off-by: default avatarHans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: default avatarKees Cook <keescook@chromium.org>
Signed-off-by: default avatarDavid Windsor <dwindsor@gmail.com>
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
parent 387ad967
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <linux/refcount.h>
#include <linux/percpu-refcount.h> #include <linux/percpu-refcount.h>
#include <linux/percpu-rwsem.h> #include <linux/percpu-rwsem.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
...@@ -156,7 +157,7 @@ struct css_set { ...@@ -156,7 +157,7 @@ struct css_set {
struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT]; struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
/* reference count */ /* reference count */
atomic_t refcount; refcount_t refcount;
/* the default cgroup associated with this css_set */ /* the default cgroup associated with this css_set */
struct cgroup *dfl_cgrp; struct cgroup *dfl_cgrp;
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <linux/kernfs.h> #include <linux/kernfs.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/refcount.h>
/* /*
* A cgroup can be associated with multiple css_sets as different tasks may * A cgroup can be associated with multiple css_sets as different tasks may
...@@ -134,7 +135,7 @@ static inline void put_css_set(struct css_set *cset) ...@@ -134,7 +135,7 @@ static inline void put_css_set(struct css_set *cset)
* can see it. Similar to atomic_dec_and_lock(), but for an * can see it. Similar to atomic_dec_and_lock(), but for an
* rwlock * rwlock
*/ */
if (atomic_add_unless(&cset->refcount, -1, 1)) if (refcount_dec_not_one(&cset->refcount))
return; return;
spin_lock_irqsave(&css_set_lock, flags); spin_lock_irqsave(&css_set_lock, flags);
...@@ -147,7 +148,7 @@ static inline void put_css_set(struct css_set *cset) ...@@ -147,7 +148,7 @@ static inline void put_css_set(struct css_set *cset)
*/ */
static inline void get_css_set(struct css_set *cset) static inline void get_css_set(struct css_set *cset)
{ {
atomic_inc(&cset->refcount); refcount_inc(&cset->refcount);
} }
bool cgroup_ssid_enabled(int ssid); bool cgroup_ssid_enabled(int ssid);
......
...@@ -346,7 +346,7 @@ static int cgroup_task_count(const struct cgroup *cgrp) ...@@ -346,7 +346,7 @@ static int cgroup_task_count(const struct cgroup *cgrp)
spin_lock_irq(&css_set_lock); spin_lock_irq(&css_set_lock);
list_for_each_entry(link, &cgrp->cset_links, cset_link) list_for_each_entry(link, &cgrp->cset_links, cset_link)
count += atomic_read(&link->cset->refcount); count += refcount_read(&link->cset->refcount);
spin_unlock_irq(&css_set_lock); spin_unlock_irq(&css_set_lock);
return count; return count;
} }
...@@ -1286,7 +1286,7 @@ static u64 current_css_set_refcount_read(struct cgroup_subsys_state *css, ...@@ -1286,7 +1286,7 @@ static u64 current_css_set_refcount_read(struct cgroup_subsys_state *css,
u64 count; u64 count;
rcu_read_lock(); rcu_read_lock();
count = atomic_read(&task_css_set(current)->refcount); count = refcount_read(&task_css_set(current)->refcount);
rcu_read_unlock(); rcu_read_unlock();
return count; return count;
} }
......
...@@ -554,7 +554,7 @@ EXPORT_SYMBOL_GPL(of_css); ...@@ -554,7 +554,7 @@ EXPORT_SYMBOL_GPL(of_css);
* haven't been created. * haven't been created.
*/ */
struct css_set init_css_set = { struct css_set init_css_set = {
.refcount = ATOMIC_INIT(1), .refcount = REFCOUNT_INIT(1),
.tasks = LIST_HEAD_INIT(init_css_set.tasks), .tasks = LIST_HEAD_INIT(init_css_set.tasks),
.mg_tasks = LIST_HEAD_INIT(init_css_set.mg_tasks), .mg_tasks = LIST_HEAD_INIT(init_css_set.mg_tasks),
.task_iters = LIST_HEAD_INIT(init_css_set.task_iters), .task_iters = LIST_HEAD_INIT(init_css_set.task_iters),
...@@ -724,7 +724,7 @@ void put_css_set_locked(struct css_set *cset) ...@@ -724,7 +724,7 @@ void put_css_set_locked(struct css_set *cset)
lockdep_assert_held(&css_set_lock); lockdep_assert_held(&css_set_lock);
if (!atomic_dec_and_test(&cset->refcount)) if (!refcount_dec_and_test(&cset->refcount))
return; return;
/* This css_set is dead. unlink it and release cgroup and css refs */ /* This css_set is dead. unlink it and release cgroup and css refs */
...@@ -977,7 +977,7 @@ static struct css_set *find_css_set(struct css_set *old_cset, ...@@ -977,7 +977,7 @@ static struct css_set *find_css_set(struct css_set *old_cset,
return NULL; return NULL;
} }
atomic_set(&cset->refcount, 1); refcount_set(&cset->refcount, 1);
INIT_LIST_HEAD(&cset->tasks); INIT_LIST_HEAD(&cset->tasks);
INIT_LIST_HEAD(&cset->mg_tasks); INIT_LIST_HEAD(&cset->mg_tasks);
INIT_LIST_HEAD(&cset->task_iters); INIT_LIST_HEAD(&cset->task_iters);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment