@@ -22,6 +22,7 @@ import (
22
22
23
23
manager "github.com/DataDog/ebpf-manager"
24
24
"github.com/cilium/ebpf"
25
+ "github.com/cilium/ebpf/features"
25
26
"github.com/davecgh/go-spew/spew"
26
27
27
28
ddebpf "github.com/DataDog/datadog-agent/pkg/ebpf"
@@ -69,6 +70,9 @@ const (
69
70
gnutlsRecordSendRetprobe = "uretprobe__gnutls_record_send"
70
71
gnutlsByeProbe = "uprobe__gnutls_bye"
71
72
gnutlsDeinitProbe = "uprobe__gnutls_deinit"
73
+
74
+ rawTracepointSchedProcessExit = "raw_tracepoint__sched_process_exit"
75
+ oldTracepointSchedProcessExit = "tracepoint__sched__sched_process_exit"
72
76
)
73
77
74
78
var openSSLProbes = []manager.ProbesSelector {
@@ -424,12 +428,23 @@ var opensslSpec = &protocols.ProtocolSpec{
424
428
EBPFFuncName : gnutlsDeinitProbe ,
425
429
},
426
430
},
431
+ {
432
+ ProbeIdentificationPair : manager.ProbeIdentificationPair {
433
+ EBPFFuncName : rawTracepointSchedProcessExit ,
434
+ },
435
+ },
436
+ {
437
+ ProbeIdentificationPair : manager.ProbeIdentificationPair {
438
+ EBPFFuncName : oldTracepointSchedProcessExit ,
439
+ },
440
+ },
427
441
},
428
442
}
429
443
430
444
type sslProgram struct {
431
- cfg * config.Config
432
- watcher * sharedlibraries.Watcher
445
+ cfg * config.Config
446
+ watcher * sharedlibraries.Watcher
447
+ ebpfManager * manager.Manager
433
448
}
434
449
435
450
func newSSLProgramProtocolFactory (m * manager.Manager , c * config.Config ) (protocols.Protocol , error ) {
@@ -441,11 +456,18 @@ func newSSLProgramProtocolFactory(m *manager.Manager, c *config.Config) (protoco
441
456
watcher * sharedlibraries.Watcher
442
457
err error
443
458
)
444
-
459
+ sslProgram := & sslProgram {
460
+ cfg : c ,
461
+ ebpfManager : m ,
462
+ }
463
+ var cleanerCB func (map [uint32 ]struct {})
464
+ if features .HaveProgramType (ebpf .RawTracepoint ) != nil {
465
+ cleanerCB = sslProgram .cleanupDeadPids
466
+ }
445
467
procRoot := kernel .ProcFSRoot ()
446
468
447
469
if c .EnableNativeTLSMonitoring && usmconfig .TLSSupported (c ) {
448
- watcher , err = sharedlibraries .NewWatcher (c , sharedlibraries .LibsetCrypto ,
470
+ watcher , err = sharedlibraries .NewWatcher (c , sharedlibraries .LibsetCrypto , cleanerCB ,
449
471
sharedlibraries.Rule {
450
472
Re : regexp .MustCompile (`libssl.so` ),
451
473
RegisterCB : addHooks (m , procRoot , openSSLProbes ),
@@ -467,10 +489,9 @@ func newSSLProgramProtocolFactory(m *manager.Manager, c *config.Config) (protoco
467
489
}
468
490
}
469
491
470
- return & sslProgram {
471
- cfg : c ,
472
- watcher : watcher ,
473
- }, nil
492
+ sslProgram .watcher = watcher
493
+
494
+ return sslProgram , nil
474
495
}
475
496
476
497
// Name return the program's name.
@@ -495,6 +516,7 @@ func sharedLibrariesConfigureOptions(options *manager.Options, cfg *config.Confi
495
516
// ConfigureOptions changes map attributes to the given options.
496
517
func (o * sslProgram ) ConfigureOptions (options * manager.Options ) {
497
518
sharedLibrariesConfigureOptions (options , o .cfg )
519
+ o .addProcessExitProbe (options )
498
520
}
499
521
500
522
// PreStart is called before the start of the provided eBPF manager.
@@ -534,6 +556,33 @@ func (o *sslProgram) DumpMaps(w io.Writer, mapName string, currentMap *ebpf.Map)
534
556
spew .Fdump (w , key , value )
535
557
}
536
558
559
+ case "ssl_read_ex_args" : // maps/ssl_read_ex_args (BPF_MAP_TYPE_HASH), key C.__u64, value C.ssl_read_ex_args_t
560
+ io .WriteString (w , "Map: '" + mapName + "', key: 'C.__u64', value: 'C.ssl_read_ex_args_t'\n " )
561
+ iter := currentMap .Iterate ()
562
+ var key uint64
563
+ var value http.SslReadExArgs
564
+ for iter .Next (unsafe .Pointer (& key ), unsafe .Pointer (& value )) {
565
+ spew .Fdump (w , key , value )
566
+ }
567
+
568
+ case "ssl_write_args" : // maps/ssl_write_args (BPF_MAP_TYPE_HASH), key C.__u64, value C.ssl_write_args_t
569
+ io .WriteString (w , "Map: '" + mapName + "', key: 'C.__u64', value: 'C.ssl_write_args_t'\n " )
570
+ iter := currentMap .Iterate ()
571
+ var key uint64
572
+ var value http.SslWriteArgs
573
+ for iter .Next (unsafe .Pointer (& key ), unsafe .Pointer (& value )) {
574
+ spew .Fdump (w , key , value )
575
+ }
576
+
577
+ case "ssl_write_ex_args_t" : // maps/ssl_write_ex_args_t (BPF_MAP_TYPE_HASH), key C.__u64, value C.ssl_write_args_t
578
+ io .WriteString (w , "Map: '" + mapName + "', key: 'C.__u64', value: 'C.ssl_write_ex_args_t'\n " )
579
+ iter := currentMap .Iterate ()
580
+ var key uint64
581
+ var value http.SslWriteExArgs
582
+ for iter .Next (unsafe .Pointer (& key ), unsafe .Pointer (& value )) {
583
+ spew .Fdump (w , key , value )
584
+ }
585
+
537
586
case "bio_new_socket_args" : // maps/bio_new_socket_args (BPF_MAP_TYPE_HASH), key C.__u64, value C.__u32
538
587
io .WriteString (w , "Map: '" + mapName + "', key: 'C.__u64', value: 'C.__u32'\n " )
539
588
iter := currentMap .Iterate ()
@@ -773,3 +822,78 @@ func getUID(lib utils.PathIdentifier) string {
773
822
func (* sslProgram ) IsBuildModeSupported (buildmode.Type ) bool {
774
823
return true
775
824
}
825
+
826
+ // addProcessExitProbe adds a raw or regular tracepoint program depending on which is supported.
827
+ func (o * sslProgram ) addProcessExitProbe (options * manager.Options ) {
828
+ if features .HaveProgramType (ebpf .RawTracepoint ) == nil {
829
+ // use a raw tracepoint on a supported kernel to intercept terminated threads and clear the corresponding maps
830
+ p := & manager.Probe {
831
+ ProbeIdentificationPair : manager.ProbeIdentificationPair {
832
+ EBPFFuncName : rawTracepointSchedProcessExit ,
833
+ UID : probeUID ,
834
+ },
835
+ TracepointName : "sched_process_exit" ,
836
+ }
837
+ o .ebpfManager .Probes = append (o .ebpfManager .Probes , p )
838
+ options .ActivatedProbes = append (options .ActivatedProbes , & manager.ProbeSelector {ProbeIdentificationPair : p .ProbeIdentificationPair })
839
+ // exclude regular tracepoint
840
+ options .ExcludedFunctions = append (options .ExcludedFunctions , oldTracepointSchedProcessExit )
841
+ } else {
842
+ // use a regular tracepoint to intercept terminated threads
843
+ p := & manager.Probe {
844
+ ProbeIdentificationPair : manager.ProbeIdentificationPair {
845
+ EBPFFuncName : oldTracepointSchedProcessExit ,
846
+ UID : probeUID ,
847
+ },
848
+ }
849
+ o .ebpfManager .Probes = append (o .ebpfManager .Probes , p )
850
+ options .ActivatedProbes = append (options .ActivatedProbes , & manager.ProbeSelector {ProbeIdentificationPair : p .ProbeIdentificationPair })
851
+ // exclude a raw tracepoint
852
+ options .ExcludedFunctions = append (options .ExcludedFunctions , rawTracepointSchedProcessExit )
853
+ }
854
+ }
855
+
856
+ var sslPidKeyMaps = []string {
857
+ "ssl_read_args" ,
858
+ "ssl_read_ex_args" ,
859
+ "ssl_write_args" ,
860
+ "ssl_write_ex_args" ,
861
+ "ssl_ctx_by_pid_tgid" ,
862
+ "bio_new_socket_args" ,
863
+ }
864
+
865
+ // cleanupDeadPids clears maps of terminated processes, is invoked when raw tracepoints unavailable.
866
+ func (o * sslProgram ) cleanupDeadPids (alivePIDs map [uint32 ]struct {}) {
867
+ for _ , mapName := range sslPidKeyMaps {
868
+ err := deleteDeadPidsInMap (o .ebpfManager , mapName , alivePIDs )
869
+ if err != nil {
870
+ log .Debugf ("SSL map %q cleanup error: %v" , mapName , err )
871
+ }
872
+ }
873
+ }
874
+
875
+ // deleteDeadPidsInMap finds a map by name and deletes dead processes.
876
+ // enters when raw tracepoint is not supported, kernel < 4.17
877
+ func deleteDeadPidsInMap (manager * manager.Manager , mapName string , alivePIDs map [uint32 ]struct {}) error {
878
+ emap , _ , err := manager .GetMap (mapName )
879
+ if err != nil {
880
+ return fmt .Errorf ("dead process cleaner failed to get map: %q error: %w" , mapName , err )
881
+ }
882
+
883
+ var keysToDelete []uint64
884
+ var key uint64
885
+ value := make ([]byte , emap .ValueSize ())
886
+ iter := emap .Iterate ()
887
+
888
+ for iter .Next (unsafe .Pointer (& key ), unsafe .Pointer (& value )) {
889
+ pid := uint32 (key >> 32 )
890
+ if _ , exists := alivePIDs [pid ]; ! exists {
891
+ keysToDelete = append (keysToDelete , key )
892
+ }
893
+ }
894
+ for _ , k := range keysToDelete {
895
+ _ = emap .Delete (unsafe .Pointer (& k ))
896
+ }
897
+
898
+ return nil
899
+ }
0 commit comments