diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/cgroup.c | 33 | ||||
| -rw-r--r-- | kernel/sched/core.c | 18 | 
2 files changed, 48 insertions, 3 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index a7c9e6ddb97..1f533877386 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -2098,6 +2098,24 @@ out_free_group_list:  	return retval;  } +static int cgroup_allow_attach(struct cgroup *cgrp, struct cgroup_taskset *tset) +{ +	struct cgroup_subsys *ss; +	int ret; + +	for_each_subsys(cgrp->root, ss) { +		if (ss->allow_attach) { +			ret = ss->allow_attach(cgrp, tset); +			if (ret) +				return ret; +		} else { +			return -EACCES; +		} +	} + +	return 0; +} +  /*   * Find the task_struct of the task to attach by vpid and pass it along to the   * function to attach either it or all tasks in its threadgroup. Will lock @@ -2129,9 +2147,18 @@ retry_find_task:  		if (!uid_eq(cred->euid, GLOBAL_ROOT_UID) &&  		    !uid_eq(cred->euid, tcred->uid) &&  		    !uid_eq(cred->euid, tcred->suid)) { -			rcu_read_unlock(); -			ret = -EACCES; -			goto out_unlock_cgroup; +			/* +			 * if the default permission check fails, give each +			 * cgroup a chance to extend the permission check +			 */ +			struct cgroup_taskset tset = { }; +			tset.single.task = tsk; +			tset.single.cgrp = cgrp; +			ret = cgroup_allow_attach(cgrp, &tset); +			if (ret) { +				rcu_read_unlock(); +				goto out_unlock_cgroup; +			}  		}  	} else  		tsk = current; diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 5b582cabd31..014040fa3d2 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -7716,6 +7716,23 @@ static void cpu_cgroup_css_offline(struct cgroup *cgrp)  	sched_offline_group(tg);  } +static int +cpu_cgroup_allow_attach(struct cgroup *cgrp, struct cgroup_taskset *tset) +{ +	const struct cred *cred = current_cred(), *tcred; +	struct task_struct *task; + +	cgroup_taskset_for_each(task, cgrp, tset) { +		tcred = __task_cred(task); + +		if ((current != task) && !capable(CAP_SYS_NICE) && +		    cred->euid != tcred->uid && cred->euid != tcred->suid) +			return -EACCES; +	} + +	return 0; +} +  static int cpu_cgroup_can_attach(struct cgroup *cgrp,  				 struct cgroup_taskset *tset)  { @@ -8075,6 +8092,7 @@ struct cgroup_subsys cpu_cgroup_subsys = {  	.css_offline	= cpu_cgroup_css_offline,  	.can_attach	= cpu_cgroup_can_attach,  	.attach		= cpu_cgroup_attach, +	.allow_attach	= cpu_cgroup_allow_attach,  	.exit		= cpu_cgroup_exit,  	.subsys_id	= cpu_cgroup_subsys_id,  	.base_cftypes	= cpu_files,  |