From d30511d1f6f091395dd704bd78c5f2d7b04a59df Mon Sep 17 00:00:00 2001
From: ZhangPeng <zhangpeng362@huawei.com>
Date: Tue, 24 Dec 2024 16:48:18 +0800
Subject: [PATCH 18/23] Revert "Revert "cgroup: fix uaf when proc_cpuset_show""

hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/IBDFAV

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

This reverts commit e52b70344587721e723fc748454520328e120484.

Signed-off-by: ZhangPeng <zhangpeng362@huawei.com>
---
 kernel/cgroup/cpuset.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 140dfb5ad3fc..2c9e50f09fc1 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -5185,6 +5185,7 @@ int proc_cpuset_show(struct seq_file *m, struct pid_namespace *ns,
 	char *buf;
 	struct cgroup_subsys_state *css;
 	int retval;
+	struct cgroup *root_cgroup = NULL;
 
 	retval = -ENOMEM;
 	buf = kmalloc(PATH_MAX, GFP_KERNEL);
@@ -5192,9 +5193,32 @@ int proc_cpuset_show(struct seq_file *m, struct pid_namespace *ns,
 		goto out;
 
 	css = task_get_css(tsk, cpuset_cgrp_id);
+	rcu_read_lock();
+	/*
+	 * When the cpuset subsystem is mounted on the legacy hierarchy,
+	 * the top_cpuset.css->cgroup does not hold a reference count of
+	 * cgroup_root.cgroup. This makes accessing css->cgroup very
+	 * dangerous because when the cpuset subsystem is remounted to the
+	 * default hierarchy, the cgroup_root.cgroup that css->cgroup points
+	 * to will be released, leading to a UAF issue. To avoid this problem,
+	 * get the reference count of top_cpuset.css->cgroup first.
+	 *
+	 * This is ugly!!
+	 */
+	if (css == &top_cpuset.css) {
+		root_cgroup = css->cgroup;
+		if (!css_tryget_online(&root_cgroup->self)) {
+			rcu_read_unlock();
+			retval = -EBUSY;
+			goto out_free;
+		}
+	}
+	rcu_read_unlock();
 	retval = cgroup_path_ns(css->cgroup, buf, PATH_MAX,
 				current->nsproxy->cgroup_ns);
 	css_put(css);
+	if (root_cgroup)
+		css_put(&root_cgroup->self);
 	if (retval >= PATH_MAX)
 		retval = -ENAMETOOLONG;
 	if (retval < 0)
-- 
2.25.1

