mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
cgroupfs: Fix lock ordering between kernfs.Filesystem.mu and TaskSet.mu.
We can't DecRef a cgroup with TaskSet.mu held as it leads to circular locking. Restructure task creation to drop cgroup refs outside the TaskSet.mu critical section. Reported-by: syzbot+16a334ab1d6873db18f2@syzkaller.appspotmail.com Reported-by: syzbot+fe1b962d430d1170e671@syzkaller.appspotmail.com PiperOrigin-RevId: 492589548
This commit is contained in:
committed by
gVisor bot
parent
9c5cd1cfca
commit
d0ae59368d
@@ -19,7 +19,6 @@ import (
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/atomicbitops"
|
||||
"gvisor.dev/gvisor/pkg/cleanup"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
"gvisor.dev/gvisor/pkg/hostarch"
|
||||
@@ -177,11 +176,9 @@ func (ts *TaskSet) newTask(ctx context.Context, cfg *TaskConfig) (*Task, error)
|
||||
// for justification.
|
||||
|
||||
var (
|
||||
cg Cgroup
|
||||
charged bool
|
||||
cu cleanup.Cleanup
|
||||
cg Cgroup
|
||||
charged, committed bool
|
||||
)
|
||||
defer cu.Clean()
|
||||
|
||||
// Reserve cgroup PIDs controller charge. This is either commited when the
|
||||
// new task enters the cgroup below, or rolled back on failure.
|
||||
@@ -196,12 +193,16 @@ func (ts *TaskSet) newTask(ctx context.Context, cfg *TaskConfig) (*Task, error)
|
||||
return nil, err
|
||||
}
|
||||
if charged {
|
||||
cu.Add(func() {
|
||||
if err := cg.Charge(t, cg.Dentry, CgroupControllerPIDs, CgroupResourcePID, -1); err != nil {
|
||||
panic(fmt.Sprintf("Failed to clean up PIDs charge on task creation failure: %v", err))
|
||||
defer func() {
|
||||
if !committed {
|
||||
if err := cg.Charge(t, cg.Dentry, CgroupControllerPIDs, CgroupResourcePID, -1); err != nil {
|
||||
panic(fmt.Sprintf("Failed to clean up PIDs charge on task creation failure: %v", err))
|
||||
}
|
||||
}
|
||||
cg.DecRef(ctx) // Ref from ChargeFor.
|
||||
})
|
||||
// Ref from ChargeFor. Note that we need to drop this outside of
|
||||
// TaskSet.mu critical sections.
|
||||
cg.DecRef(ctx)
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,11 +239,7 @@ func (ts *TaskSet) newTask(ctx context.Context, cfg *TaskConfig) (*Task, error)
|
||||
|
||||
// srcT may be nil, in which case we default to root cgroups.
|
||||
t.EnterInitialCgroups(srcT)
|
||||
|
||||
cu.Release()
|
||||
if charged {
|
||||
cg.decRef() // Ref from ChargeFor.
|
||||
}
|
||||
committed = true
|
||||
|
||||
if tg.leader == nil {
|
||||
// New thread group.
|
||||
|
||||
Reference in New Issue
Block a user