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

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
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include <linux/wait.h>
#include <linux/mutex.h>
#include <linux/rcupdate.h>
#include <linux/refcount.h>
#include <linux/percpu-refcount.h>
#include <linux/percpu-rwsem.h>
#include <linux/workqueue.h>
@@ -156,7 +157,7 @@ struct css_set {
	struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];

	/* reference count */
	atomic_t refcount;
	refcount_t refcount;

	/* the default cgroup associated with this css_set */
	struct cgroup *dfl_cgrp;
+3 −2
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
#include <linux/kernfs.h>
#include <linux/workqueue.h>
#include <linux/list.h>
#include <linux/refcount.h>

/*
 * 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)
	 * can see it. Similar to atomic_dec_and_lock(), but for an
	 * rwlock
	 */
	if (atomic_add_unless(&cset->refcount, -1, 1))
	if (refcount_dec_not_one(&cset->refcount))
		return;

	spin_lock_irqsave(&css_set_lock, flags);
@@ -147,7 +148,7 @@ static inline void put_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);
+2 −2
Original line number Diff line number Diff line
@@ -346,7 +346,7 @@ static int cgroup_task_count(const struct cgroup *cgrp)

	spin_lock_irq(&css_set_lock);
	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);
	return count;
}
@@ -1286,7 +1286,7 @@ static u64 current_css_set_refcount_read(struct cgroup_subsys_state *css,
	u64 count;

	rcu_read_lock();
	count = atomic_read(&task_css_set(current)->refcount);
	count = refcount_read(&task_css_set(current)->refcount);
	rcu_read_unlock();
	return count;
}
+3 −3
Original line number Diff line number Diff line
@@ -554,7 +554,7 @@ EXPORT_SYMBOL_GPL(of_css);
 * haven't been created.
 */
struct css_set init_css_set = {
	.refcount		= ATOMIC_INIT(1),
	.refcount		= REFCOUNT_INIT(1),
	.tasks			= LIST_HEAD_INIT(init_css_set.tasks),
	.mg_tasks		= LIST_HEAD_INIT(init_css_set.mg_tasks),
	.task_iters		= LIST_HEAD_INIT(init_css_set.task_iters),
@@ -724,7 +724,7 @@ void put_css_set_locked(struct css_set *cset)

	lockdep_assert_held(&css_set_lock);

	if (!atomic_dec_and_test(&cset->refcount))
	if (!refcount_dec_and_test(&cset->refcount))
		return;

	/* 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,
		return NULL;
	}

	atomic_set(&cset->refcount, 1);
	refcount_set(&cset->refcount, 1);
	INIT_LIST_HEAD(&cset->tasks);
	INIT_LIST_HEAD(&cset->mg_tasks);
	INIT_LIST_HEAD(&cset->task_iters);