Skip to content

Commit a86e656

Browse files
fix(engine): restrict internal feedback to analyze
Feedback from findings back into the rules engine could cause a deadlock. This is because the engine would eventually block on trying to to send a new event to the feedbacking signature. This would cause a deadlock there - propagating back to the engine and pipeline in general. This does not occur in analyze mode - likely due to less stress in that mode. Introduce a mode field to the engine config to allow distinction between tracee-rules, single binary and analyze modes. The feedback logic which is implemented in the engine is only relevant for analyze mode. In single binary mode, we rely on the pipeline to handle the feedback.
1 parent bf80d8e commit a86e656

File tree

4 files changed

+24
-13
lines changed

4 files changed

+24
-13
lines changed

pkg/analyze/analyze.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,10 @@ func Analyze(cfg Config) {
5050
sigNamesToIds := sigs.CreateEventsFromSignatures(events.StartSignatureID, signatures)
5151

5252
engineConfig := engine.Config{
53+
Mode: engine.ModeAnalyze,
5354
Signatures: signatures,
5455
SignatureBufferSize: 1000,
55-
Enabled: true, // simulate tracee single binary mode
5656
SigNameToEventID: sigNamesToIds,
57-
ShouldDispatchEvent: func(eventIdInt32 int32) bool {
58-
// in analyze mode we don't need to filter by policy
59-
return true
60-
},
6157
}
6258

6359
// two seperate contexts.

pkg/cmd/cobra/cobra.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ func GetTraceeRunner(c *cobra.Command, version string) (cmd.Runner, error) {
314314
runner.InstallPath = traceeInstallPath
315315

316316
runner.TraceeConfig.EngineConfig = engine.Config{
317-
Enabled: true,
317+
Mode: engine.ModeSingleBinary,
318318
SigNameToEventID: sigNameToEventId,
319319
Signatures: signatures,
320320
// This used to be a flag, we have removed the flag from this binary to test

pkg/ebpf/events_pipeline.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/aquasecurity/tracee/pkg/errfmt"
1515
"github.com/aquasecurity/tracee/pkg/events"
1616
"github.com/aquasecurity/tracee/pkg/logger"
17+
"github.com/aquasecurity/tracee/pkg/signatures/engine"
1718
traceetime "github.com/aquasecurity/tracee/pkg/time"
1819
"github.com/aquasecurity/tracee/pkg/utils"
1920
"github.com/aquasecurity/tracee/types/trace"
@@ -72,7 +73,7 @@ func (t *Tracee) handleEvents(ctx context.Context, initialized chan<- struct{})
7273

7374
// Engine events stage: events go through the signatures engine for detection.
7475

75-
if t.config.EngineConfig.Enabled {
76+
if t.config.EngineConfig.Mode == engine.ModeSingleBinary {
7677
eventsChan, errc = t.engineEvents(ctx, eventsChan)
7778
errcList = append(errcList, errc)
7879
}
@@ -615,7 +616,7 @@ func (t *Tracee) sinkEvents(ctx context.Context, in <-chan *trace.Event) <-chan
615616
event.MatchedPolicies = t.policyManager.MatchedNames(event.MatchedPoliciesUser)
616617

617618
// Parse args here if the rule engine is NOT enabled (parsed there if it is).
618-
if t.config.Output.ParseArguments && !t.config.EngineConfig.Enabled {
619+
if t.config.Output.ParseArguments && t.config.EngineConfig.Mode != engine.ModeSingleBinary {
619620
err := t.parseArguments(event)
620621
if err != nil {
621622
t.handleError(err)

pkg/signatures/engine/engine.go

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,18 @@ const EVENT_CONTAINER_ORIGIN = "container"
1818
const EVENT_HOST_ORIGIN = "host"
1919
const ALL_EVENT_TYPES = "*"
2020

21+
type Mode uint8
22+
23+
const (
24+
ModeRules Mode = iota
25+
ModeAnalyze
26+
ModeSingleBinary
27+
)
28+
2129
// Config defines the engine's configurable values
2230
type Config struct {
2331
// Engine-in-Pipeline related configuration
24-
Enabled bool // Enables the signatures engine to run in the events pipeline
32+
Mode Mode
2533
SigNameToEventID map[string]int32 // Cache of loaded signature event names to event ids, used to filter in dispatching
2634

2735
// Callback from tracee to determine if event should be dispatched to signature.
@@ -148,9 +156,15 @@ func (engine *Engine) unloadAllSignatures() {
148156
func (engine *Engine) matchHandler(res *detect.Finding) {
149157
_ = engine.stats.Detections.Increment()
150158
engine.output <- res
151-
if !engine.config.Enabled {
159+
// TODO: the feedback here is enabled only in analyze, as it was causing a deadlock in the pipeline
160+
// when the engine was blocked on sending a new event to the feedbacking signature.
161+
// This is because the engine would eventually block on trying to to send
162+
// a new event to the feedbacking signature. This would cause a deadlock
163+
// there - propagating back to the engine and pipeline in general.
164+
// TODO2: Once we integrate the pipeline into analyze mode, we can remove this logic.
165+
if !(engine.config.Mode == ModeAnalyze) {
152166
return
153-
// next section is relevant only for engine-in-pipeline and analyze
167+
// next section is relevant only for analyze
154168
}
155169
e, err := findings.FindingToEvent(res)
156170
if err != nil {
@@ -272,8 +286,8 @@ drain:
272286
}
273287

274288
func (engine *Engine) dispatchEvent(s detect.Signature, event protocol.Event) {
275-
if engine.config.Enabled {
276-
// Do this test only if engine runs as part of the event pipeline
289+
if engine.config.Mode == ModeSingleBinary {
290+
// Filter only if engine runs as part of the event pipeline (single binary mode)
277291
if ok := engine.filterDispatchInPipeline(s, event); !ok {
278292
return
279293
}

0 commit comments

Comments
 (0)