mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Fix circular lock between filesystemRWMutex and taskSetRWMutex.
PiperOrigin-RevId: 500747195
This commit is contained in:
committed by
gVisor bot
parent
a17ad261d6
commit
a248c63cd5
@@ -19,17 +19,44 @@ import (
|
||||
pb "gvisor.dev/gvisor/pkg/sentry/seccheck/points/points_go_proto"
|
||||
)
|
||||
|
||||
func getTaskCurrentWorkingDirectory(t *Task) string {
|
||||
// Grab the filesystem context first since it needs tasks.mu to be locked.
|
||||
// It's safe to unlock and use the values obtained here as long as there's
|
||||
// no way to modify root and wd from a separate task.
|
||||
t.k.tasks.mu.RLock()
|
||||
root := t.FSContext().RootDirectory()
|
||||
wd := t.FSContext().WorkingDirectory()
|
||||
t.k.tasks.mu.RUnlock()
|
||||
|
||||
// Perform VFS operations outside of task mutex to avoid circular locking with
|
||||
// filesystem mutexes.
|
||||
var cwd string
|
||||
if root.Ok() {
|
||||
defer root.DecRef(t)
|
||||
if wd.Ok() {
|
||||
defer wd.DecRef(t)
|
||||
vfsObj := root.Mount().Filesystem().VirtualFilesystem()
|
||||
cwd, _ = vfsObj.PathnameWithDeleted(t, root, wd)
|
||||
}
|
||||
}
|
||||
return cwd
|
||||
}
|
||||
|
||||
// LoadSeccheckData sets info from the task based on mask.
|
||||
func LoadSeccheckData(t *Task, mask seccheck.FieldMask, info *pb.ContextData) {
|
||||
var cwd string
|
||||
if mask.Contains(seccheck.FieldCtxtCwd) {
|
||||
cwd = getTaskCurrentWorkingDirectory(t)
|
||||
}
|
||||
t.k.tasks.mu.RLock()
|
||||
defer t.k.tasks.mu.RUnlock()
|
||||
LoadSeccheckDataLocked(t, mask, info)
|
||||
LoadSeccheckDataLocked(t, mask, info, cwd)
|
||||
}
|
||||
|
||||
// LoadSeccheckDataLocked sets info from the task based on mask.
|
||||
//
|
||||
// Preconditions: The TaskSet mutex must be locked.
|
||||
func LoadSeccheckDataLocked(t *Task, mask seccheck.FieldMask, info *pb.ContextData) {
|
||||
func LoadSeccheckDataLocked(t *Task, mask seccheck.FieldMask, info *pb.ContextData, cwd string) {
|
||||
if mask.Contains(seccheck.FieldCtxtTime) {
|
||||
info.TimeNs = t.k.RealtimeClock().Now().Nanoseconds()
|
||||
}
|
||||
@@ -49,14 +76,7 @@ func LoadSeccheckDataLocked(t *Task, mask seccheck.FieldMask, info *pb.ContextDa
|
||||
info.ContainerId = t.tg.leader.ContainerID()
|
||||
}
|
||||
if mask.Contains(seccheck.FieldCtxtCwd) {
|
||||
if root := t.FSContext().RootDirectory(); root.Ok() {
|
||||
defer root.DecRef(t)
|
||||
if wd := t.FSContext().WorkingDirectory(); wd.Ok() {
|
||||
defer wd.DecRef(t)
|
||||
vfsObj := root.Mount().Filesystem().VirtualFilesystem()
|
||||
info.Cwd, _ = vfsObj.PathnameWithDeleted(t, root, wd)
|
||||
}
|
||||
}
|
||||
info.Cwd = cwd
|
||||
}
|
||||
if mask.Contains(seccheck.FieldCtxtProcessName) {
|
||||
info.ProcessName = t.Name()
|
||||
|
||||
@@ -310,7 +310,10 @@ func (t *Task) Clone(args *linux.CloneArgs) (ThreadID, *SyscallControl, error) {
|
||||
|
||||
func getCloneSeccheckInfo(t, nt *Task, flags uint64) (seccheck.FieldSet, *pb.CloneInfo) {
|
||||
fields := seccheck.Global.GetFieldSet(seccheck.PointClone)
|
||||
|
||||
var cwd string
|
||||
if fields.Context.Contains(seccheck.FieldCtxtCwd) {
|
||||
cwd = getTaskCurrentWorkingDirectory(t)
|
||||
}
|
||||
t.k.tasks.mu.RLock()
|
||||
defer t.k.tasks.mu.RUnlock()
|
||||
info := &pb.CloneInfo{
|
||||
@@ -322,7 +325,7 @@ func getCloneSeccheckInfo(t, nt *Task, flags uint64) (seccheck.FieldSet, *pb.Clo
|
||||
|
||||
if !fields.Context.Empty() {
|
||||
info.ContextData = &pb.ContextData{}
|
||||
LoadSeccheckDataLocked(t, fields.Context, info.ContextData)
|
||||
LoadSeccheckDataLocked(t, fields.Context, info.ContextData, cwd)
|
||||
}
|
||||
|
||||
return fields, info
|
||||
|
||||
@@ -748,7 +748,9 @@ func getExitNotifyParentSeccheckInfo(t *Task) (seccheck.FieldSet, *pb.ExitNotify
|
||||
}
|
||||
if !fields.Context.Empty() {
|
||||
info.ContextData = &pb.ContextData{}
|
||||
LoadSeccheckDataLocked(t, fields.Context, info.ContextData)
|
||||
// cwd isn't used for notifyExit seccheck so it's ok to pass an empty
|
||||
// string.
|
||||
LoadSeccheckDataLocked(t, fields.Context, info.ContextData, "")
|
||||
}
|
||||
|
||||
return fields, info
|
||||
|
||||
@@ -243,9 +243,42 @@ func init() {
|
||||
ContextFields: defaultContextFields,
|
||||
})
|
||||
registerPoint(PointDesc{
|
||||
ID: PointExitNotifyParent,
|
||||
Name: "sentry/exit_notify_parent",
|
||||
ContextFields: defaultContextFields,
|
||||
ID: PointExitNotifyParent,
|
||||
Name: "sentry/exit_notify_parent",
|
||||
ContextFields: []FieldDesc{
|
||||
{
|
||||
ID: FieldCtxtTime,
|
||||
Name: "time",
|
||||
},
|
||||
{
|
||||
ID: FieldCtxtThreadID,
|
||||
Name: "thread_id",
|
||||
},
|
||||
{
|
||||
ID: FieldCtxtThreadStartTime,
|
||||
Name: "task_start_time",
|
||||
},
|
||||
{
|
||||
ID: FieldCtxtThreadGroupID,
|
||||
Name: "group_id",
|
||||
},
|
||||
{
|
||||
ID: FieldCtxtThreadGroupStartTime,
|
||||
Name: "thread_group_start_time",
|
||||
},
|
||||
{
|
||||
ID: FieldCtxtContainerID,
|
||||
Name: "container_id",
|
||||
},
|
||||
{
|
||||
ID: FieldCtxtCredentials,
|
||||
Name: "credentials",
|
||||
},
|
||||
{
|
||||
ID: FieldCtxtProcessName,
|
||||
Name: "process_name",
|
||||
},
|
||||
},
|
||||
})
|
||||
registerPoint(PointDesc{
|
||||
ID: PointTaskExit,
|
||||
|
||||
Reference in New Issue
Block a user