diff --git a/pkg/network/usm/ebpf_ssl.go b/pkg/network/usm/ebpf_ssl.go index 6dfabfbfae079..102725257482e 100644 --- a/pkg/network/usm/ebpf_ssl.go +++ b/pkg/network/usm/ebpf_ssl.go @@ -8,10 +8,16 @@ package usm import ( + "bytes" "debug/elf" "fmt" + "os" + "path/filepath" "regexp" + "strconv" "strings" + "sync" + "time" "unsafe" manager "github.com/DataDog/ebpf-manager" @@ -29,6 +35,7 @@ import ( "github.com/DataDog/datadog-agent/pkg/network/usm/sharedlibraries" "github.com/DataDog/datadog-agent/pkg/network/usm/utils" "github.com/DataDog/datadog-agent/pkg/util/common" + "github.com/DataDog/datadog-agent/pkg/util/kernel" "github.com/DataDog/datadog-agent/pkg/util/log" ) @@ -232,6 +239,10 @@ const ( sslSockByCtxMap = "ssl_sock_by_ctx" ) +var ( + buildKitProcessName = []byte("buildkitd") +) + // Template, will be modified during runtime. // The constructor of SSLProgram requires more parameters than we provide in the general way, thus we need to have // a dynamic initialization. @@ -423,21 +434,24 @@ func newSSLProgramProtocolFactory(m *manager.Manager, sockFDMap *ebpf.Map, bpfTe watcher *sharedlibraries.Watcher err error ) + + procRoot := kernel.ProcFSRoot() + if c.EnableNativeTLSMonitoring && http.HTTPSSupported(c) { watcher, err = sharedlibraries.NewWatcher(c, bpfTelemetry, sharedlibraries.Rule{ Re: regexp.MustCompile(`libssl.so`), - RegisterCB: addHooks(m, openSSLProbes), + RegisterCB: addHooks(m, procRoot, openSSLProbes), UnregisterCB: removeHooks(m, openSSLProbes), }, sharedlibraries.Rule{ Re: regexp.MustCompile(`libcrypto.so`), - RegisterCB: addHooks(m, cryptoProbes), + RegisterCB: addHooks(m, procRoot, cryptoProbes), UnregisterCB: removeHooks(m, cryptoProbes), }, sharedlibraries.Rule{ Re: regexp.MustCompile(`libgnutls.so`), - RegisterCB: addHooks(m, gnuTLSProbes), + RegisterCB: addHooks(m, procRoot, gnuTLSProbes), UnregisterCB: removeHooks(m, gnuTLSProbes), }, ) @@ -545,8 +559,52 @@ func (o *sslProgram) GetStats() *protocols.ProtocolStats { return nil } -func addHooks(m *manager.Manager, probes []manager.ProbesSelector) func(utils.FilePath) error { +const ( + // Defined in https://man7.org/linux/man-pages/man5/proc.5.html. + taskCommLen = 16 +) + +var ( + taskCommLenBufferPool = sync.Pool{ + New: func() any { + buf := make([]byte, taskCommLen) + return &buf + }, + } +) + +func isBuildKit(procRoot string, pid uint32) bool { + filePath := filepath.Join(procRoot, strconv.Itoa(int(pid)), "comm") + + file, err := os.Open(filePath) + if err != nil { + // Waiting a bit, as we might get the event of process creation before the directory was created. + for i := 0; i < 30; i++ { + time.Sleep(1 * time.Millisecond) + // reading again. + file, err = os.Open(filePath) + if err == nil { + break + } + } + } + + buf := taskCommLenBufferPool.Get().(*[]byte) + defer taskCommLenBufferPool.Put(buf) + n, err := file.Read(*buf) + if err != nil { + // short living process can hit here, or slow start of another process. + return false + } + return bytes.Equal(bytes.TrimSpace((*buf)[:n]), buildKitProcessName) +} + +func addHooks(m *manager.Manager, procRoot string, probes []manager.ProbesSelector) func(utils.FilePath) error { return func(fpath utils.FilePath) error { + if isBuildKit(procRoot, fpath.PID) { + return fmt.Errorf("process %d is buildkitd, skipping", fpath.PID) + } + uid := getUID(fpath.ID) elfFile, err := elf.Open(fpath.HostPath) @@ -555,8 +613,8 @@ func addHooks(m *manager.Manager, probes []manager.ProbesSelector) func(utils.Fi } defer elfFile.Close() - symbolsSet := make(common.StringSet, 0) - symbolsSetBestEffort := make(common.StringSet, 0) + symbolsSet := make(common.StringSet) + symbolsSetBestEffort := make(common.StringSet) for _, singleProbe := range probes { _, isBestEffort := singleProbe.(*manager.BestEffort) for _, selector := range singleProbe.GetProbesIdentificationPairList() { diff --git a/pkg/network/usm/istio.go b/pkg/network/usm/istio.go index 1919c2b0639fb..ced3271f3429f 100644 --- a/pkg/network/usm/istio.go +++ b/pkg/network/usm/istio.go @@ -108,13 +108,14 @@ func newIstioMonitor(c *config.Config, mgr *manager.Manager) *istioMonitor { return nil } + procRoot := kernel.ProcFSRoot() return &istioMonitor{ registry: utils.NewFileRegistry("istio"), - procRoot: kernel.ProcFSRoot(), + procRoot: procRoot, done: make(chan struct{}), // Callbacks - registerCB: addHooks(mgr, istioProbes), + registerCB: addHooks(mgr, procRoot, istioProbes), unregisterCB: removeHooks(mgr, istioProbes), } } diff --git a/pkg/network/usm/utils/file_registry.go b/pkg/network/usm/utils/file_registry.go index 3a589a961e4f9..97c661f3b2492 100644 --- a/pkg/network/usm/utils/file_registry.go +++ b/pkg/network/usm/utils/file_registry.go @@ -59,6 +59,7 @@ type FileRegistry struct { type FilePath struct { HostPath string ID PathIdentifier + PID uint32 } func NewFilePath(procRoot, namespacedPath string, pid uint32) (FilePath, error) { @@ -73,7 +74,7 @@ func NewFilePath(procRoot, namespacedPath string, pid uint32) (FilePath, error) return FilePath{}, err } - return FilePath{HostPath: path, ID: pathID}, nil + return FilePath{HostPath: path, ID: pathID, PID: pid}, nil } type callback func(FilePath) error