Commit 0b732977 authored by Hou Tao's avatar Hou Tao Committed by Zheng Zengkai
Browse files

cgroup/files: use task_get_css() to get a valid css during dup_fd()



hulk inclusion
category: bugfix
bugzilla: 50779
CVE: NA

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

Process fork and cgroup migration can happen simultaneously, and
in the following case use-after-free of css_set is possible:

CPU 0: process fork    CPU 1: cgroup migration

dup_fd                 __cgroup1_procs_write(threadgroup=false)
  files_cgroup_assign
    // task A
    task_lock
    task_cgroup(current, files_cgrp_id)
      css_set = task_css_set_check()

 			 cgroup_migrate_execute
  			   files_cgroup_can_attach
			   css_set_move_task
			     put_css_set_locked()
  			   files_cgroup_attach
			     // task B which is in the same
			     // thread group as task A
			     task_lock
			 cgroup_migrate_finish
			   // the css_set will be freed
			   put_css_set_locked()

      // use-after-free
      css_set->subsys[files_cgrp_id]

Fix it by using task_get_css() instead to get a valid css.

Fixes: 52cc1eccf6de ("cgroups: Resource controller for open files")
Signed-off-by: default avatarHou Tao <houtao1@huawei.com>
Reviewed-by: default avatarluojiajun <luojiajun3@huawei.com>
Signed-off-by: default avatarYang Yingliang <yangyingliang@huawei.com>

Signed-off-by: default avatarLu Jialin <lujialin4@huawei.com>
Reviewed-by: default avatarXiu Jianfeng <xiujianfeng@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parent 87056bf2
Loading
Loading
Loading
Loading
+5 −7
Original line number Diff line number Diff line
@@ -293,18 +293,16 @@ struct cgroup_subsys files_cgrp_subsys = {
	.dfl_cftypes = files,
};

/*
 * It could race against cgroup migration of current task, and
 * using task_get_css() to get a valid css.
 */
void files_cgroup_assign(struct files_struct *files)
{
	struct task_struct *tsk = current;
	struct cgroup_subsys_state *css;
	struct cgroup *cgrp;

	task_lock(tsk);
	cgrp = task_cgroup(tsk, files_cgrp_id);
	css = cgroup_subsys_state(cgrp, files_cgrp_id);
	css_get(css);
	css = task_get_css(current, files_cgrp_id);
	files->files_cgroup = container_of(css, struct files_cgroup, css);
	task_unlock(tsk);
}

void files_cgroup_remove(struct files_struct *files)
+0 −6
Original line number Diff line number Diff line
@@ -432,12 +432,6 @@ static inline void cgroup_put(struct cgroup *cgrp)
	css_put(&cgrp->self);
}

static inline struct cgroup_subsys_state *cgroup_subsys_state(
	struct cgroup *cgrp, int subsys_id)
{
	return cgrp->subsys[subsys_id];
}

/**
 * task_css_set_check - obtain a task's css_set with extra access conditions
 * @task: the task to obtain css_set for