From 2996235545433ce25e917af11f4985d7b6880764 Mon Sep 17 00:00:00 2001 From: Waiman Long Date: Mon, 24 Jun 2024 19:53:32 -0400 Subject: [PATCH v2] cgroup/cpuset: Prevent UAF in proc_cpuset_show() The unmounting of a cpuset cgroup filesystem will lead to a call to cpuset_bind() to rebind it back to &cgrp_dfl_root.cgrp via the following call sequence. cgroup_destroy_root() --> rebind_subsystems() --> cpuset_bind() The call to cpuset_bind() is done after setting top_cpuset.css.cgroup to the &cgrp_dfl_root.cgrp. The allocated v1 cgroup root will be freed after the completion of the cpuset_bind() call and other miscellaneous cleanups. Fix this potential UAF problem by putting the access and parsing of top_cpuset.css.cgroup under cpuset_mutex to synchronize with cpuset_bind() of the unmount operation. If the cpuset_mutex is acquired after cpuset_bind(), top_cpuset.css.cgroup is guaranteed to point to cgrp_dfl_root.cgrp. If it is acquired before cpuset_bind(), the allocated v1 cgroup root cannot be freed until after the cpuset_mutex is released. A similar UAF problem in proc_cpuset_show() had been reported before in [1]. [1] https://syzkaller.appspot.com/bug?extid=9b1ff7be974a403aa4cd Reported-by: Chen Ridong Closes: https://syzkaller.appspot.com/bug?extid=9b1ff7be974a403aa4cd Signed-off-by: Waiman Long --- kernel/cgroup/cpuset.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c index c12b9fdb22a4..953150a06d81 100644 --- a/kernel/cgroup/cpuset.c +++ b/kernel/cgroup/cpuset.c @@ -5051,10 +5051,17 @@ int proc_cpuset_show(struct seq_file *m, struct pid_namespace *ns, if (!buf) goto out; + /* + * Access to css->cgroup is guarded by cpuset_mutex to synchronize + * with the cpuset_bind() call of a racing v1 cgroup root unmount + * operation to prevent UAF. + */ + mutex_lock(&cpuset_mutex); css = task_get_css(tsk, cpuset_cgrp_id); retval = cgroup_path_ns(css->cgroup, buf, PATH_MAX, current->nsproxy->cgroup_ns); css_put(css); + mutex_unlock(&cpuset_mutex); if (retval == -E2BIG) retval = -ENAMETOOLONG; if (retval < 0) -- 2.39.3