ANDROID: sched: fix race with CPU hot-unplug when overriding affinity
Migrating a task to a CPU which is concurrently being taken offline can cause the migration to fail silently, with the task left running on the old CPU. This is usually not the end of the world, but when forcefully migrating a 32-bit task during execve() from a 64-bit task, it is imperative that we do not attempt to return to userspace on a 64-bit-only CPU. Take the CPU hotplug lock for read while forcefully migrating a 32-bit task on execve() so that the migration cannot fail. Bug: 187917024 Change-Id: I6eaf2a564fe3ad73c03f0a6029aade09c707330f Signed-off-by: Will Deacon <willdeacon@google.com>
This commit is contained in:
parent
b6cab5d17d
commit
2f056f11e8
1 changed files with 11 additions and 2 deletions
|
|
@ -2091,7 +2091,15 @@ void force_compatible_cpus_allowed_ptr(struct task_struct *p)
|
|||
cpumask_var_t new_mask;
|
||||
const struct cpumask *override_mask = task_cpu_possible_mask(p);
|
||||
|
||||
if (!alloc_cpumask_var(&new_mask, GFP_KERNEL))
|
||||
alloc_cpumask_var(&new_mask, GFP_KERNEL);
|
||||
|
||||
/*
|
||||
* __migrate_task() can fail silently in the face of concurrent
|
||||
* offlining of the chosen destination CPU, so take the hotplug
|
||||
* lock to ensure that the migration succeeds.
|
||||
*/
|
||||
cpus_read_lock();
|
||||
if (!cpumask_available(new_mask))
|
||||
goto out_set_mask;
|
||||
|
||||
if (!restrict_cpus_allowed_ptr(p, new_mask, override_mask))
|
||||
|
|
@ -2111,8 +2119,9 @@ out_set_mask:
|
|||
cpumask_pr_args(override_mask));
|
||||
}
|
||||
|
||||
set_cpus_allowed_ptr(p, override_mask);
|
||||
WARN_ON(set_cpus_allowed_ptr(p, override_mask));
|
||||
out_free_mask:
|
||||
cpus_read_unlock();
|
||||
free_cpumask_var(new_mask);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue