diff --git a/go.mod b/go.mod index 64dec0be9357..9d9c48c2f1dc 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/Masterminds/sprig/v3 v3.2.3 github.com/aquasecurity/libbpfgo v0.7.0-libbpf-1.4.0.20240729111821-61d531acf4ca github.com/aquasecurity/tracee/api v0.0.0-20240905132323-d1eaeef6a19f - github.com/aquasecurity/tracee/signatures/helpers v0.0.0-20240607205742-90c301111aee + github.com/aquasecurity/tracee/signatures/helpers v0.0.0-20241009193135-0b23713fa9f9 github.com/aquasecurity/tracee/types v0.0.0-20241008181102-d40bc1f81863 github.com/containerd/containerd v1.7.21 github.com/docker/docker v26.1.5+incompatible diff --git a/go.sum b/go.sum index 4ca5340269ee..9a7f30106857 100644 --- a/go.sum +++ b/go.sum @@ -408,8 +408,8 @@ github.com/aquasecurity/libbpfgo v0.7.0-libbpf-1.4.0.20240729111821-61d531acf4ca github.com/aquasecurity/libbpfgo v0.7.0-libbpf-1.4.0.20240729111821-61d531acf4ca/go.mod h1:UpO6kTehEgAGGKR2twztBxvzjTiLiV/cb2xmlYb+TfE= github.com/aquasecurity/tracee/api v0.0.0-20240905132323-d1eaeef6a19f h1:O4UmMQViaaP1wKL1eXe7C6VylwrUmUB5mYM+roqnUZg= github.com/aquasecurity/tracee/api v0.0.0-20240905132323-d1eaeef6a19f/go.mod h1:Gn6xVkaBkVe1pOQ0++uuHl+lMMClv0TPY8mCQ6j88aA= -github.com/aquasecurity/tracee/signatures/helpers v0.0.0-20240607205742-90c301111aee h1:1KJy6Z2bSpmKQVPShU7hhbXgGVOgMwvzf9rjoWMTYEg= -github.com/aquasecurity/tracee/signatures/helpers v0.0.0-20240607205742-90c301111aee/go.mod h1:SX08YRCsPFh8CvCvzkV8FSn1sqWAarNVEJq9RSZoF/8= +github.com/aquasecurity/tracee/signatures/helpers v0.0.0-20241009193135-0b23713fa9f9 h1:sB84YYSDgUAYNSonXeMPweaN6dviCld8UNqcKDn1jBM= +github.com/aquasecurity/tracee/signatures/helpers v0.0.0-20241009193135-0b23713fa9f9/go.mod h1:/eGxScU8+vnxYhchZ72Y0lv1HqTSooLvtGCt9x7450I= github.com/aquasecurity/tracee/types v0.0.0-20241008181102-d40bc1f81863 h1:domVTTQICTuCvX+ZW5EjvdUBz8EH7FedBj5lRqwpgf4= github.com/aquasecurity/tracee/types v0.0.0-20241008181102-d40bc1f81863/go.mod h1:Jwh9OOuiMHXDoGQY12N9ls5YB+j1FlRcXvFMvh1CmIU= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= diff --git a/pkg/cmd/cobra/cobra.go b/pkg/cmd/cobra/cobra.go index a37aa9e70c32..fafbd43bc657 100644 --- a/pkg/cmd/cobra/cobra.go +++ b/pkg/cmd/cobra/cobra.go @@ -331,9 +331,6 @@ func GetTraceeRunner(c *cobra.Command, version string) (cmd.Runner, error) { runner.Printer = p runner.InstallPath = traceeInstallPath - // parse arguments must be enabled if the rule engine is part of the pipeline - runner.TraceeConfig.Output.ParseArguments = true - runner.TraceeConfig.EngineConfig = engine.Config{ Enabled: true, SigNameToEventID: sigNameToEventId, diff --git a/pkg/ebpf/events_pipeline.go b/pkg/ebpf/events_pipeline.go index fa1eb2b16887..edfb72416627 100644 --- a/pkg/ebpf/events_pipeline.go +++ b/pkg/ebpf/events_pipeline.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/binary" + "slices" "strconv" "sync" "unsafe" @@ -536,10 +537,13 @@ func (t *Tracee) deriveEvents(ctx context.Context, in <-chan *trace.Event) ( // acting on the derived event. eventCopy := *event + // shallow clone the event arguments (new slice is created) before deriving the copy, + // to ensure the original event arguments are not modified by the derivation stage. + argsCopy := slices.Clone(event.Args) out <- event // Note: event is being derived before any of its args are parsed. - derivatives, errors := t.eventDerivations.DeriveEvent(eventCopy) + derivatives, errors := t.eventDerivations.DeriveEvent(eventCopy, argsCopy) for _, err := range errors { t.handleError(err) @@ -614,8 +618,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) @@ -727,15 +731,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 diff --git a/pkg/ebpf/signature_engine.go b/pkg/ebpf/signature_engine.go index 32376c9420b3..a0d66ef83799 100644 --- a/pkg/ebpf/signature_engine.go +++ b/pkg/ebpf/signature_engine.go @@ -2,6 +2,7 @@ package ebpf import ( "context" + "slices" "github.com/aquasecurity/tracee/pkg/containers" "github.com/aquasecurity/tracee/pkg/dnscache" @@ -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 } diff --git a/pkg/events/derive/derive.go b/pkg/events/derive/derive.go index af7000b3737e..1ecfd11e2c53 100644 --- a/pkg/events/derive/derive.go +++ b/pkg/events/derive/derive.go @@ -1,6 +1,8 @@ package derive import ( + "slices" + "github.com/aquasecurity/tracee/pkg/events" "github.com/aquasecurity/tracee/types/trace" ) @@ -41,12 +43,15 @@ func (t Table) Register(deriveFrom, deriveTo events.ID, deriveCondition func() b } // DeriveEvent takes a trace.Event and checks if it can derive additional events from it as defined by a derivationTable. -func (t Table) DeriveEvent(event trace.Event) ([]trace.Event, []error) { +func (t Table) DeriveEvent(event trace.Event, origArgs []trace.Argument) ([]trace.Event, []error) { derivatives := []trace.Event{} errors := []error{} deriveFns := t[events.ID(event.EventID)] for id, deriveFn := range deriveFns { if deriveFn.Enabled() { + // at each derivation, we need use a copy of the original arguments, + // since they might be modified by a previous derivation. + event.Args = slices.Clone(origArgs) derivative, errs := deriveFn.DeriveFunction(event) for _, err := range errs { errors = append(errors, deriveError(id, err)) diff --git a/pkg/events/derive/derive_test.go b/pkg/events/derive/derive_test.go index 4932b7418fc7..e69f1c6bf660 100644 --- a/pkg/events/derive/derive_test.go +++ b/pkg/events/derive/derive_test.go @@ -2,6 +2,7 @@ package derive import ( "fmt" + "slices" "testing" "github.com/stretchr/testify/assert" @@ -74,7 +75,8 @@ func Test_DeriveEvent(t *testing.T) { t.Run(tc.name, func(t *testing.T) { t.Parallel() - derived, errors := mockDerivationTable.DeriveEvent(tc.event) + argsCopy := slices.Clone(tc.event.Args) + derived, errors := mockDerivationTable.DeriveEvent(tc.event, argsCopy) assert.Equal(t, tc.expectedDerived, derived) assert.Equal(t, tc.expectedErrors, errors) }) diff --git a/pkg/signatures/benchmark/signature/golang/anti_debugging.go b/pkg/signatures/benchmark/signature/golang/anti_debugging.go index 16b94d8c4f2d..b892dd037fca 100644 --- a/pkg/signatures/benchmark/signature/golang/anti_debugging.go +++ b/pkg/signatures/benchmark/signature/golang/anti_debugging.go @@ -3,6 +3,7 @@ package golang import ( "fmt" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/signatures/helpers" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/protocol" @@ -12,6 +13,7 @@ import ( type antiDebugging struct { cb detect.SignatureHandler metadata detect.SignatureMetadata + logger detect.Logger } func NewAntiDebuggingSignature() (detect.Signature, error) { @@ -30,6 +32,7 @@ func NewAntiDebuggingSignature() (detect.Signature, error) { func (sig *antiDebugging) Init(ctx detect.SignatureContext) error { sig.cb = ctx.Callback + sig.logger = ctx.Logger return nil } @@ -52,22 +55,30 @@ func (sig *antiDebugging) OnEvent(event protocol.Event) error { if ee.EventName != "ptrace" { return nil } - request, err := helpers.GetTraceeArgumentByName(ee, "request", helpers.GetArgOps{DefaultArgs: false}) + requestArg, err := helpers.GetTraceeIntArgumentByName(ee, "request") if err != nil { return err } - requestString, ok := request.Value.(string) - if !ok { - return fmt.Errorf("failed to cast request's value") - } - if requestString != "PTRACE_TRACEME" { + + if uint64(requestArg) != parsers.PTRACE_TRACEME.Value() { return nil } + + var ptraceRequestData string + requestString, err := parsers.ParsePtraceRequestArgument(uint64(requestArg)) + + if err != nil { + ptraceRequestData = fmt.Sprint(requestArg) + sig.logger.Debugw("anti_debugging sig: failed to parse ptrace request argument: %v", err) + } else { + ptraceRequestData = requestString.String() + } + sig.cb(&detect.Finding{ SigMetadata: sig.metadata, Event: event, Data: map[string]interface{}{ - "ptrace request": requestString, + "ptrace request": ptraceRequestData, }, }) return nil diff --git a/pkg/signatures/benchmark/signature/golang/code_injection.go b/pkg/signatures/benchmark/signature/golang/code_injection.go index bdef40babea6..a3e99e644d8d 100644 --- a/pkg/signatures/benchmark/signature/golang/code_injection.go +++ b/pkg/signatures/benchmark/signature/golang/code_injection.go @@ -65,11 +65,11 @@ func (sig *codeInjection) OnEvent(event protocol.Event) error { } switch ee.EventName { case "open", "openat": - flags, err := helpers.GetTraceeArgumentByName(ee, "flags", helpers.GetArgOps{DefaultArgs: false}) + flags, err := helpers.GetTraceeIntArgumentByName(ee, "flags") if err != nil { return fmt.Errorf("%v %#v", err, ee) } - if helpers.IsFileWrite(flags.Value.(string)) { + if helpers.IsFileWrite(flags) { pathname, err := helpers.GetTraceeArgumentByName(ee, "pathname", helpers.GetArgOps{DefaultArgs: false}) if err != nil { return err diff --git a/pkg/signatures/regosig/aio.go b/pkg/signatures/regosig/aio.go index 38dea29db2e1..2e95b86c37b6 100644 --- a/pkg/signatures/regosig/aio.go +++ b/pkg/signatures/regosig/aio.go @@ -11,6 +11,7 @@ import ( "github.com/open-policy-agent/opa/compile" "github.com/open-policy-agent/opa/rego" + "github.com/aquasecurity/tracee/pkg/events" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/protocol" "github.com/aquasecurity/tracee/types/trace" @@ -194,6 +195,12 @@ func (a *aio) OnEvent(event protocol.Event) error { if !ok { return fmt.Errorf("failed to cast event's payload") } + + err := events.ParseArgs(&ee) + if err != nil { + return fmt.Errorf("rego aio: failed to parse event data: %v", err) + } + input := rego.EvalInput(ee) ctx := context.TODO() diff --git a/pkg/signatures/regosig/traceerego.go b/pkg/signatures/regosig/traceerego.go index 37aae756bd36..81cea2977915 100644 --- a/pkg/signatures/regosig/traceerego.go +++ b/pkg/signatures/regosig/traceerego.go @@ -11,8 +11,10 @@ import ( "github.com/open-policy-agent/opa/ast" "github.com/open-policy-agent/opa/rego" + "github.com/aquasecurity/tracee/pkg/events" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/protocol" + "github.com/aquasecurity/tracee/types/trace" ) // RegoSignature is an abstract signature that is implemented in rego @@ -158,7 +160,18 @@ func (sig *RegoSignature) getSelectedEvents(pkgName string) ([]detect.SignatureE // if bool is "returned", a true evaluation will generate a Finding with no data // if document is "returned", any non-empty evaluation will generate a Finding with the document as the Finding's "Data" func (sig *RegoSignature) OnEvent(event protocol.Event) error { - input := rego.EvalInput(event.Payload) + ee, ok := event.Payload.(trace.Event) + + if !ok { + return fmt.Errorf("failed to cast event's payload") + } + + err := events.ParseArgs(&ee) + if err != nil { + return fmt.Errorf("rego aio: failed to parse event data: %v", err) + } + + input := rego.EvalInput(ee) results, err := sig.matchPQ.Eval(context.TODO(), input) if err != nil { return fmt.Errorf("evaluating rego: %w", err) diff --git a/pkg/signatures/regosig/traceerego_test.go b/pkg/signatures/regosig/traceerego_test.go index 82e4ae1f212a..5269a99048c9 100644 --- a/pkg/signatures/regosig/traceerego_test.go +++ b/pkg/signatures/regosig/traceerego_test.go @@ -349,6 +349,7 @@ func OnEventSpec(t *testing.T, target string, partial bool) { Payload: "just some stuff", }, finding: nil, + error: "failed to cast event's payload", }, } diff --git a/signatures/golang/anti_debugging_ptraceme.go b/signatures/golang/anti_debugging_ptraceme.go index 9b2fb22afda8..95e80b2b117c 100644 --- a/signatures/golang/anti_debugging_ptraceme.go +++ b/signatures/golang/anti_debugging_ptraceme.go @@ -3,6 +3,7 @@ package main import ( "fmt" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/signatures/helpers" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/protocol" @@ -11,12 +12,12 @@ import ( type AntiDebuggingPtraceme struct { cb detect.SignatureHandler - ptraceTraceMe string + ptraceTraceMe int } func (sig *AntiDebuggingPtraceme) Init(ctx detect.SignatureContext) error { sig.cb = ctx.Callback - sig.ptraceTraceMe = "PTRACE_TRACEME" + sig.ptraceTraceMe = int(parsers.PTRACE_TRACEME.Value()) return nil } @@ -52,7 +53,7 @@ func (sig *AntiDebuggingPtraceme) OnEvent(event protocol.Event) error { switch eventObj.EventName { case "ptrace": - requestArg, err := helpers.GetTraceeStringArgumentByName(eventObj, "request") + requestArg, err := helpers.GetTraceeIntArgumentByName(eventObj, "request") if err != nil { return err } diff --git a/signatures/golang/anti_debugging_ptraceme_test.go b/signatures/golang/anti_debugging_ptraceme_test.go index 39139edb4e41..3d82108d65ce 100644 --- a/signatures/golang/anti_debugging_ptraceme_test.go +++ b/signatures/golang/anti_debugging_ptraceme_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/signatures/signaturestest" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/trace" @@ -29,7 +30,7 @@ func TestAntiDebuggingPtraceme(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "request", }, - Value: interface{}("PTRACE_TRACEME"), + Value: interface{}(int64(parsers.PTRACE_TRACEME.Value())), }, }, }, @@ -44,7 +45,7 @@ func TestAntiDebuggingPtraceme(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "request", }, - Value: interface{}("PTRACE_TRACEME"), + Value: interface{}(int64(parsers.PTRACE_TRACEME.Value())), }, }, }.ToProtocol(), @@ -76,7 +77,7 @@ func TestAntiDebuggingPtraceme(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "request", }, - Value: interface{}("PTRACE_PEEKTEXT"), + Value: interface{}(int64(parsers.PTRACE_PEEKTEXT.Value())), }, }, }, diff --git a/signatures/golang/aslr_inspection.go b/signatures/golang/aslr_inspection.go index e16855f980a8..87f88989356f 100644 --- a/signatures/golang/aslr_inspection.go +++ b/signatures/golang/aslr_inspection.go @@ -57,7 +57,7 @@ func (sig *AslrInspection) OnEvent(event protocol.Event) error { return err } - flags, err := helpers.GetTraceeStringArgumentByName(eventObj, "flags") + flags, err := helpers.GetTraceeIntArgumentByName(eventObj, "flags") if err != nil { return err } diff --git a/signatures/golang/aslr_inspection_test.go b/signatures/golang/aslr_inspection_test.go index 39264499e6a3..e8e3b39ed98c 100644 --- a/signatures/golang/aslr_inspection_test.go +++ b/signatures/golang/aslr_inspection_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/signatures/signaturestest" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/trace" @@ -29,7 +30,7 @@ func TestAslrInspection(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: interface{}(buildFlagArgValue(parsers.O_RDONLY)), }, { ArgMeta: trace.ArgMeta{ @@ -50,7 +51,7 @@ func TestAslrInspection(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: interface{}(buildFlagArgValue(parsers.O_RDONLY)), }, { ArgMeta: trace.ArgMeta{ @@ -94,7 +95,7 @@ func TestAslrInspection(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: interface{}(buildFlagArgValue(parsers.O_WRONLY)), }, }, }, @@ -111,7 +112,7 @@ func TestAslrInspection(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: interface{}(buildFlagArgValue(parsers.O_RDONLY)), }, { ArgMeta: trace.ArgMeta{ diff --git a/signatures/golang/cgroup_notify_on_release_modification.go b/signatures/golang/cgroup_notify_on_release_modification.go index 1f018e0cdd28..ef5057976f04 100644 --- a/signatures/golang/cgroup_notify_on_release_modification.go +++ b/signatures/golang/cgroup_notify_on_release_modification.go @@ -59,7 +59,7 @@ func (sig *CgroupNotifyOnReleaseModification) OnEvent(event protocol.Event) erro } basename := path.Base(pathname) - flags, err := helpers.GetTraceeStringArgumentByName(eventObj, "flags") + flags, err := helpers.GetTraceeIntArgumentByName(eventObj, "flags") if err != nil { return err } diff --git a/signatures/golang/cgroup_notify_on_release_modification_test.go b/signatures/golang/cgroup_notify_on_release_modification_test.go index 661f77b149ad..d6507a3f65ff 100644 --- a/signatures/golang/cgroup_notify_on_release_modification_test.go +++ b/signatures/golang/cgroup_notify_on_release_modification_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/signatures/signaturestest" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/trace" @@ -35,7 +36,7 @@ func TestCgroupNotifyOnReleaseModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: interface{}(buildFlagArgValue(parsers.O_WRONLY)), }, }, }, @@ -56,7 +57,7 @@ func TestCgroupNotifyOnReleaseModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: interface{}(buildFlagArgValue(parsers.O_WRONLY)), }, }, }.ToProtocol(), @@ -94,7 +95,7 @@ func TestCgroupNotifyOnReleaseModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: interface{}(buildFlagArgValue(parsers.O_RDONLY)), }, }, }, @@ -117,7 +118,7 @@ func TestCgroupNotifyOnReleaseModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: interface{}(buildFlagArgValue(parsers.O_WRONLY)), }, }, }, diff --git a/signatures/golang/cgroup_release_agent_modification.go b/signatures/golang/cgroup_release_agent_modification.go index 87685fcf2cad..fd9fa537a93e 100644 --- a/signatures/golang/cgroup_release_agent_modification.go +++ b/signatures/golang/cgroup_release_agent_modification.go @@ -56,7 +56,7 @@ func (sig *CgroupReleaseAgentModification) OnEvent(event protocol.Event) error { switch eventObj.EventName { case "security_file_open": - flags, err := helpers.GetTraceeStringArgumentByName(eventObj, "flags") + flags, err := helpers.GetTraceeIntArgumentByName(eventObj, "flags") if err != nil { return err } diff --git a/signatures/golang/cgroup_release_agent_modification_test.go b/signatures/golang/cgroup_release_agent_modification_test.go index 262e33a31218..bce02349d280 100644 --- a/signatures/golang/cgroup_release_agent_modification_test.go +++ b/signatures/golang/cgroup_release_agent_modification_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/signatures/signaturestest" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/trace" @@ -35,7 +36,7 @@ func TestCgroupReleaseAgentModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: interface{}(buildFlagArgValue(parsers.O_WRONLY)), }, }, }, @@ -56,7 +57,7 @@ func TestCgroupReleaseAgentModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: interface{}(buildFlagArgValue(parsers.O_WRONLY)), }, }, }.ToProtocol(), @@ -141,7 +142,7 @@ func TestCgroupReleaseAgentModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: interface{}(buildFlagArgValue(parsers.O_RDONLY)), }, }, }, @@ -164,7 +165,7 @@ func TestCgroupReleaseAgentModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: interface{}(buildFlagArgValue(parsers.O_WRONLY)), }, }, }, diff --git a/signatures/golang/core_pattern_modification.go b/signatures/golang/core_pattern_modification.go index 5672a56c5629..4949ab7c7752 100644 --- a/signatures/golang/core_pattern_modification.go +++ b/signatures/golang/core_pattern_modification.go @@ -58,7 +58,7 @@ func (sig *CorePatternModification) OnEvent(event protocol.Event) error { return err } - flags, err := helpers.GetTraceeStringArgumentByName(eventObj, "flags") + flags, err := helpers.GetTraceeIntArgumentByName(eventObj, "flags") if err != nil { return err } diff --git a/signatures/golang/core_pattern_modification_test.go b/signatures/golang/core_pattern_modification_test.go index d2877db9b7e9..9c1d26b61808 100644 --- a/signatures/golang/core_pattern_modification_test.go +++ b/signatures/golang/core_pattern_modification_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/signatures/signaturestest" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/trace" @@ -35,7 +36,7 @@ func TestCorePatternModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, }, }, @@ -56,7 +57,7 @@ func TestCorePatternModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, }, }.ToProtocol(), @@ -94,7 +95,7 @@ func TestCorePatternModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, }, }, @@ -117,7 +118,7 @@ func TestCorePatternModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, }, }, diff --git a/signatures/golang/default_loader_modification.go b/signatures/golang/default_loader_modification.go index d2a2df58c1e0..738953d81fc0 100644 --- a/signatures/golang/default_loader_modification.go +++ b/signatures/golang/default_loader_modification.go @@ -59,7 +59,7 @@ func (sig *DefaultLoaderModification) OnEvent(event protocol.Event) error { switch eventObj.EventName { case "security_file_open": - flags, err := helpers.GetTraceeStringArgumentByName(eventObj, "flags") + flags, err := helpers.GetTraceeIntArgumentByName(eventObj, "flags") if err != nil { return err } diff --git a/signatures/golang/default_loader_modification_test.go b/signatures/golang/default_loader_modification_test.go index a33e2300896d..094b70f8fafb 100644 --- a/signatures/golang/default_loader_modification_test.go +++ b/signatures/golang/default_loader_modification_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/signatures/signaturestest" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/trace" @@ -35,7 +36,7 @@ func TestDefaultLoaderModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, }, }, @@ -56,7 +57,7 @@ func TestDefaultLoaderModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, }, }.ToProtocol(), @@ -141,7 +142,7 @@ func TestDefaultLoaderModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, }, }, @@ -164,7 +165,7 @@ func TestDefaultLoaderModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, }, }, diff --git a/signatures/golang/docker_abuse.go b/signatures/golang/docker_abuse.go index 9671f763c56c..7d2bfa3b11bd 100644 --- a/signatures/golang/docker_abuse.go +++ b/signatures/golang/docker_abuse.go @@ -61,7 +61,7 @@ func (sig *DockerAbuse) OnEvent(event protocol.Event) error { return err } - flags, err := helpers.GetTraceeStringArgumentByName(eventObj, "flags") + flags, err := helpers.GetTraceeIntArgumentByName(eventObj, "flags") if err != nil { return err } diff --git a/signatures/golang/docker_abuse_test.go b/signatures/golang/docker_abuse_test.go index 5ba66e94b766..24fde9746bba 100644 --- a/signatures/golang/docker_abuse_test.go +++ b/signatures/golang/docker_abuse_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/signatures/signaturestest" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/trace" @@ -30,7 +31,7 @@ func TestDockerAbuse(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, { ArgMeta: trace.ArgMeta{ @@ -52,7 +53,7 @@ func TestDockerAbuse(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, { ArgMeta: trace.ArgMeta{ @@ -140,7 +141,7 @@ func TestDockerAbuse(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, { ArgMeta: trace.ArgMeta{ @@ -164,7 +165,7 @@ func TestDockerAbuse(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, { ArgMeta: trace.ArgMeta{ diff --git a/signatures/golang/dynamic_code_loading.go b/signatures/golang/dynamic_code_loading.go index be148f9b5484..7e1245cd1513 100644 --- a/signatures/golang/dynamic_code_loading.go +++ b/signatures/golang/dynamic_code_loading.go @@ -11,12 +11,12 @@ import ( type DynamicCodeLoading struct { cb detect.SignatureHandler - alertText string + alertType trace.MemProtAlert } func (sig *DynamicCodeLoading) Init(ctx detect.SignatureContext) error { sig.cb = ctx.Callback - sig.alertText = "Protection changed from W to E!" + sig.alertType = trace.ProtAlertMprotectWXToX return nil } @@ -52,12 +52,13 @@ func (sig *DynamicCodeLoading) OnEvent(event protocol.Event) error { switch eventObj.EventName { case "mem_prot_alert": - alert, err := helpers.GetTraceeStringArgumentByName(eventObj, "alert") + alert, err := helpers.GetTraceeUintArgumentByName(eventObj, "alert") if err != nil { return err } + memProtAlert := trace.MemProtAlert(alert) - if alert == sig.alertText { + if memProtAlert == sig.alertType { metadata, err := sig.GetMetadata() if err != nil { return err diff --git a/signatures/golang/dynamic_code_loading_test.go b/signatures/golang/dynamic_code_loading_test.go index b7dec8a46208..51ab065f5056 100644 --- a/signatures/golang/dynamic_code_loading_test.go +++ b/signatures/golang/dynamic_code_loading_test.go @@ -29,7 +29,7 @@ func TestDynamicCodeLoading(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "alert", }, - Value: interface{}("Protection changed from W to E!"), + Value: uint32(trace.ProtAlertMprotectWXToX), }, }, }, @@ -44,7 +44,7 @@ func TestDynamicCodeLoading(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "alert", }, - Value: interface{}("Protection changed from W to E!"), + Value: uint32(trace.ProtAlertMprotectWXToX), }, }, }.ToProtocol(), @@ -76,7 +76,7 @@ func TestDynamicCodeLoading(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "alert", }, - Value: interface{}("Protection changed to Executable!"), + Value: uint32(trace.ProtAlertMmapWX), }, }, }, diff --git a/signatures/golang/k8s_service_account_token.go b/signatures/golang/k8s_service_account_token.go index d721b3ac83c7..4e861b41629b 100644 --- a/signatures/golang/k8s_service_account_token.go +++ b/signatures/golang/k8s_service_account_token.go @@ -70,7 +70,7 @@ func (sig *K8SServiceAccountToken) OnEvent(event protocol.Event) error { return err } - flags, err := helpers.GetTraceeStringArgumentByName(eventObj, "flags") + flags, err := helpers.GetTraceeIntArgumentByName(eventObj, "flags") if err != nil { return err } diff --git a/signatures/golang/k8s_service_account_token_test.go b/signatures/golang/k8s_service_account_token_test.go index 57e46a05eb4f..b06accf1c869 100644 --- a/signatures/golang/k8s_service_account_token_test.go +++ b/signatures/golang/k8s_service_account_token_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/signatures/signaturestest" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/trace" @@ -30,7 +31,7 @@ func TestK8SServiceAccountToken(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, { ArgMeta: trace.ArgMeta{ @@ -52,7 +53,7 @@ func TestK8SServiceAccountToken(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, { ArgMeta: trace.ArgMeta{ @@ -91,7 +92,7 @@ func TestK8SServiceAccountToken(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, { ArgMeta: trace.ArgMeta{ @@ -115,7 +116,7 @@ func TestK8SServiceAccountToken(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, { ArgMeta: trace.ArgMeta{ @@ -139,7 +140,7 @@ func TestK8SServiceAccountToken(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, { ArgMeta: trace.ArgMeta{ diff --git a/signatures/golang/kernel_module_loading.go b/signatures/golang/kernel_module_loading.go index 37fd1f8a716e..2cdbb0e0a232 100644 --- a/signatures/golang/kernel_module_loading.go +++ b/signatures/golang/kernel_module_loading.go @@ -61,22 +61,29 @@ func (sig *KernelModuleLoading) OnEvent(event protocol.Event) error { Data: nil, }) case "security_kernel_read_file": - loadedType, err := helpers.GetTraceeStringArgumentByName(eventObj, "type") + loadedType, err := helpers.GetTraceeArgumentByName(eventObj, "type", helpers.GetArgOps{}) if err != nil { return err } - if loadedType == "kernel-module" { - metadata, err := sig.GetMetadata() - if err != nil { - return err - } - sig.cb(&detect.Finding{ - SigMetadata: metadata, - Event: event, - Data: nil, - }) + kernelReadType, ok := loadedType.Value.(trace.KernelReadType) + if !ok { + return nil } + + if kernelReadType != trace.KernelReadKernelModule { + return nil + } + + metadata, err := sig.GetMetadata() + if err != nil { + return err + } + sig.cb(&detect.Finding{ + SigMetadata: metadata, + Event: event, + Data: nil, + }) } return nil diff --git a/signatures/golang/kernel_module_loading_test.go b/signatures/golang/kernel_module_loading_test.go index 013288ea485f..09ebe989b53b 100644 --- a/signatures/golang/kernel_module_loading_test.go +++ b/signatures/golang/kernel_module_loading_test.go @@ -60,7 +60,7 @@ func TestKernelModuleLoading(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "type", }, - Value: interface{}("kernel-module"), + Value: trace.KernelReadKernelModule, }, }, }, @@ -75,7 +75,7 @@ func TestKernelModuleLoading(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "type", }, - Value: interface{}("kernel-module"), + Value: trace.KernelReadKernelModule, }, }, }.ToProtocol(), @@ -107,7 +107,7 @@ func TestKernelModuleLoading(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "type", }, - Value: interface{}("firmware"), + Value: trace.KernelReadFirmware, }, }, }, diff --git a/signatures/golang/kubernetes_certificate_theft_attempt.go b/signatures/golang/kubernetes_certificate_theft_attempt.go index 847b5b388c0f..aeb1b7389721 100644 --- a/signatures/golang/kubernetes_certificate_theft_attempt.go +++ b/signatures/golang/kubernetes_certificate_theft_attempt.go @@ -65,7 +65,7 @@ func (sig *KubernetesCertificateTheftAttempt) OnEvent(event protocol.Event) erro } } - flags, err := helpers.GetTraceeStringArgumentByName(eventObj, "flags") + flags, err := helpers.GetTraceeIntArgumentByName(eventObj, "flags") if err != nil { return err } diff --git a/signatures/golang/kubernetes_certificate_theft_attempt_test.go b/signatures/golang/kubernetes_certificate_theft_attempt_test.go index 852642d768d8..b5f8b35a1121 100644 --- a/signatures/golang/kubernetes_certificate_theft_attempt_test.go +++ b/signatures/golang/kubernetes_certificate_theft_attempt_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/signatures/signaturestest" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/trace" @@ -30,7 +31,7 @@ func TestKubernetesCertificateTheftAttempt(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, { ArgMeta: trace.ArgMeta{ @@ -52,7 +53,7 @@ func TestKubernetesCertificateTheftAttempt(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, { ArgMeta: trace.ArgMeta{ @@ -138,7 +139,7 @@ func TestKubernetesCertificateTheftAttempt(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, { ArgMeta: trace.ArgMeta{ @@ -162,7 +163,7 @@ func TestKubernetesCertificateTheftAttempt(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, { ArgMeta: trace.ArgMeta{ @@ -186,7 +187,7 @@ func TestKubernetesCertificateTheftAttempt(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, { ArgMeta: trace.ArgMeta{ diff --git a/signatures/golang/ld_preload.go b/signatures/golang/ld_preload.go index 181e6ab27dbe..6ff59e806eb2 100644 --- a/signatures/golang/ld_preload.go +++ b/signatures/golang/ld_preload.go @@ -85,7 +85,7 @@ func (sig *LdPreload) OnEvent(event protocol.Event) error { return err } - flags, err := helpers.GetTraceeStringArgumentByName(eventObj, "flags") + flags, err := helpers.GetTraceeIntArgumentByName(eventObj, "flags") if err != nil { return err } diff --git a/signatures/golang/ld_preload_test.go b/signatures/golang/ld_preload_test.go index 4d884cbf4c51..42ae921dd3bb 100644 --- a/signatures/golang/ld_preload_test.go +++ b/signatures/golang/ld_preload_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/signatures/signaturestest" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/trace" @@ -29,7 +30,7 @@ func TestLdPreload(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, { ArgMeta: trace.ArgMeta{ @@ -50,7 +51,7 @@ func TestLdPreload(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, { ArgMeta: trace.ArgMeta{ @@ -194,7 +195,7 @@ func TestLdPreload(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, { ArgMeta: trace.ArgMeta{ @@ -217,7 +218,7 @@ func TestLdPreload(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, { ArgMeta: trace.ArgMeta{ diff --git a/signatures/golang/proc_kcore_read.go b/signatures/golang/proc_kcore_read.go index 7a39d91f0573..29400b527f23 100644 --- a/signatures/golang/proc_kcore_read.go +++ b/signatures/golang/proc_kcore_read.go @@ -58,7 +58,7 @@ func (sig *ProcKcoreRead) OnEvent(event protocol.Event) error { return err } - flags, err := helpers.GetTraceeStringArgumentByName(eventObj, "flags") + flags, err := helpers.GetTraceeIntArgumentByName(eventObj, "flags") if err != nil { return err } diff --git a/signatures/golang/proc_kcore_read_test.go b/signatures/golang/proc_kcore_read_test.go index 6e05960bb7ec..c6ad61f1ae77 100644 --- a/signatures/golang/proc_kcore_read_test.go +++ b/signatures/golang/proc_kcore_read_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/signatures/signaturestest" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/trace" @@ -29,7 +30,7 @@ func TestProcKcoreRead(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, { ArgMeta: trace.ArgMeta{ @@ -50,7 +51,7 @@ func TestProcKcoreRead(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, { ArgMeta: trace.ArgMeta{ @@ -94,7 +95,7 @@ func TestProcKcoreRead(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, }, }, @@ -117,7 +118,7 @@ func TestProcKcoreRead(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, }, }, diff --git a/signatures/golang/proc_mem_access.go b/signatures/golang/proc_mem_access.go index e1f80b911067..a742ec9e3813 100644 --- a/signatures/golang/proc_mem_access.go +++ b/signatures/golang/proc_mem_access.go @@ -61,7 +61,7 @@ func (sig *ProcMemAccess) OnEvent(event protocol.Event) error { return err } - flags, err := helpers.GetTraceeStringArgumentByName(eventObj, "flags") + flags, err := helpers.GetTraceeIntArgumentByName(eventObj, "flags") if err != nil { return err } diff --git a/signatures/golang/proc_mem_access_test.go b/signatures/golang/proc_mem_access_test.go index 1fbd0ee93816..4c262cafd792 100644 --- a/signatures/golang/proc_mem_access_test.go +++ b/signatures/golang/proc_mem_access_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/signatures/signaturestest" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/trace" @@ -29,7 +30,7 @@ func TestProcMemAccess(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, { ArgMeta: trace.ArgMeta{ @@ -50,7 +51,7 @@ func TestProcMemAccess(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, { ArgMeta: trace.ArgMeta{ @@ -88,7 +89,7 @@ func TestProcMemAccess(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, { ArgMeta: trace.ArgMeta{ @@ -111,7 +112,7 @@ func TestProcMemAccess(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, { ArgMeta: trace.ArgMeta{ diff --git a/signatures/golang/proc_mem_code_injection.go b/signatures/golang/proc_mem_code_injection.go index 6dc7d84bfb17..4e935d36d578 100644 --- a/signatures/golang/proc_mem_code_injection.go +++ b/signatures/golang/proc_mem_code_injection.go @@ -61,7 +61,7 @@ func (sig *ProcMemCodeInjection) OnEvent(event protocol.Event) error { return err } - flags, err := helpers.GetTraceeStringArgumentByName(eventObj, "flags") + flags, err := helpers.GetTraceeIntArgumentByName(eventObj, "flags") if err != nil { return err } diff --git a/signatures/golang/proc_mem_code_injection_test.go b/signatures/golang/proc_mem_code_injection_test.go index 90a20c8b8e2f..92600803d1b8 100644 --- a/signatures/golang/proc_mem_code_injection_test.go +++ b/signatures/golang/proc_mem_code_injection_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/signatures/signaturestest" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/trace" @@ -29,7 +30,7 @@ func TestProcMemCodeInjection(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, { ArgMeta: trace.ArgMeta{ @@ -50,7 +51,7 @@ func TestProcMemCodeInjection(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, { ArgMeta: trace.ArgMeta{ @@ -88,7 +89,7 @@ func TestProcMemCodeInjection(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, { ArgMeta: trace.ArgMeta{ @@ -111,7 +112,7 @@ func TestProcMemCodeInjection(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, { ArgMeta: trace.ArgMeta{ diff --git a/signatures/golang/ptrace_code_injection.go b/signatures/golang/ptrace_code_injection.go index 593701d4903b..b6eb6ceeb1d5 100644 --- a/signatures/golang/ptrace_code_injection.go +++ b/signatures/golang/ptrace_code_injection.go @@ -3,6 +3,7 @@ package main import ( "fmt" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/signatures/helpers" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/protocol" @@ -11,14 +12,14 @@ import ( type PtraceCodeInjection struct { cb detect.SignatureHandler - ptracePokeText string - ptracePokeData string + ptracePokeText int + ptracePokeData int } func (sig *PtraceCodeInjection) Init(ctx detect.SignatureContext) error { sig.cb = ctx.Callback - sig.ptracePokeText = "PTRACE_POKETEXT" - sig.ptracePokeData = "PTRACE_POKEDATA" + sig.ptracePokeText = int(parsers.PTRACE_POKETEXT.Value()) + sig.ptracePokeData = int(parsers.PTRACE_POKEDATA.Value()) return nil } @@ -54,7 +55,7 @@ func (sig *PtraceCodeInjection) OnEvent(event protocol.Event) error { switch eventObj.EventName { case "ptrace": - requestArg, err := helpers.GetTraceeStringArgumentByName(eventObj, "request") + requestArg, err := helpers.GetTraceeIntArgumentByName(eventObj, "request") if err != nil { return err } diff --git a/signatures/golang/ptrace_code_injection_test.go b/signatures/golang/ptrace_code_injection_test.go index d882a4365b16..5f1424e25ebb 100644 --- a/signatures/golang/ptrace_code_injection_test.go +++ b/signatures/golang/ptrace_code_injection_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/signatures/signaturestest" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/trace" @@ -29,7 +30,7 @@ func TestPtraceCodeInjection(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "request", }, - Value: interface{}("PTRACE_POKETEXT"), + Value: int32(parsers.PTRACE_POKETEXT.Value()), }, }, }, @@ -44,7 +45,7 @@ func TestPtraceCodeInjection(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "request", }, - Value: interface{}("PTRACE_POKETEXT"), + Value: int32(parsers.PTRACE_POKETEXT.Value()), }, }, }.ToProtocol(), @@ -76,7 +77,7 @@ func TestPtraceCodeInjection(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "request", }, - Value: interface{}("PTRACE_POKEDATA"), + Value: int32(parsers.PTRACE_POKEDATA.Value()), }, }, }, @@ -91,7 +92,7 @@ func TestPtraceCodeInjection(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "request", }, - Value: interface{}("PTRACE_POKEDATA"), + Value: int32(parsers.PTRACE_POKEDATA.Value()), }, }, }.ToProtocol(), @@ -123,7 +124,7 @@ func TestPtraceCodeInjection(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "request", }, - Value: interface{}("PTRACE_PEEKTEXT"), + Value: int32(parsers.PTRACE_PEEKTEXT.Value()), }, }, }, diff --git a/signatures/golang/rcd_modification.go b/signatures/golang/rcd_modification.go index fa4e0cdba68a..336338f96986 100644 --- a/signatures/golang/rcd_modification.go +++ b/signatures/golang/rcd_modification.go @@ -65,7 +65,7 @@ func (sig *RcdModification) OnEvent(event protocol.Event) error { return err } - flags, err := helpers.GetTraceeStringArgumentByName(eventObj, "flags") + flags, err := helpers.GetTraceeIntArgumentByName(eventObj, "flags") if err != nil { return err } diff --git a/signatures/golang/rcd_modification_test.go b/signatures/golang/rcd_modification_test.go index eae82c3fb26f..ba1f5131776f 100644 --- a/signatures/golang/rcd_modification_test.go +++ b/signatures/golang/rcd_modification_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/signatures/signaturestest" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/trace" @@ -29,7 +30,7 @@ func TestRcdModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, { ArgMeta: trace.ArgMeta{ @@ -50,7 +51,7 @@ func TestRcdModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, { ArgMeta: trace.ArgMeta{ @@ -88,7 +89,7 @@ func TestRcdModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, { ArgMeta: trace.ArgMeta{ @@ -109,7 +110,7 @@ func TestRcdModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, { ArgMeta: trace.ArgMeta{ @@ -288,7 +289,7 @@ func TestRcdModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, { ArgMeta: trace.ArgMeta{ @@ -311,7 +312,7 @@ func TestRcdModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, { ArgMeta: trace.ArgMeta{ diff --git a/signatures/golang/sched_debug_recon.go b/signatures/golang/sched_debug_recon.go index 6c10283fbb44..88335f820c50 100644 --- a/signatures/golang/sched_debug_recon.go +++ b/signatures/golang/sched_debug_recon.go @@ -57,7 +57,7 @@ func (sig *SchedDebugRecon) OnEvent(event protocol.Event) error { return err } - flags, err := helpers.GetTraceeStringArgumentByName(eventObj, "flags") + flags, err := helpers.GetTraceeIntArgumentByName(eventObj, "flags") if err != nil { return err } diff --git a/signatures/golang/sched_debug_recon_test.go b/signatures/golang/sched_debug_recon_test.go index 51db29b0d3eb..8337184f45d2 100644 --- a/signatures/golang/sched_debug_recon_test.go +++ b/signatures/golang/sched_debug_recon_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/signatures/signaturestest" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/trace" @@ -29,7 +30,7 @@ func TestSchedDebugRecon(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, { ArgMeta: trace.ArgMeta{ @@ -50,7 +51,7 @@ func TestSchedDebugRecon(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, { ArgMeta: trace.ArgMeta{ @@ -88,7 +89,7 @@ func TestSchedDebugRecon(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, { ArgMeta: trace.ArgMeta{ @@ -111,7 +112,7 @@ func TestSchedDebugRecon(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, { ArgMeta: trace.ArgMeta{ diff --git a/signatures/golang/scheduled_task_modification.go b/signatures/golang/scheduled_task_modification.go index a7564e78bd04..fe52daf8f43e 100644 --- a/signatures/golang/scheduled_task_modification.go +++ b/signatures/golang/scheduled_task_modification.go @@ -65,7 +65,7 @@ func (sig *ScheduledTaskModification) OnEvent(event protocol.Event) error { return err } - flags, err := helpers.GetTraceeStringArgumentByName(eventObj, "flags") + flags, err := helpers.GetTraceeIntArgumentByName(eventObj, "flags") if err != nil { return err } diff --git a/signatures/golang/scheduled_task_modification_test.go b/signatures/golang/scheduled_task_modification_test.go index c25abcb776ce..f3b1e8de1880 100644 --- a/signatures/golang/scheduled_task_modification_test.go +++ b/signatures/golang/scheduled_task_modification_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/signatures/signaturestest" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/trace" @@ -29,7 +30,7 @@ func TestScheduledTaskModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, { ArgMeta: trace.ArgMeta{ @@ -50,7 +51,7 @@ func TestScheduledTaskModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, { ArgMeta: trace.ArgMeta{ @@ -88,7 +89,7 @@ func TestScheduledTaskModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, { ArgMeta: trace.ArgMeta{ @@ -109,7 +110,7 @@ func TestScheduledTaskModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, { ArgMeta: trace.ArgMeta{ @@ -288,7 +289,7 @@ func TestScheduledTaskModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, { ArgMeta: trace.ArgMeta{ @@ -311,7 +312,7 @@ func TestScheduledTaskModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, { ArgMeta: trace.ArgMeta{ diff --git a/signatures/golang/sudoers_modification.go b/signatures/golang/sudoers_modification.go index 74973699e87b..90c4d90a1775 100644 --- a/signatures/golang/sudoers_modification.go +++ b/signatures/golang/sudoers_modification.go @@ -59,7 +59,7 @@ func (sig *SudoersModification) OnEvent(event protocol.Event) error { switch eventObj.EventName { case "security_file_open": - flags, err := helpers.GetTraceeStringArgumentByName(eventObj, "flags") + flags, err := helpers.GetTraceeIntArgumentByName(eventObj, "flags") if err != nil { return err } diff --git a/signatures/golang/sudoers_modification_test.go b/signatures/golang/sudoers_modification_test.go index 544392eb3d92..209749cb06ef 100644 --- a/signatures/golang/sudoers_modification_test.go +++ b/signatures/golang/sudoers_modification_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/signatures/signaturestest" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/trace" @@ -35,7 +36,7 @@ func TestSudoersModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, }, }, @@ -56,7 +57,7 @@ func TestSudoersModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, }, }.ToProtocol(), @@ -94,7 +95,7 @@ func TestSudoersModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, }, }, @@ -115,7 +116,7 @@ func TestSudoersModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, }, }.ToProtocol(), @@ -247,7 +248,7 @@ func TestSudoersModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, }, }, @@ -270,7 +271,7 @@ func TestSudoersModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, }, }, diff --git a/signatures/golang/system_request_key_config_modification.go b/signatures/golang/system_request_key_config_modification.go index 05d8c531fd03..e110c02e1305 100644 --- a/signatures/golang/system_request_key_config_modification.go +++ b/signatures/golang/system_request_key_config_modification.go @@ -52,7 +52,7 @@ func (sig *SystemRequestKeyConfigModification) OnEvent(event protocol.Event) err switch eventObj.EventName { case "security_file_open": - flags, err := helpers.GetTraceeStringArgumentByName(eventObj, "flags") + flags, err := helpers.GetTraceeIntArgumentByName(eventObj, "flags") if err != nil { return err } diff --git a/signatures/golang/system_request_key_config_modification_test.go b/signatures/golang/system_request_key_config_modification_test.go index f906621c3ed4..051cdd7d53d4 100644 --- a/signatures/golang/system_request_key_config_modification_test.go +++ b/signatures/golang/system_request_key_config_modification_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/signatures/signaturestest" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/trace" @@ -35,7 +36,7 @@ func TestSystemRequestKeyConfigModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, }, }, @@ -56,7 +57,7 @@ func TestSystemRequestKeyConfigModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, }, }.ToProtocol(), @@ -94,7 +95,7 @@ func TestSystemRequestKeyConfigModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_RDONLY"), + Value: buildFlagArgValue(parsers.O_RDONLY), }, }, }, @@ -117,7 +118,7 @@ func TestSystemRequestKeyConfigModification(t *testing.T) { ArgMeta: trace.ArgMeta{ Name: "flags", }, - Value: interface{}("O_WRONLY"), + Value: buildFlagArgValue(parsers.O_WRONLY), }, }, }, diff --git a/signatures/golang/test_helpers.go b/signatures/golang/test_helpers.go new file mode 100644 index 000000000000..c395fefbedcc --- /dev/null +++ b/signatures/golang/test_helpers.go @@ -0,0 +1,11 @@ +package main + +import "github.com/aquasecurity/tracee/pkg/events/parsers" + +func buildFlagArgValue(flags ...parsers.SystemFunctionArgument) int32 { + var res int32 + for _, flagVal := range flags { + res = res | int32(flagVal.Value()) + } + return res +} diff --git a/tests/e2e-inst-signatures/e2e-bpf_attach.go b/tests/e2e-inst-signatures/e2e-bpf_attach.go index a803e78fba2d..4eeb87da2a71 100644 --- a/tests/e2e-inst-signatures/e2e-bpf_attach.go +++ b/tests/e2e-inst-signatures/e2e-bpf_attach.go @@ -3,6 +3,7 @@ package main import ( "fmt" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/signatures/helpers" "github.com/aquasecurity/tracee/types/detect" "github.com/aquasecurity/tracee/types/protocol" @@ -48,14 +49,14 @@ func (sig *e2eBpfAttach) OnEvent(event protocol.Event) error { return err } - attachType, err := helpers.GetTraceeStringArgumentByName(eventObj, "attach_type") + attachType, err := helpers.GetTraceeIntArgumentByName(eventObj, "attach_type") if err != nil { return err } // check expected values from test for detection - if symbolName != "security_file_open" || attachType != "kprobe" { + if symbolName != "security_file_open" || attachType != int(parsers.BPFProgTypeKprobe) { return nil }