Skip to content

Commit 0b98556

Browse files
PR aquasecurity#4803: 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. commit a86e656 (main), cherry-pick
1 parent 651ff83 commit 0b98556

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
@@ -315,7 +315,7 @@ func GetTraceeRunner(c *cobra.Command, version string) (cmd.Runner, error) {
315315
runner.InstallPath = traceeInstallPath
316316

317317
runner.TraceeConfig.EngineConfig = engine.Config{
318-
Enabled: true,
318+
Mode: engine.ModeSingleBinary,
319319
SigNameToEventID: sigNameToEventId,
320320
Signatures: signatures,
321321
// 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
@@ -15,6 +15,7 @@ import (
1515
"github.com/aquasecurity/tracee/pkg/errfmt"
1616
"github.com/aquasecurity/tracee/pkg/events"
1717
"github.com/aquasecurity/tracee/pkg/logger"
18+
"github.com/aquasecurity/tracee/pkg/signatures/engine"
1819
traceetime "github.com/aquasecurity/tracee/pkg/time"
1920
"github.com/aquasecurity/tracee/pkg/utils"
2021
"github.com/aquasecurity/tracee/types/trace"
@@ -73,7 +74,7 @@ func (t *Tracee) handleEvents(ctx context.Context, initialized chan<- struct{})
7374

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

76-
if t.config.EngineConfig.Enabled {
77+
if t.config.EngineConfig.Mode == engine.ModeSingleBinary {
7778
eventsChan, errc = t.engineEvents(ctx, eventsChan)
7879
errcList = append(errcList, errc)
7980
}
@@ -609,7 +610,7 @@ func (t *Tracee) sinkEvents(ctx context.Context, in <-chan *trace.Event) <-chan
609610
event.MatchedPolicies = t.policyManager.MatchedNames(event.MatchedPoliciesUser)
610611

611612
// Parse args here if the rule engine is NOT enabled (parsed there if it is).
612-
if t.config.Output.ParseArguments && !t.config.EngineConfig.Enabled {
613+
if t.config.Output.ParseArguments && t.config.EngineConfig.Mode != engine.ModeSingleBinary {
613614
err := t.parseArguments(event)
614615
if err != nil {
615616
t.handleError(err)

pkg/signatures/engine/engine.go

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

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

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

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

0 commit comments

Comments
 (0)