Skip to content

Commit

Permalink
chore(ebpf): copy event before parsing it
Browse files Browse the repository at this point in the history
Refactor 'event feeding to engine' logic to copy the event before
parsing it, cloning its arguments.
  • Loading branch information
geyslan committed Oct 9, 2024
1 parent 8b4da2f commit c00b2b6
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 38 deletions.
18 changes: 8 additions & 10 deletions pkg/ebpf/events_pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -614,8 +614,8 @@ func (t *Tracee) sinkEvents(ctx context.Context, in <-chan *trace.Event) <-chan
// Populate the event with the names of the matched policies.
event.MatchedPolicies = t.policyManager.MatchedNames(event.MatchedPoliciesUser)

// Parse args here if the rule engine is not enabled (parsed there if it is).
if !t.config.EngineConfig.Enabled {
// Parse args here if the rule engine is NOT enabled (parsed there if it is).
if t.config.Output.ParseArguments && !t.config.EngineConfig.Enabled {
err := t.parseArguments(event)
if err != nil {
t.handleError(err)
Expand Down Expand Up @@ -727,15 +727,13 @@ func (t *Tracee) handleError(err error) {
// cmd/tracee-rules), it happens on the "sink" stage of the pipeline (close to the
// printers).
func (t *Tracee) parseArguments(e *trace.Event) error {
if t.config.Output.ParseArguments {
err := events.ParseArgs(e)
if err != nil {
return errfmt.WrapError(err)
}
err := events.ParseArgs(e)
if err != nil {
return errfmt.WrapError(err)
}

if t.config.Output.ParseArgumentsFDs {
return events.ParseArgsFDs(e, uint64(e.Timestamp), t.FDArgPathMap)
}
if t.config.Output.ParseArgumentsFDs {
return events.ParseArgsFDs(e, uint64(e.Timestamp), t.FDArgPathMap)
}

return nil
Expand Down
66 changes: 38 additions & 28 deletions pkg/ebpf/signature_engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package ebpf

import (
"context"
"slices"

"github.com/aquasecurity/tracee/pkg/containers"
"github.com/aquasecurity/tracee/pkg/dnscache"
Expand Down Expand Up @@ -52,51 +53,60 @@ func (t *Tracee) engineEvents(ctx context.Context, in <-chan *trace.Event) (<-ch

go t.sigEngine.Start(ctx)

// Create a function for feeding the engine with an event
feedFunc := func(event *trace.Event) {
if event == nil {
return // might happen during initialization (ctrl+c seg faults)
}
// TODO: in the upcoming releases, the rule engine should be changed to receive trace.Event,
// and return a trace.Event, which should remove the necessity of converting trace.Event to protocol.Event,
// and converting detect.Finding into trace.Event

id := events.ID(event.EventID)
go func() {
defer close(out)
defer close(errc)
defer close(engineInput)
defer close(engineOutput)

// feedEngine feeds an event to the rules engine
feedEngine := func(event *trace.Event) {
if event == nil {
return // might happen during initialization (ctrl+c seg faults)
}

id := events.ID(event.EventID)

// if the event is marked as submit, we pass it to the engine
if t.policyManager.IsEventToSubmit(id) {
err := t.parseArguments(event)
if err != nil {
t.handleError(err)
// if the event is NOT marked as submit, it is not sent to the rules engine
if !t.policyManager.IsEventToSubmit(id) {
return
}

// Get a copy of our event before sending it down the pipeline.
// This is needed because a later modification of the event (in
// particular of the matched policies) can affect engine stage.
// Get a copy of event before parsing it or sending it down the pipeline.
// This is needed because a later modification of the event (matched policies or
// arguments parsing) can affect engine stage.
eventCopy := *event

if t.config.Output.ParseArguments {
// shallow clone the event arguments before parsing them (new slice is created),
// to keep the eventCopy with raw arguments.
eventCopy.Args = slices.Clone(event.Args)

err := t.parseArguments(event)
if err != nil {
t.handleError(err)
return
}
}

// pass the event to the sink stage, if the event is also marked as emit
// it will be sent to print by the sink stage
out <- event

// send the event to the rule event
// send the copied event to the rules engine
engineInput <- eventCopy.ToProtocol()
}
}

// TODO: in the upcoming releases, the rule engine should be changed to receive trace.Event,
// and return a trace.Event, which should remove the necessity of converting trace.Event to protocol.Event,
// and converting detect.Finding into trace.Event

go func() {
defer close(out)
defer close(errc)
defer close(engineInput)
defer close(engineOutput)

for {
select {
case event := <-in:
feedFunc(event)
feedEngine(event)
case event := <-engineOutputEvents:
feedFunc(event)
feedEngine(event)
case <-ctx.Done():
return
}
Expand Down

0 comments on commit c00b2b6

Please sign in to comment.