cgroup/cpuset: Expand the scope of cpuset_can_attach_check()

Expand the scope of cpuset_can_attach_check() by including the setting
of setsched flag inside cpuset_can_attach_check() with the new @oldcs
and @psetsched argument. As cpuset_can_attach_check() is also called
from cpuset_can_fork(), set the new arguments to NULL from that caller.

Signed-off-by: Waiman Long <longman@redhat.com>
Reviewed-by: Ridong Chen <ridong.chen@linux.dev>
Signed-off-by: Michal Koutný <mkoutny@suse.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
Waiman Long 2026-07-02 17:47:52 -04:00 committed by Tejun Heo
parent e165f243fe
commit 74eda6ea70

View File

@ -3022,12 +3022,39 @@ static int update_prstate(struct cpuset *cs, int new_prs)
* For v1, cpus_allowed and mems_allowed can't be empty.
* For v2, effective_cpus can't be empty.
* Note that in v1, effective_cpus = cpus_allowed.
*
* Also set the boolean flag passed in by @psetsched depending on if
* security_task_setscheduler() call is needed and @oldcs is not NULL.
*/
static int cpuset_can_attach_check(struct cpuset *cs)
static int cpuset_can_attach_check(struct cpuset *cs, struct cpuset *oldcs,
bool *psetsched)
{
if (cpumask_empty(cs->effective_cpus) ||
(!is_in_v2_mode() && nodes_empty(cs->mems_allowed)))
return -ENOSPC;
if (!oldcs)
return 0;
/*
* Skip rights over task setsched check in v2 when nothing changes,
* migration permission derives from hierarchy ownership in
* cgroup_procs_write_permission()).
*/
*psetsched = !cpuset_v2() ||
!cpumask_equal(cs->effective_cpus, oldcs->effective_cpus) ||
!nodes_equal(cs->effective_mems, oldcs->effective_mems);
/*
* A v1 cpuset with tasks will have no CPU left only when CPU hotplug
* brings the last online CPU offline as users are not allowed to empty
* cpuset.cpus when there are active tasks inside. When that happens,
* we should allow tasks to migrate out without security check to make
* sure they will be able to run after migration.
*/
if (!is_in_v2_mode() && cpumask_empty(oldcs->effective_cpus))
*psetsched = false;
return 0;
}
@ -3074,29 +3101,10 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
mutex_lock(&cpuset_mutex);
/* Check to see if task is allowed in the cpuset */
ret = cpuset_can_attach_check(cs);
ret = cpuset_can_attach_check(cs, oldcs, &setsched_check);
if (ret)
goto out_unlock;
/*
* Skip rights over task setsched check in v2 when nothing changes,
* migration permission derives from hierarchy ownership in
* cgroup_procs_write_permission()).
*/
setsched_check = !cpuset_v2() ||
!cpumask_equal(cs->effective_cpus, oldcs->effective_cpus) ||
!nodes_equal(cs->effective_mems, oldcs->effective_mems);
/*
* A v1 cpuset with tasks will have no CPU left only when CPU hotplug
* brings the last online CPU offline as users are not allowed to empty
* cpuset.cpus when there are active tasks inside. When that happens,
* we should allow tasks to migrate out without security check to make
* sure they will be able to run after migration.
*/
if (!is_in_v2_mode() && cpumask_empty(oldcs->effective_cpus))
setsched_check = false;
cgroup_taskset_for_each(task, css, tset) {
ret = task_can_attach(task);
if (ret)
@ -3639,7 +3647,7 @@ static int cpuset_can_fork(struct task_struct *task, struct css_set *cset)
mutex_lock(&cpuset_mutex);
/* Check to see if task is allowed in the cpuset */
ret = cpuset_can_attach_check(cs);
ret = cpuset_can_attach_check(cs, NULL, NULL);
if (ret)
goto out_unlock;