Re: [PATCH] cgroup/cpuset: rebind mm mempolicy to effective_mems, not mems_allowed
From: Waiman Long
Date: Wed Jun 10 2026 - 22:50:57 EST
On 6/9/26 7:57 PM, Farhad Alemi wrote:
cpuset_update_tasks_nodemask() rebinds a task's own mempolicy to the
cpuset's effective, online mems (newmems, from guarantee_online_mems()),
but rebinds that task's VMA mempolicies to the *configured* mask instead:
cpuset_change_task_nodemask(task, &newmems);
...
mpol_rebind_mm(mm, &cs->mems_allowed);
On the default (v2) hierarchy a cpuset that has never had cpuset.mems
written keeps mems_allowed empty while effective_mems is inherited
non-empty from the parent, and tasks may be attached to it (the
empty-mems attach check is v1-only). A subsequent rebind -- e.g. from a
CPU hotplug event walking the cpuset -- then calls mpol_rebind_mm() with
an empty mask. For a VMA policy created with MPOL_F_RELATIVE_NODES this
reaches mpol_relative_nodemask() ->
nodes_fold(..., nodes_weight(cs->mems_allowed) == 0) -> bitmap_fold(),
whose set_bit(oldbit % sz, dst) divides by zero:
Oops: divide error: 0000 [#1] SMP KASAN NOPTI
RIP: 0010:bitmap_fold+0x5e/0xb0
mpol_rebind_nodemask
mpol_rebind_mm
cpuset_update_tasks_nodemask
cpuset_handle_hotplug
sched_cpu_deactivate
cpuhp_thread_fun
cs->mems_allowed is the only nodemask in this function that is not the
effective set: the task-policy rebind, the page-migration target and
cs->old_mems_allowed all use newmems. The sibling cpuset_attach() path
already rebinds VMA policies against the effective mems
(cpuset_attach_nodemask_to = cs->effective_mems) and explicitly notes
that mems_allowed can be empty under hotplug. Rebind the VMA policies to
newmems too: it is guaranteed non-empty by guarantee_online_mems(), which
fixes the divide-by-zero, and it makes the VMA policies consistent with
the task policy and with the nodes the task is actually allowed to use.
Fixes: ae1c802382f7 ("cpuset: apply cs->effective_{cpus,mems}")
Suggested-by: Gregory Price <gourry@xxxxxxxxxx>
Signed-off-by: Farhad Alemi <farhad.alemi@xxxxxxxxxxxx>
Cc: stable@xxxxxxxxxxxxxxx
---
kernel/cgroup/cpuset.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -2649,7 +2649,7 @@ void cpuset_update_tasks_nodemask(struct cpuset *cs)
migrate = is_memory_migrate(cs);
- mpol_rebind_mm(mm, &cs->mems_allowed);
+ mpol_rebind_mm(mm, &newmems);
if (migrate)
cpuset_migrate_mm(mm, &cs->old_mems_allowed, &newmems);
else
Could you change it to &cs->effecitve_mems instead? For v2, effective_mems will never be empty.
In fact, this is part of the following patch
https://lore.kernel.org/lkml/20260604150229.414135-2-longman@xxxxxxxxxx/
Given that this bug can crash the kernel, it should be separated out as a separate patch.
Cheers,
Longman