sched/core: Forbid Unity-based games from changing their CPU affinity

Unity-based games (such as Wild Rift) like to shoot themselves in the foot
by setting a nonsense CPU affinity, restricting the game to a narrow set of
CPU cores that it thinks are the "big" cores in a heterogeneous CPU. It
assumes that CPUs only have two performance domains (clusters), and
therefore royally mucks up games' CPU affinities on CPUs which have more
than two performance domains.

Check if a setaffinity target task is part of a Unity-based game and
silently ignore the setaffinity request so that it can't sabotage itself.

Signed-off-by: Sultan Alsawaf <sultan@kerneltoast.com>
This commit is contained in:
Sultan Alsawaf 2024-05-11 00:10:43 -07:00 committed by Ksawlii
parent 136bbfd757
commit d4bbaf5715

View file

@ -6177,11 +6177,32 @@ out_unlock:
return retval;
}
static bool task_is_unity_game(struct task_struct *p)
{
struct task_struct *t;
bool ret = false;
/* Filter for Android user applications (i.e., positive adj) */
if (p->signal->oom_score_adj >= 0) {
rcu_read_lock();
for_each_thread(p, t) {
/* Check for a UnityMain thread in the thread group */
if (!strcmp(t->comm, "UnityMain")) {
ret = true;
break;
}
}
rcu_read_unlock();
}
return ret;
}
long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
{
cpumask_var_t cpus_allowed, new_mask;
struct task_struct *p;
int retval;
int retval = 0;
int skip = 0;
rcu_read_lock();
@ -6196,6 +6217,20 @@ long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
get_task_struct(p);
rcu_read_unlock();
/*
* Unity-based games like to shoot themselves in the foot by setting a
* nonsense CPU affinity, restricting the game to a narrow set of CPU
* cores that it thinks are the "big" cores in a heterogeneous CPU. It
* assumes that CPUs only have two performance domains (clusters), and
* therefore royally mucks up games' CPU affinities on CPUs which have
* more than two performance domains.
*
* Check if the target task is part of a Unity-based game and silently
* ignore the setaffinity request so that it can't sabotage itself.
*/
if (task_is_unity_game(p))
goto out_put_task;
if (p->flags & PF_NO_SETAFFINITY) {
retval = -EINVAL;
goto out_put_task;