From: Farhad Alemi <[email protected]>

Creating a child cpuset where cpuset.mems is never set leads to a div/0
when a VMA mempolicy with MPOL_F_RELATIVE_NODES rebinds in response to a
CPU hotplug event.

Reproduction steps:
 1) Create a cgroup w/ cpuset controls (do not set cpuset.mems)
 2) Move the task into the child cpuset
 3) Create a VMA mempolicy for that task with MPOL_F_RELATIVE_NODES
 4) unplug and hotplug a cpu
      echo 0 > /sys/devices/system/cpu/cpu1/online
      echo 1 > /sys/devices/system/cpu/cpu1/online
 5) mempolicy rebind does a div/0 in mpol_relative_nodemask on the
    call to __nodes_fold()

The cpuset code passes (cs->mems_allowed) which is not guaranteed to have
nodes to the rebind routine.  Use cs->effective_mems instead, which is
guaranteed to have a non-empty nodemask.

Closes: 
https://lore.kernel.org/linux-mm/ca+0ovcgxbzkxa+ou8w3s84r3knpnxxrfmsnr-udh+afqbbg...@mail.gmail.com/
Link: 
https://lore.kernel.org/all/CA+0ovCiEz6SP_sn3kN4Tb+_oC=eHMXy_Ffj=usv3wredqru...@mail.gmail.com/
Fixes: ae1c802382f7 ("cpuset: apply cs->effective_{cpus,mems}")
Suggested-by: Gregory Price <[email protected]>
Suggested-by: Waiman Long <[email protected]>
Signed-off-by: Farhad Alemi <[email protected]>
Acked-by: Waiman Long <[email protected]>
Reviewed-by: Ridong Chen <[email protected]>
Reviewed-by: Gregory Price <[email protected]>
Cc: [email protected]
---
 kernel/cgroup/cpuset.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index e53f35e2726f..49d8564d1a48 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -2671,7 +2671,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, &cs->effective_mems);
                if (migrate)
                        cpuset_migrate_mm(mm, &cs->old_mems_allowed, &newmems);
                else
-- 
2.54.0


Reply via email to