From 7de87b36a1f9f8f0bf9e45273d92f69e12716a53 Mon Sep 17 00:00:00 2001 From: Jonathan Ribas Date: Fri, 20 Dec 2024 11:36:53 +0100 Subject: [PATCH] Add PCE NSID resolution for ptrace events --- pkg/security/probe/field_handlers_ebpf.go | 17 ++++++++++++++++- pkg/security/probe/probe_ebpf.go | 9 ++++++++- pkg/security/utils/proc_linux.go | 12 ++---------- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/pkg/security/probe/field_handlers_ebpf.go b/pkg/security/probe/field_handlers_ebpf.go index b76b70a76b833..63215156e4a19 100644 --- a/pkg/security/probe/field_handlers_ebpf.go +++ b/pkg/security/probe/field_handlers_ebpf.go @@ -20,6 +20,7 @@ import ( "github.com/DataDog/datadog-agent/pkg/security/resolvers" sprocess "github.com/DataDog/datadog-agent/pkg/security/resolvers/process" "github.com/DataDog/datadog-agent/pkg/security/secl/containerutils" + "github.com/DataDog/datadog-agent/pkg/security/utils" "github.com/DataDog/datadog-agent/pkg/security/secl/args" "github.com/DataDog/datadog-agent/pkg/security/secl/model" @@ -230,7 +231,7 @@ func (fh *EBPFFieldHandlers) ResolveRights(_ *model.Event, e *model.FileFields) return int(e.Mode) & (syscall.S_ISUID | syscall.S_ISGID | syscall.S_ISVTX | syscall.S_IRWXU | syscall.S_IRWXG | syscall.S_IRWXO) } -// ResolveChownUID resolves the ResolveProcessCacheEntry id of a chown event to a username +// ResolveChownUID resolves the user id of a chown event to a username func (fh *EBPFFieldHandlers) ResolveChownUID(ev *model.Event, e *model.ChownEvent) string { if len(e.User) == 0 { e.User, _ = fh.resolvers.UserGroupResolver.ResolveUser(int(e.UID), ev.ContainerContext.ContainerID) @@ -731,3 +732,17 @@ func (fh *EBPFFieldHandlers) ResolveOnDemandArg4Str(_ *model.Event, e *model.OnD func (fh *EBPFFieldHandlers) ResolveOnDemandArg4Uint(_ *model.Event, e *model.OnDemandEvent) int { return int(binary.NativeEndian.Uint64(e.Data[192 : 192+8])) } + +// ResolveProcessNSID resolves the process namespace ID +func (fh *EBPFFieldHandlers) ResolveProcessNSID(e *model.Event) (uint64, error) { + if e.ProcessCacheEntry.Process.NSID != 0 { + return e.ProcessCacheEntry.Process.NSID, nil + } + + nsid, err := utils.GetProcessPidNamespace(e.ProcessCacheEntry.Process.Pid) + if err != nil { + return 0, err + } + e.ProcessCacheEntry.Process.NSID = nsid + return nsid, nil +} diff --git a/pkg/security/probe/probe_ebpf.go b/pkg/security/probe/probe_ebpf.go index 23fdece00aa8e..828a8e0b85ce0 100644 --- a/pkg/security/probe/probe_ebpf.go +++ b/pkg/security/probe/probe_ebpf.go @@ -1090,7 +1090,14 @@ func (p *EBPFProbe) handleEvent(CPU int, data []byte) { if containerID == "" && event.PTrace.Request != unix.PTRACE_ATTACH { pidToResolve = event.PTrace.NSPID } else { - pid, err := utils.TryToResolveTraceePid(event.ProcessContext.Process.Pid, event.PTrace.NSPID) + nsid, err := p.fieldHandlers.ResolveProcessNSID(event) + if err != nil { + seclog.Debugf("PTrace NSID resolution error for process %s in container %s: %v", + event.ProcessContext.Process.FileEvent.PathnameStr, containerID, err) + return + } + + pid, err := utils.TryToResolveTraceePid(event.ProcessContext.Process.Pid, nsid, event.PTrace.NSPID) if err != nil { seclog.Debugf("PTrace tracee resolution error for process %s in container %s: %v", event.ProcessContext.Process.FileEvent.PathnameStr, containerID, err) diff --git a/pkg/security/utils/proc_linux.go b/pkg/security/utils/proc_linux.go index 35a0db8098c19..229a4b16350ed 100644 --- a/pkg/security/utils/proc_linux.go +++ b/pkg/security/utils/proc_linux.go @@ -567,22 +567,14 @@ var isNsPidAvailable = sync.OnceValue(func() bool { }) // TryToResolveTraceePid tries to resolve and returnt the HOST tracee PID, given the HOST tracer PID and the namespaced tracee PID. -func TryToResolveTraceePid(hostTracerPID, NsTraceePid uint32) (uint32, error) { +func TryToResolveTraceePid(hostTracerPID uint32, tracerNSID uint64, NsTraceePid uint32) (uint32, error) { // Look if the NSpid status field is available or not (it should be, except for Centos7). if isNsPidAvailable() { /* If it's available, we will search for an host pid having the same PID namespace as the tracer, and having the corresponding NS PID in its status field */ - - // 1. get the pid namespace of the tracer - ns, err := GetProcessPidNamespace(hostTracerPID) - if err != nil { - return 0, fmt.Errorf("Failed to resolve PID namespace: %v", err) - } - - // 2. find the host pid matching the arg pid with he tracer namespace - pid, err := FindPidNamespace(NsTraceePid, ns) + pid, err := FindPidNamespace(NsTraceePid, tracerNSID) if err != nil { return 0, fmt.Errorf("Failed to resolve tracee PID namespace: %v", err) }