github.com/castai/kvisor@v1.7.1-0.20240516114728-b3572a2607b5/pkg/ebpftracer/signature/signature.go (about) 1 package signature 2 3 import ( 4 "bytes" 5 "context" 6 "time" 7 8 castpb "github.com/castai/kvisor/api/v1/runtime" 9 "github.com/castai/kvisor/pkg/ebpftracer/events" 10 "github.com/castai/kvisor/pkg/ebpftracer/types" 11 "github.com/castai/kvisor/pkg/logging" 12 ) 13 14 type SignatureMetadata struct { 15 ID castpb.SignatureEventID 16 Name string 17 Version string 18 TargetEvents []events.ID 19 } 20 21 type SignatureEngineConfig struct { 22 InputChanSize int `validate:"required"` 23 OutputChanSize int `validate:"required"` 24 DefaultSignatureConfig DefaultSignatureConfig 25 } 26 27 type Signature interface { 28 GetMetadata() SignatureMetadata 29 30 OnEvent(event *types.Event) *castpb.SignatureFinding 31 } 32 33 type SignatureEngine struct { 34 log *logging.Logger 35 inputEvents chan *types.Event 36 eventsChan chan *castpb.Event 37 signatures []Signature 38 // Map of precalculated singature metadata to reduce object churn in event handling loop 39 signaturesMetadata map[Signature]*castpb.SignatureMetadata 40 eventsSignatureTriggers map[events.ID][]Signature 41 } 42 43 func NewEngine(signatures []Signature, log *logging.Logger, cfg SignatureEngineConfig) *SignatureEngine { 44 eventsSignatureTriggers, signaturesMetadata := buildLookupMaps(signatures) 45 46 return &SignatureEngine{ 47 log: log.WithField("component", "signature_engine"), 48 inputEvents: make(chan *types.Event, cfg.InputChanSize), 49 eventsChan: make(chan *castpb.Event, cfg.OutputChanSize), 50 signatures: signatures, 51 eventsSignatureTriggers: eventsSignatureTriggers, 52 signaturesMetadata: signaturesMetadata, 53 } 54 } 55 56 func buildLookupMaps(signatures []Signature) (map[events.ID][]Signature, map[Signature]*castpb.SignatureMetadata) { 57 signaturesByEvent := map[events.ID][]Signature{} 58 signatureMetadata := map[Signature]*castpb.SignatureMetadata{} 59 60 for _, signature := range signatures { 61 metadata := signature.GetMetadata() 62 signatureMetadata[signature] = &castpb.SignatureMetadata{ 63 Id: metadata.ID, 64 Version: metadata.Version, 65 } 66 67 for _, event := range metadata.TargetEvents { 68 signaturesByEvent[event] = append(signaturesByEvent[event], signature) 69 } 70 } 71 72 return signaturesByEvent, signatureMetadata 73 } 74 75 func (e *SignatureEngine) TargetEvents() []events.ID { 76 result := make([]events.ID, 0, len(e.eventsSignatureTriggers)) 77 78 for event := range e.eventsSignatureTriggers { 79 result = append(result, event) 80 } 81 82 return result 83 } 84 85 func (e *SignatureEngine) EventInput() chan<- *types.Event { 86 return e.inputEvents 87 } 88 89 func (e *SignatureEngine) Events() <-chan *castpb.Event { 90 return e.eventsChan 91 } 92 93 func (e *SignatureEngine) QueueEvent(event *types.Event) { 94 select { 95 case e.inputEvents <- event: 96 default: 97 } 98 } 99 100 func (e *SignatureEngine) Run(ctx context.Context) error { 101 e.log.Infof("running") 102 defer e.log.Infof("stopping") 103 104 for { 105 select { 106 case <-ctx.Done(): 107 return ctx.Err() 108 109 case event := <-e.inputEvents: 110 e.handleEvent(event) 111 } 112 } 113 } 114 115 func (e *SignatureEngine) handleEvent(event *types.Event) { 116 signatures := e.eventsSignatureTriggers[event.Context.EventID] 117 118 for _, signature := range signatures { 119 finding := signature.OnEvent(event) 120 121 if finding == nil { 122 continue 123 } 124 125 metadata := e.signaturesMetadata[signature] 126 127 e.eventsChan <- &castpb.Event{ 128 EventType: castpb.EventType_EVENT_SIGNATURE, 129 Timestamp: uint64(time.Now().UTC().UnixNano()), 130 ProcessName: string(bytes.Trim(event.Context.Comm[:], "\x00")), 131 Namespace: event.Container.PodNamespace, 132 PodName: event.Container.PodName, 133 ContainerName: event.Container.Name, 134 PodUid: event.Container.PodUID, 135 ContainerId: event.Container.ID, 136 CgroupId: event.Context.CgroupID, 137 HostPid: event.Context.HostPid, 138 Data: &castpb.Event_Signature{ 139 Signature: &castpb.SignatureEvent{ 140 Metadata: metadata, 141 Finding: finding, 142 }, 143 }, 144 } 145 } 146 }