diff --git a/pkg/sentry/kernel/ptrace.go b/pkg/sentry/kernel/ptrace.go index 535fa8f71..9029eaa99 100644 --- a/pkg/sentry/kernel/ptrace.go +++ b/pkg/sentry/kernel/ptrace.go @@ -567,10 +567,10 @@ func (t *Task) ptraceDetach(target *Task, sig linux.Signal) error { return nil } -// exitPtrace is called in the exit path to detach all of t's tracees. -func (t *Task) exitPtrace() { - t.tg.pidns.owner.mu.Lock() - defer t.tg.pidns.owner.mu.Unlock() +// exitPtraceLocked is called in the exit path to detach all of t's tracees. +// +// Preconditions: The TaskSet mutex must be locked for writing. +func (t *Task) exitPtraceLocked() { for target := range t.ptraceTracees { if target.ptraceOpts.ExitKill { target.tg.signalHandlers.mu.Lock() diff --git a/pkg/sentry/kernel/task_exit.go b/pkg/sentry/kernel/task_exit.go index b5c2ff6c4..6d0c3ba5f 100644 --- a/pkg/sentry/kernel/task_exit.go +++ b/pkg/sentry/kernel/task_exit.go @@ -315,14 +315,15 @@ func (*runExitMain) execute(t *Task) taskRunState { t.tg.Release(t) } + t.tg.pidns.owner.mu.Lock() // Detach tracees. - t.exitPtrace() - + t.exitPtraceLocked() // Reparent the task's children. - t.exitChildren() + t.exitChildrenLocked() + t.tg.pidns.owner.mu.Unlock() - // Don't tail-call runExitNotify, as exitChildren may have initiated a stop - // to wait for a PID namespace to die. + // Don't tail-call runExitNotify, as exitChildrenLocked may have initiated + // a stop to wait for a PID namespace to die. return (*runExitNotify)(nil) } @@ -360,9 +361,8 @@ func (t *Task) exitThreadGroup() bool { return last } -func (t *Task) exitChildren() { - t.tg.pidns.owner.mu.Lock() - defer t.tg.pidns.owner.mu.Unlock() +// Preconditions: The TaskSet mutex must be locked for writing. +func (t *Task) exitChildrenLocked() { newParent := t.findReparentTargetLocked() if newParent == nil { // "If the init process of a PID namespace terminates, the kernel