Skip to content

Commit 57dcd64

Browse files
Tetsuo Handahtejun
authored andcommitted
cgroup,freezer: hold cpu_hotplug_lock before freezer_mutex
syzbot is reporting circular locking dependency between cpu_hotplug_lock and freezer_mutex, for commit f5d39b0 ("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@syzkaller.appspotmail.com> Link: https://syzkaller.appspot.com/bug?extid=c39682e86c9d84152f93 Suggested-by: Hillf Danton <hdanton@sina.com> Fixes: f5d39b0 ("freezer,sched: Rewrite core freezer logic") Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Mukesh Ojha <quic_mojha@quicinc.com> Signed-off-by: Tejun Heo <tj@kernel.org>
1 parent 292fd84 commit 57dcd64

1 file changed

Lines changed: 5 additions & 2 deletions

File tree

kernel/cgroup/legacy_freezer.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <linux/freezer.h>
2323
#include <linux/seq_file.h>
2424
#include <linux/mutex.h>
25+
#include <linux/cpu.h>
2526

2627
/*
2728
* 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,
350351

351352
if (freeze) {
352353
if (!(freezer->state & CGROUP_FREEZING))
353-
static_branch_inc(&freezer_active);
354+
static_branch_inc_cpuslocked(&freezer_active);
354355
freezer->state |= state;
355356
freeze_cgroup(freezer);
356357
} else {
@@ -361,7 +362,7 @@ static void freezer_apply_state(struct freezer *freezer, bool freeze,
361362
if (!(freezer->state & CGROUP_FREEZING)) {
362363
freezer->state &= ~CGROUP_FROZEN;
363364
if (was_freezing)
364-
static_branch_dec(&freezer_active);
365+
static_branch_dec_cpuslocked(&freezer_active);
365366
unfreeze_cgroup(freezer);
366367
}
367368
}
@@ -379,6 +380,7 @@ static void freezer_change_state(struct freezer *freezer, bool freeze)
379380
{
380381
struct cgroup_subsys_state *pos;
381382

383+
cpus_read_lock();
382384
/*
383385
* Update all its descendants in pre-order traversal. Each
384386
* 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)
407409
}
408410
rcu_read_unlock();
409411
mutex_unlock(&freezer_mutex);
412+
cpus_read_unlock();
410413
}
411414

412415
static ssize_t freezer_write(struct kernfs_open_file *of,

0 commit comments

Comments
 (0)