From a8453b177e574bc4dee3ea70be532ac322fb2e40 Mon Sep 17 00:00:00 2001 From: Hou Tao Date: Sun, 5 May 2019 16:51:35 +0800 Subject: [PATCH] cgroup/files: use task_get_css() to get a valid css during dup_fd() euler inclusion category: bugfix bugzilla: 14007 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: Hou Tao Reviewed-by: luojiajun Signed-off-by: Yang Yingliang --- fs/filescontrol.c | 12 +++++------- include/linux/cgroup.h | 6 ------ 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/fs/filescontrol.c b/fs/filescontrol.c index 44ad9ef44e20..1d2d29127fd4 100644 --- a/fs/filescontrol.c +++ b/fs/filescontrol.c @@ -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) diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index f3e50549e41c..ca51b2c15bcc 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -416,12 +416,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 -- GitLab