Re: [PATCH] cgroup,freezer: hold cpu_hotplug_lock before freezer_mutex

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





On 4/5/2023 6:45 PM, Tetsuo Handa wrote:
syzbot is reporting circular locking dependency between cpu_hotplug_lock
and freezer_mutex, for commit f5d39b020809 ("freezer,sched: Rewrite core
freezer logic") replaced atomic_inc() in freezer_apply_state() with
static_branch_inc() which holds cpu_hotplug_lock.

cpu_hotplug_lock => cgroup_threadgroup_rwsem => freezer_mutex

   cgroup_file_write() {
     cgroup_procs_write() {
       __cgroup_procs_write() {
         cgroup_procs_write_start() {
           cgroup_attach_lock() {
             cpus_read_lock() {
               percpu_down_read(&cpu_hotplug_lock);
             }
             percpu_down_write(&cgroup_threadgroup_rwsem);
           }
         }
         cgroup_attach_task() {
           cgroup_migrate() {
             cgroup_migrate_execute() {
               freezer_attach() {
                 mutex_lock(&freezer_mutex);
                 (...snipped...)
               }
             }
           }
         }
         (...snipped...)
       }
     }
   }

freezer_mutex => cpu_hotplug_lock

   cgroup_file_write() {
     freezer_write() {
       freezer_change_state() {
         mutex_lock(&freezer_mutex);
         freezer_apply_state() {
           static_branch_inc(&freezer_active) {
             static_key_slow_inc() {
               cpus_read_lock();
               static_key_slow_inc_cpuslocked();
               cpus_read_unlock();
             }
           }
         }
         mutex_unlock(&freezer_mutex);
       }
     }
   }

Swap locking order by moving cpus_read_lock() in freezer_apply_state()
to before mutex_lock(&freezer_mutex) in freezer_change_state().

Reported-by: syzbot <syzbot+c39682e86c9d84152f93@xxxxxxxxxxxxxxxxxxxxxxxxx>
Link: https://syzkaller.appspot.com/bug?extid=c39682e86c9d84152f93
Suggested-by: Hillf Danton <hdanton@xxxxxxxx>
Fixes: f5d39b020809 ("freezer,sched: Rewrite core freezer logic")
Signed-off-by: Tetsuo Handa <penguin-kernel@xxxxxxxxxxxxxxxxxxx>
---
  kernel/cgroup/legacy_freezer.c | 7 +++++--
  1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/kernel/cgroup/legacy_freezer.c b/kernel/cgroup/legacy_freezer.c
index 1b6b21851e9d..936473203a6b 100644
--- a/kernel/cgroup/legacy_freezer.c
+++ b/kernel/cgroup/legacy_freezer.c
@@ -22,6 +22,7 @@
  #include <linux/freezer.h>
  #include <linux/seq_file.h>
  #include <linux/mutex.h>
+#include <linux/cpu.h>
/*
   * A cgroup is freezing if any FREEZING flags are set.  FREEZING_SELF is
@@ -350,7 +351,7 @@ static void freezer_apply_state(struct freezer *freezer, bool freeze,
if (freeze) {
  		if (!(freezer->state & CGROUP_FREEZING))
-			static_branch_inc(&freezer_active);
+			static_branch_inc_cpuslocked(&freezer_active);
  		freezer->state |= state;
  		freeze_cgroup(freezer);
  	} else {
@@ -361,7 +362,7 @@ static void freezer_apply_state(struct freezer *freezer, bool freeze,
  		if (!(freezer->state & CGROUP_FREEZING)) {
  			freezer->state &= ~CGROUP_FROZEN;
  			if (was_freezing)
-				static_branch_dec(&freezer_active);
+				static_branch_dec_cpuslocked(&freezer_active);
  			unfreeze_cgroup(freezer);
  		}
  	}
@@ -379,6 +380,7 @@ static void freezer_change_state(struct freezer *freezer, bool freeze)
  {
  	struct cgroup_subsys_state *pos;
+ cpus_read_lock();
  	/*
  	 * Update all its descendants in pre-order traversal.  Each
  	 * descendant will try to inherit its parent's FREEZING state as
@@ -407,6 +409,7 @@ static void freezer_change_state(struct freezer *freezer, bool freeze)
  	}
  	rcu_read_unlock();
  	mutex_unlock(&freezer_mutex);
+	cpus_read_unlock();
  }
static ssize_t freezer_write(struct kernfs_open_file *of,

This was reported here as well

https://lore.kernel.org/lkml/90147a2b-982e-ae57-9b7c-062bee0fab07@xxxxxxxxxx/

Reviewed-by: Mukesh Ojha <quic_mojha@xxxxxxxxxxx>

--Mukesh




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]     [Monitors]

  Powered by Linux