Commit 110e3f25 authored by Liu Shixin's avatar Liu Shixin
Browse files

dhugetlb: use rcu lock to protect hpool

hulk inclusion
category: bugfix
bugzilla: 46904, https://gitee.com/openeuler/kernel/issues/IA5JXN



--------------------------------

In freeing process, set memcg->hpool or dpool_global_hpool to NULL and
then freeing it. To avoid UAF problem of hpool, we have to make sure the
users that already hold pointer to hpool don't use the pointer after
freeing hpool. The freeing of hpool should block until make sure all such
users don't use hpool. Since anyone who want to use hpool have to
increase its refcount at first. Use rcu_read_lock() and synchronize_rcu()
to guarantee all such users failed to get hpool before freeing hpool.

Fixes: 0bc0d0d5 ("dhugetlb: backport dynamic hugetlb feature")
Signed-off-by: default avatarLiu Shixin <liushixin2@huawei.com>
parent 745a3c56
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -3360,6 +3360,7 @@ void dhugetlb_pool_put(struct dhugetlb_pool *hpool)

	if (atomic_dec_and_test(&hpool->refcnt)) {
		css_put(&hpool->attach_memcg->css);
		synchronize_rcu();
		kfree(hpool);
	}
}
@@ -3500,9 +3501,14 @@ struct dhugetlb_pool *get_dhugetlb_pool_from_task(struct task_struct *tsk)

	rcu_read_lock();
	memcg = mem_cgroup_from_task(tsk);
	if (!memcg || !css_tryget(&memcg->css)) {
		rcu_read_unlock();
		return NULL;
	}
	rcu_read_unlock();

	hpool = get_dhugetlb_pool_from_memcg(memcg);
	css_put(&memcg->css);

	return hpool;
}
+8 −3
Original line number Diff line number Diff line
@@ -4701,14 +4701,19 @@ static ssize_t memcg_write_event_control(struct kernfs_open_file *of,
struct dhugetlb_pool *get_dhugetlb_pool_from_memcg(struct mem_cgroup *memcg)
{
	struct mem_cgroup_extension *memcg_ext;
	struct dhugetlb_pool *hpool;

	if (!memcg)
		return NULL;

	rcu_read_lock();
	memcg_ext = container_of(memcg, struct mem_cgroup_extension, memcg);
	if (dhugetlb_pool_get(memcg_ext->hpool))
		return memcg_ext->hpool;
	return NULL;
	hpool = memcg_ext->hpool;
	if (!dhugetlb_pool_get(hpool))
		hpool = NULL;
	rcu_read_unlock();

	return hpool;
}

static void set_dhugetlb_pool_to_memcg(struct mem_cgroup *memcg,