diff --git a/go.mod b/go.mod index 2ec409d4102b..6439f4c85d68 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/Masterminds/sprig/v3 v3.2.3 github.com/aquasecurity/libbpfgo v0.7.0-libbpf-1.4 github.com/aquasecurity/tracee/api v0.0.0-20240607205742-90c301111aee + github.com/aquasecurity/tracee/pkg/events/parsers v0.0.0-00010101000000-000000000000 github.com/aquasecurity/tracee/signatures/helpers v0.0.0-20240607205742-90c301111aee github.com/aquasecurity/tracee/types v0.0.0-20240607205742-90c301111aee github.com/containerd/containerd v1.7.17 @@ -76,6 +77,7 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/moby v26.1.3+incompatible // indirect github.com/moby/sys/sequential v0.5.0 // indirect github.com/moby/sys/user v0.1.0 // indirect github.com/moby/term v0.5.0 // indirect @@ -105,7 +107,6 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect - gotest.tools/v3 v3.4.0 // indirect k8s.io/apiextensions-apiserver v0.30.1 // indirect k8s.io/klog/v2 v2.120.1 // indirect k8s.io/kube-openapi v0.0.0-20240430033511-f0e62f92d13f // indirect @@ -177,3 +178,5 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect kernel.org/pub/linux/libs/security/libcap/psx v1.2.69 // indirect ) + +replace github.com/aquasecurity/tracee/pkg/events/parsers => ./pkg/events/parsers diff --git a/go.sum b/go.sum index 309a1837b414..b16e3be972ce 100644 --- a/go.sum +++ b/go.sum @@ -717,6 +717,8 @@ github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3N github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/moby/moby v26.1.3+incompatible h1:gIzra6kadTUzPUZWpyUfkaLKymz9I8gANMB1NKk2pF0= +github.com/moby/moby v26.1.3+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc= github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g= github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= @@ -1430,8 +1432,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= -gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/pkg/ebpf/events_pipeline.go b/pkg/ebpf/events_pipeline.go index 583f6060d37d..5bba680992a6 100644 --- a/pkg/ebpf/events_pipeline.go +++ b/pkg/ebpf/events_pipeline.go @@ -4,13 +4,17 @@ import ( "bytes" "context" "encoding/binary" + "fmt" "strconv" "sync" "unsafe" + bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/tracee/pkg/bufferdecoder" "github.com/aquasecurity/tracee/pkg/errfmt" "github.com/aquasecurity/tracee/pkg/events" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/pkg/logger" "github.com/aquasecurity/tracee/pkg/policy" "github.com/aquasecurity/tracee/pkg/utils" @@ -724,13 +728,30 @@ func (t *Tracee) handleError(err error) { // printers). func (t *Tracee) parseArguments(e *trace.Event) error { if t.config.Output.ParseArguments { - err := events.ParseArgs(e) + err := parsers.ParseArgs(e) if err != nil { return errfmt.WrapError(err) } if t.config.Output.ParseArgumentsFDs { - return events.ParseArgsFDs(e, uint64(t.getOrigEvtTimestamp(e)), t.FDArgPathMap) + return parseArgsFDs(e, uint64(t.getOrigEvtTimestamp(e)), t.FDArgPathMap) + } + } + + return nil +} + +func parseArgsFDs(event *trace.Event, origTimestamp uint64, fdArgPathMap *bpf.BPFMap) error { + if fdArg := parsers.GetArg(event, "fd"); fdArg != nil { + if fd, isInt32 := fdArg.Value.(int32); isInt32 { + ts := origTimestamp + bs, err := fdArgPathMap.GetValue(unsafe.Pointer(&ts)) + if err != nil { + return errfmt.WrapError(err) + } + + fpath := string(bytes.Trim(bs, "\x00")) + fdArg.Value = fmt.Sprintf("%d=%s", fd, fpath) } } diff --git a/pkg/ebpf/net_capture.go b/pkg/ebpf/net_capture.go index 88c3c32adf57..008d5f607b52 100644 --- a/pkg/ebpf/net_capture.go +++ b/pkg/ebpf/net_capture.go @@ -9,6 +9,7 @@ import ( "github.com/google/gopacket/layers" "github.com/aquasecurity/tracee/pkg/events" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/pkg/logger" "github.com/aquasecurity/tracee/types/trace" ) @@ -103,7 +104,7 @@ func (t *Tracee) processNetCapEvent(event *trace.Event) { // sanity checks - payloadArg := events.GetArg(event, "payload") + payloadArg := parsers.GetArg(event, "payload") if payloadArg == nil { logger.Debugw("Network capture: no payload packet") return diff --git a/pkg/ebpf/processor_funcs.go b/pkg/ebpf/processor_funcs.go index d5f309d3517c..baed1f218ccf 100644 --- a/pkg/ebpf/processor_funcs.go +++ b/pkg/ebpf/processor_funcs.go @@ -16,6 +16,7 @@ import ( "github.com/aquasecurity/tracee/pkg/errfmt" "github.com/aquasecurity/tracee/pkg/events" "github.com/aquasecurity/tracee/pkg/events/parse" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/pkg/filehash" "github.com/aquasecurity/tracee/pkg/logger" "github.com/aquasecurity/tracee/pkg/utils" @@ -102,7 +103,7 @@ func (t *Tracee) processReadEvent(event *trace.Event) error { // processKernelReadFile processes a security read event and changes the read type value. func processKernelReadFile(event *trace.Event) error { - readTypeArg := events.GetArg(event, "type") + readTypeArg := parsers.GetArg(event, "type") readTypeInt, ok := readTypeArg.Value.(int32) if !ok { return errfmt.Errorf("missing argument %s in event %s", "type", event.EventName) @@ -287,7 +288,7 @@ func (t *Tracee) processHookedProcFops(event *trace.Event) error { } hookedFops = append(hookedFops, trace.HookedSymbolData{SymbolName: functionName, ModuleOwner: hookingFunction.Owner}) } - err = events.SetArgValue(event, hookedFopsPointersArgName, hookedFops) + err = parsers.SetArgValue(event, hookedFopsPointersArgName, hookedFops) if err != nil { return err } @@ -326,15 +327,15 @@ func (t *Tracee) processPrintMemDump(event *trace.Event) error { return errfmt.WrapError(err) } arch = string(bytes.TrimRight(utsName.Machine[:], "\x00")) - err = events.SetArgValue(event, "arch", arch) + err = parsers.SetArgValue(event, "arch", arch) if err != nil { return err } - err = events.SetArgValue(event, "symbol_name", symbol.Name) + err = parsers.SetArgValue(event, "symbol_name", symbol.Name) if err != nil { return err } - err = events.SetArgValue(event, "symbol_owner", symbol.Owner) + err = parsers.SetArgValue(event, "symbol_owner", symbol.Owner) if err != nil { return err } @@ -394,7 +395,7 @@ func (t *Tracee) processSchedProcessFork(event *trace.Event) error { // normalizeEventArgTime normalizes the event arg time to be relative to tracee start time or // current time. func (t *Tracee) normalizeEventArgTime(event *trace.Event, argName string) error { - arg := events.GetArg(event, argName) + arg := parsers.GetArg(event, argName) if arg == nil { return errfmt.Errorf("couldn't find argument %s of event %s", argName, event.EventName) } diff --git a/pkg/events/derive/net_packet_helpers.go b/pkg/events/derive/net_packet_helpers.go index eee835714000..6d861cb46a40 100644 --- a/pkg/events/derive/net_packet_helpers.go +++ b/pkg/events/derive/net_packet_helpers.go @@ -12,7 +12,7 @@ import ( "github.com/google/gopacket/layers" "github.com/aquasecurity/tracee/pkg/dnscache" - "github.com/aquasecurity/tracee/pkg/events" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/pkg/logger" "github.com/aquasecurity/tracee/types/trace" ) @@ -82,7 +82,7 @@ func strToLower(given string) string { // parsePayloadArg returns the packet payload from the event. func parsePayloadArg(event *trace.Event) ([]byte, error) { - payloadArg := events.GetArg(event, "payload") + payloadArg := parsers.GetArg(event, "payload") if payloadArg == nil { return nil, noPayloadError() } diff --git a/pkg/events/parsers/data_parsers.go b/pkg/events/parsers/data_parsers.go index 147b6ffeaad7..b9022d8a1bc4 100644 --- a/pkg/events/parsers/data_parsers.go +++ b/pkg/events/parsers/data_parsers.go @@ -8,9 +8,8 @@ import ( "strings" "sync/atomic" + "github.com/moby/moby/pkg/parsers/kernel" "golang.org/x/sys/unix" - - "github.com/aquasecurity/tracee/pkg/utils/environment" ) type SystemFunctionArgument interface { @@ -264,7 +263,10 @@ func ParseOpenFlagArgument(rawValue uint64) (OpenFlagArgument, error) { } if len(f) == 0 { - return OpenFlagArgument{}, fmt.Errorf("no valid open flag values present in raw value: 0x%x", rawValue) + return OpenFlagArgument{}, fmt.Errorf( + "no valid open flag values present in raw value: 0x%x", + rawValue, + ) } return OpenFlagArgument{rawValue: rawValue, stringValue: strings.Join(f, "|")}, nil @@ -3262,7 +3264,7 @@ func ParseLegacyGUPFlags(rawValue uint64) LegacyGUPFlag { var currentOSGUPFlagsParse uint32 var skipDetermineGUPFlagsFunc uint32 -const gupFlagsChangeVersion = "6.3.0" +var gupFlagsChangeVersion, _ = kernel.ParseRelease("6.3.0") // ParseGUPFlagsCurrentOS parse the GUP flags received according to current machine OS version. // It uses optimizations to perform better than ParseGUPFlagsForOS @@ -3272,21 +3274,14 @@ func ParseGUPFlagsCurrentOS(rawValue uint64) (SystemFunctionArgument, error) { legacyParsing ) if atomic.LoadUint32(&skipDetermineGUPFlagsFunc) == 0 { - osInfo, err := environment.GetOSInfo() - if err != nil { - return nil, fmt.Errorf("error getting current OS info - %s", err) - } - compare, err := osInfo.CompareOSBaseKernelRelease(gupFlagsChangeVersion) + currentVersion, err := kernel.GetKernelVersion() if err != nil { - return nil, fmt.Errorf( - "error comparing OS versions to determine how to parse GUP flags - %s", - err, - ) + return nil, fmt.Errorf("error getting current kernel version - %s", err) } - if compare == environment.KernelVersionOlder { - atomic.StoreUint32(¤tOSGUPFlagsParse, legacyParsing) - } else { + if kernel.CompareKernelVersion(*currentVersion, *gupFlagsChangeVersion) >= 0 { atomic.StoreUint32(¤tOSGUPFlagsParse, newVersionsParsing) + } else { + atomic.StoreUint32(¤tOSGUPFlagsParse, legacyParsing) } // Avoid doing this check in the future atomic.StoreUint32(&skipDetermineGUPFlagsFunc, 1) @@ -3305,19 +3300,17 @@ func ParseGUPFlagsCurrentOS(rawValue uint64) (SystemFunctionArgument, error) { } // ParseGUPFlagsForOS parse the GUP flags received according to given OS version. -func ParseGUPFlagsForOS(osInfo *environment.OSInfo, rawValue uint64) (SystemFunctionArgument, error) { - compare, err := osInfo.CompareOSBaseKernelRelease(gupFlagsChangeVersion) +func ParseGUPFlagsForOS(kernelVersion string, rawValue uint64) ( + SystemFunctionArgument, error, +) { + parsedVersion, err := kernel.ParseRelease(kernelVersion) if err != nil { - return nil, fmt.Errorf( - "error comparing OS versions to determine how to parse GUP flags - %s", - err, - ) + return nil, fmt.Errorf("error parsing given kernel version - %s", err) } - - if compare == environment.KernelVersionOlder { - return ParseLegacyGUPFlags(rawValue), nil + if kernel.CompareKernelVersion(*parsedVersion, *gupFlagsChangeVersion) >= 0 { + return ParseGUPFlags(rawValue), nil } - return ParseGUPFlags(rawValue), nil + return ParseLegacyGUPFlags(rawValue), nil } // ===================================================== @@ -3589,3 +3582,47 @@ func ParseFsNotifyObjType(rawValue uint64) (FsNotifyObjType, error) { } return v, nil } + +// ===================================================== + +// BpfAttachType is the type of probe the BPF program was attach to. +// This type is not of the kernel, but unique to Tracee. It must match the +// `bpf_attach_type_e` enum in the bpf code. +type BpfAttachType struct { + rawValue int32 + stringValue string +} + +var ( + BPF_RAW_TRACEPOINT = BpfAttachType{rawValue: 0, stringValue: "raw_tracepoint"} + PERF_TRACEPOINT = BpfAttachType{rawValue: 1, stringValue: "tracepoint"} + PERF_KPROBE = BpfAttachType{rawValue: 2, stringValue: "kprobe"} + PERF_KRETPROBE = BpfAttachType{rawValue: 3, stringValue: "kretprobe"} + PERF_UPROBE = BpfAttachType{rawValue: 4, stringValue: "uprobe"} + PERF_URETPROBE = BpfAttachType{rawValue: 5, stringValue: "uretprobe"} +) + +var attachTypeMap = map[int32]BpfAttachType{ + int32(BPF_RAW_TRACEPOINT.Value()): BPF_RAW_TRACEPOINT, + int32(PERF_TRACEPOINT.Value()): PERF_TRACEPOINT, + int32(PERF_KPROBE.Value()): PERF_KPROBE, + int32(PERF_KRETPROBE.Value()): PERF_KRETPROBE, + int32(PERF_UPROBE.Value()): PERF_UPROBE, + int32(PERF_URETPROBE.Value()): PERF_URETPROBE, +} + +func (attachType BpfAttachType) Value() uint64 { + return uint64(attachType.rawValue) +} + +func (attachType BpfAttachType) String() string { + return attachType.stringValue +} + +func ParseBpfAttachType(attachType int32) (BpfAttachType, error) { + v, ok := attachTypeMap[attachType] + if !ok { + return BpfAttachType{}, fmt.Errorf("not a valid argument: %d", attachType) + } + return v, nil +} diff --git a/pkg/events/parsers/go.mod b/pkg/events/parsers/go.mod new file mode 100644 index 000000000000..68fe266160a3 --- /dev/null +++ b/pkg/events/parsers/go.mod @@ -0,0 +1,22 @@ +module tracee/pkg/events/parsers + +go 1.21 + +require ( + github.com/aquasecurity/tracee/types v0.0.0-20240531175500-73839cfd71e6 + github.com/moby/moby v26.1.3+incompatible + github.com/stretchr/testify v1.9.0 + golang.org/x/sys v0.20.0 +) + +require ( + github.com/containerd/log v0.1.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rogpeppe/go-internal v1.10.0 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + gotest.tools/v3 v3.5.1 // indirect +) diff --git a/pkg/events/parsers/go.sum b/pkg/events/parsers/go.sum new file mode 100644 index 000000000000..1a660ec0810e --- /dev/null +++ b/pkg/events/parsers/go.sum @@ -0,0 +1,42 @@ +github.com/aquasecurity/tracee/types v0.0.0-20240531175500-73839cfd71e6 h1:2rCXNs7elaI1EWSyVNMsOmOMulnhcxSUQVY2ykgym+4= +github.com/aquasecurity/tracee/types v0.0.0-20240531175500-73839cfd71e6/go.mod h1:J0f9nzJWrFmFgMoK0s4Yirfh82vfKMatXytd1YdfU2I= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/moby/moby v26.1.3+incompatible h1:gIzra6kadTUzPUZWpyUfkaLKymz9I8gANMB1NKk2pF0= +github.com/moby/moby v26.1.3+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= diff --git a/pkg/events/parse_args.go b/pkg/events/parsers/parse_args.go similarity index 62% rename from pkg/events/parse_args.go rename to pkg/events/parsers/parse_args.go index c646d211fd05..dda93fa7c55f 100644 --- a/pkg/events/parse_args.go +++ b/pkg/events/parsers/parse_args.go @@ -1,15 +1,9 @@ -package events +package parsers import ( - "bytes" "fmt" "strconv" - "unsafe" - bpf "github.com/aquasecurity/libbpfgo" - - "github.com/aquasecurity/tracee/pkg/errfmt" - "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/types/trace" ) @@ -28,15 +22,15 @@ func ParseArgs(event *trace.Event) error { arg.Value = "" } - parseOrEmptyString := func(arg *trace.Argument, sysArg parsers.SystemFunctionArgument, err error) { + parseOrEmptyString := func(arg *trace.Argument, sysArg SystemFunctionArgument, err error) { emptyString(arg) if err == nil { arg.Value = sysArg.String() } } - switch ID(event.EventID) { - case MemProtAlert: + switch event.EventName { + case "mem_prot_alert": if alertArg := GetArg(event, "alert"); alertArg != nil { if alert, isUint32 := alertArg.Value.(uint32); isUint32 { alertArg.Value = trace.MemProtAlert(alert).String() @@ -45,208 +39,209 @@ func ParseArgs(event *trace.Event) error { } if protArg := GetArg(event, "prot"); protArg != nil { if prot, isInt32 := protArg.Value.(int32); isInt32 { - mmapProtArgument := parsers.ParseMmapProt(uint64(prot)) + mmapProtArgument := ParseMmapProt(uint64(prot)) parseOrEmptyString(protArg, mmapProtArgument, nil) } } if prevProtArg := GetArg(event, "prev_prot"); prevProtArg != nil { if prevProt, isInt32 := prevProtArg.Value.(int32); isInt32 { - mmapProtArgument := parsers.ParseMmapProt(uint64(prevProt)) + mmapProtArgument := ParseMmapProt(uint64(prevProt)) parseOrEmptyString(prevProtArg, mmapProtArgument, nil) } } - case SysEnter, SysExit: - if syscallArg := GetArg(event, "syscall"); syscallArg != nil { - if id, isInt32 := syscallArg.Value.(int32); isInt32 { - if Core.IsDefined(ID(id)) { - eventDefinition := Core.GetDefinitionByID(ID(id)) - if eventDefinition.IsSyscall() { - syscallArg.Value = eventDefinition.GetName() - syscallArg.Type = "string" - } - } - } - } - case CapCapable: + // TODO: Add support for syscall id to name parsing + // case "sys_enter", "sys_exit": + // if syscallArg := GetArg(event, "syscall"); syscallArg != nil { + // if id, isInt32 := syscallArg.Value.(int32); isInt32 { + // if events.Core.IsDefined(events.ID(id)) { + // eventDefinition := events.Core.GetDefinitionByID(events.ID(id)) + // if eventDefinition.IsSyscall() { + // syscallArg.Value = eventDefinition.GetName() + // syscallArg.Type = "string" + // } + // } + // } + // } + case "cap_capable": if capArg := GetArg(event, "cap"); capArg != nil { if capability, isInt32 := capArg.Value.(int32); isInt32 { - capabilityFlagArgument, err := parsers.ParseCapability(uint64(capability)) + capabilityFlagArgument, err := ParseCapability(uint64(capability)) parseOrEmptyString(capArg, capabilityFlagArgument, err) } } - case SecurityMmapFile, DoMmap: + case "security_mmap_file", "do_mmap": if protArg := GetArg(event, "prot"); protArg != nil { if prot, isUint64 := protArg.Value.(uint64); isUint64 { - mmapProtArgument := parsers.ParseMmapProt(prot) + mmapProtArgument := ParseMmapProt(prot) parseOrEmptyString(protArg, mmapProtArgument, nil) } } - case Mmap, Mprotect, PkeyMprotect: + case "mmap", "mprotect", "pkey_mprotect": if protArg := GetArg(event, "prot"); protArg != nil { if prot, isInt32 := protArg.Value.(int32); isInt32 { - mmapProtArgument := parsers.ParseMmapProt(uint64(prot)) + mmapProtArgument := ParseMmapProt(uint64(prot)) parseOrEmptyString(protArg, mmapProtArgument, nil) } } - case SecurityFileMprotect: + case "security_file_mprotect": if protArg := GetArg(event, "prot"); protArg != nil { if prot, isInt32 := protArg.Value.(int32); isInt32 { - mmapProtArgument := parsers.ParseMmapProt(uint64(prot)) + mmapProtArgument := ParseMmapProt(uint64(prot)) parseOrEmptyString(protArg, mmapProtArgument, nil) } } if prevProtArg := GetArg(event, "prev_prot"); prevProtArg != nil { if prevProt, isInt32 := prevProtArg.Value.(int32); isInt32 { - mmapProtArgument := parsers.ParseMmapProt(uint64(prevProt)) + mmapProtArgument := ParseMmapProt(uint64(prevProt)) parseOrEmptyString(prevProtArg, mmapProtArgument, nil) } } - case Ptrace: + case "ptrace": if reqArg := GetArg(event, "request"); reqArg != nil { if req, isInt64 := reqArg.Value.(int64); isInt64 { - ptraceRequestArgument, err := parsers.ParsePtraceRequestArgument(uint64(req)) + ptraceRequestArgument, err := ParsePtraceRequestArgument(uint64(req)) parseOrEmptyString(reqArg, ptraceRequestArgument, err) } } - case Prctl: + case "prctl": if optArg := GetArg(event, "option"); optArg != nil { if opt, isInt32 := optArg.Value.(int32); isInt32 { - prctlOptionArgument, err := parsers.ParsePrctlOption(uint64(opt)) + prctlOptionArgument, err := ParsePrctlOption(uint64(opt)) parseOrEmptyString(optArg, prctlOptionArgument, err) } } - case Socketcall: + case "socketcall": if callArg := GetArg(event, "call"); callArg != nil { if call, isInt32 := callArg.Value.(int32); isInt32 { - socketcallArgument, err := parsers.ParseSocketcallCall(uint64(call)) + socketcallArgument, err := ParseSocketcallCall(uint64(call)) parseOrEmptyString(callArg, socketcallArgument, err) } } - case Socket: + case "socket": if domArg := GetArg(event, "domain"); domArg != nil { if dom, isInt32 := domArg.Value.(int32); isInt32 { - socketDomainArgument, err := parsers.ParseSocketDomainArgument(uint64(dom)) + socketDomainArgument, err := ParseSocketDomainArgument(uint64(dom)) parseOrEmptyString(domArg, socketDomainArgument, err) } } if typeArg := GetArg(event, "type"); typeArg != nil { if typ, isInt32 := typeArg.Value.(int32); isInt32 { - socketTypeArgument, err := parsers.ParseSocketType(uint64(typ)) + socketTypeArgument, err := ParseSocketType(uint64(typ)) parseOrEmptyString(typeArg, socketTypeArgument, err) } } - case SecuritySocketCreate, SecuritySocketConnect: + case "security_socket_create", "security_socket_connect": if domArg := GetArg(event, "family"); domArg != nil { if dom, isInt32 := domArg.Value.(int32); isInt32 { - socketDomainArgument, err := parsers.ParseSocketDomainArgument(uint64(dom)) + socketDomainArgument, err := ParseSocketDomainArgument(uint64(dom)) parseOrEmptyString(domArg, socketDomainArgument, err) } } if typeArg := GetArg(event, "type"); typeArg != nil { if typ, isInt32 := typeArg.Value.(int32); isInt32 { - socketTypeArgument, err := parsers.ParseSocketType(uint64(typ)) + socketTypeArgument, err := ParseSocketType(uint64(typ)) parseOrEmptyString(typeArg, socketTypeArgument, err) } } - case Access, Faccessat: + case "access", "faccessat": if modeArg := GetArg(event, "mode"); modeArg != nil { if mode, isInt32 := modeArg.Value.(int32); isInt32 { - accessModeArgument, err := parsers.ParseAccessMode(uint64(mode)) + accessModeArgument, err := ParseAccessMode(uint64(mode)) parseOrEmptyString(modeArg, accessModeArgument, err) } } - case Execveat: + case "execveat": if flagsArg := GetArg(event, "flags"); flagsArg != nil { if flags, isInt32 := flagsArg.Value.(int32); isInt32 { - execFlagArgument, err := parsers.ParseExecFlag(uint64(flags)) + execFlagArgument, err := ParseExecFlag(uint64(flags)) parseOrEmptyString(flagsArg, execFlagArgument, err) } } - case Open, Openat, SecurityFileOpen: + case "open", "openat", "security_file_open": if flagsArg := GetArg(event, "flags"); flagsArg != nil { if flags, isInt32 := flagsArg.Value.(int32); isInt32 { - openFlagArgument, err := parsers.ParseOpenFlagArgument(uint64(flags)) + openFlagArgument, err := ParseOpenFlagArgument(uint64(flags)) parseOrEmptyString(flagsArg, openFlagArgument, err) } } - case Mknod, Mknodat, Chmod, Fchmod, Fchmodat: + case "mknod", "mknodat", "chmod", "fchmod", "fchmodat": if modeArg := GetArg(event, "mode"); modeArg != nil { if mode, isUint32 := modeArg.Value.(uint32); isUint32 { - inodeModeArgument, err := parsers.ParseInodeMode(uint64(mode)) + inodeModeArgument, err := ParseInodeMode(uint64(mode)) parseOrEmptyString(modeArg, inodeModeArgument, err) } } - case SecurityInodeMknod: + case "security_inode_mknod": if modeArg := GetArg(event, "mode"); modeArg != nil { if mode, isUint16 := modeArg.Value.(uint16); isUint16 { - inodeModeArgument, err := parsers.ParseInodeMode(uint64(mode)) + inodeModeArgument, err := ParseInodeMode(uint64(mode)) parseOrEmptyString(modeArg, inodeModeArgument, err) } } - case Clone: + case "clone": if flagsArg := GetArg(event, "flags"); flagsArg != nil { if flags, isUint64 := flagsArg.Value.(uint64); isUint64 { - cloneFlagArgument, err := parsers.ParseCloneFlags(uint64(flags)) + cloneFlagArgument, err := ParseCloneFlags(uint64(flags)) parseOrEmptyString(flagsArg, cloneFlagArgument, err) } } - case Bpf, SecurityBPF: + case "bpf", "security_bpf": if cmdArg := GetArg(event, "cmd"); cmdArg != nil { if cmd, isInt32 := cmdArg.Value.(int32); isInt32 { - bpfCommandArgument, err := parsers.ParseBPFCmd(uint64(cmd)) + bpfCommandArgument, err := ParseBPFCmd(uint64(cmd)) parseOrEmptyString(cmdArg, bpfCommandArgument, err) } } - case SecurityKernelReadFile, SecurityPostReadFile: + case "security_kernel_read_file", "security_post_read_file": if typeArg := GetArg(event, "type"); typeArg != nil { if readFileId, isInt32 := typeArg.Value.(trace.KernelReadType); isInt32 { emptyString(typeArg) typeArg.Value = readFileId.String() } } - case SchedProcessExec: + case "sched_process_exec": if modeArg := GetArg(event, "stdin_type"); modeArg != nil { if mode, isUint16 := modeArg.Value.(uint16); isUint16 { - inodeModeArgument, err := parsers.ParseInodeMode(uint64(mode)) + inodeModeArgument, err := ParseInodeMode(uint64(mode)) parseOrEmptyString(modeArg, inodeModeArgument, err) } } - case DirtyPipeSplice: + case "dirty_pipe_splice": if modeArg := GetArg(event, "in_file_type"); modeArg != nil { if mode, isUint16 := modeArg.Value.(uint16); isUint16 { - inodeModeArgument, err := parsers.ParseInodeMode(uint64(mode)) + inodeModeArgument, err := ParseInodeMode(uint64(mode)) parseOrEmptyString(modeArg, inodeModeArgument, err) } } - case SecuritySocketSetsockopt, Setsockopt, Getsockopt: + case "security_socket_setsockopt", "setsockopt", "getsockopt": if levelArg := GetArg(event, "level"); levelArg != nil { if level, isInt := levelArg.Value.(int32); isInt { - levelArgument, err := parsers.ParseSocketLevel(uint64(level)) + levelArgument, err := ParseSocketLevel(uint64(level)) parseOrEmptyString(levelArg, levelArgument, err) } } if optionNameArg := GetArg(event, "optname"); optionNameArg != nil { if opt, isInt := optionNameArg.Value.(int32); isInt { - var optionNameArgument parsers.SocketOptionArgument + var optionNameArgument SocketOptionArgument var err error - if ID(event.EventID) == Getsockopt { - optionNameArgument, err = parsers.ParseGetSocketOption(uint64(opt)) + if event.EventName == "getsockopt" { + optionNameArgument, err = ParseGetSocketOption(uint64(opt)) } else { - optionNameArgument, err = parsers.ParseSetSocketOption(uint64(opt)) + optionNameArgument, err = ParseSetSocketOption(uint64(opt)) } parseOrEmptyString(optionNameArg, optionNameArgument, err) } } - case BpfAttach: + case "bpf_attach": if progTypeArg := GetArg(event, "prog_type"); progTypeArg != nil { if progType, isInt := progTypeArg.Value.(int32); isInt { - progTypeArgument, err := parsers.ParseBPFProgType(uint64(progType)) + progTypeArgument, err := ParseBPFProgType(uint64(progType)) parseOrEmptyString(progTypeArg, progTypeArgument, err) } } if helpersArg := GetArg(event, "prog_helpers"); helpersArg != nil { if helpersList, isUintSlice := helpersArg.Value.([]uint64); isUintSlice { - parsedHelpersList, err := parseBpfHelpersUsage(helpersList) + parsedHelpersList, err := ParseBpfHelpersUsage(helpersList) if err != nil { return err } @@ -256,23 +251,20 @@ func ParseArgs(event *trace.Event) error { } if attachTypeArg := GetArg(event, "attach_type"); attachTypeArg != nil { if attachType, isInt := attachTypeArg.Value.(int32); isInt { - attachTypestr, err := parseBpfAttachType(attachType) - emptyString(attachTypeArg) - if err == nil { - attachTypeArg.Value = attachTypestr - } + attachTypeArgument, err := ParseBpfAttachType(attachType) + parseOrEmptyString(attachTypeArg, attachTypeArgument, err) } } - case SecurityBpfProg: + case "security_bpf_prog": if progTypeArg := GetArg(event, "type"); progTypeArg != nil { if progType, isInt := progTypeArg.Value.(int32); isInt { - progTypeArgument, err := parsers.ParseBPFProgType(uint64(progType)) + progTypeArgument, err := ParseBPFProgType(uint64(progType)) parseOrEmptyString(progTypeArg, progTypeArgument, err) } } if helpersArg := GetArg(event, "helpers"); helpersArg != nil { if helpersList, isUintSlice := helpersArg.Value.([]uint64); isUintSlice { - parsedHelpersList, err := parseBpfHelpersUsage(helpersList) + parsedHelpersList, err := ParseBpfHelpersUsage(helpersList) if err != nil { return err } @@ -280,16 +272,16 @@ func ParseArgs(event *trace.Event) error { helpersArg.Value = parsedHelpersList } } - case SecurityPathNotify: + case "security_path_notify": if maskArg := GetArg(event, "mask"); maskArg != nil { if mask, isUint64 := maskArg.Value.(uint64); isUint64 { - fsNotifyMaskArgument := parsers.ParseFsNotifyMask(mask) + fsNotifyMaskArgument := ParseFsNotifyMask(mask) parseOrEmptyString(maskArg, fsNotifyMaskArgument, nil) } } if objTypeArg := GetArg(event, "obj_type"); objTypeArg != nil { if objType, isUint := objTypeArg.Value.(uint32); isUint { - objTypeArgument, err := parsers.ParseFsNotifyObjType(uint64(objType)) + objTypeArgument, err := ParseFsNotifyObjType(uint64(objType)) parseOrEmptyString(objTypeArg, objTypeArgument, err) } } @@ -298,23 +290,6 @@ func ParseArgs(event *trace.Event) error { return nil } -func ParseArgsFDs(event *trace.Event, origTimestamp uint64, fdArgPathMap *bpf.BPFMap) error { - if fdArg := GetArg(event, "fd"); fdArg != nil { - if fd, isInt32 := fdArg.Value.(int32); isInt32 { - ts := origTimestamp - bs, err := fdArgPathMap.GetValue(unsafe.Pointer(&ts)) - if err != nil { - return errfmt.WrapError(err) - } - - fpath := string(bytes.Trim(bs, "\x00")) - fdArg.Value = fmt.Sprintf("%d=%s", fd, fpath) - } - } - - return nil -} - func GetArg(event *trace.Event, argName string) *trace.Argument { for i := range event.Args { if event.Args[i].Name == argName { @@ -345,13 +320,14 @@ func (arg CustomFunctionArgument) Value() uint64 { return arg.val } -func parseBpfHelpersUsage(helpersList []uint64) ([]string, error) { +// ParseBpfHelpersUsage parse number of bpf helpers to their matching names. +func ParseBpfHelpersUsage(helpersList []uint64) ([]string, error) { var usedHelpers []string for i := 0; i < len(helpersList)*64; i++ { if (helpersList[i/64] & (1 << (i % 64))) > 0 { - // helper number is used. get its name from libbpfgo - bpfHelper, err := parsers.ParseBPFFunc(uint64(i)) + // helper number is used. get its name + bpfHelper, err := ParseBPFFunc(uint64(i)) if err != nil { continue } @@ -361,22 +337,3 @@ func parseBpfHelpersUsage(helpersList []uint64) ([]string, error) { return usedHelpers, nil } - -func parseBpfAttachType(attachType int32) (string, error) { - switch attachType { - case 0: - return "raw_tracepoint", nil - case 1: - return "tracepoint", nil - case 2: - return "kprobe", nil - case 3: - return "kretprobe", nil - case 4: - return "uprobe", nil - case 5: - return "uretprobe", nil - default: - return "", errfmt.Errorf("unknown attach_type got from bpf_attach event") - } -} diff --git a/pkg/events/parse_args_test.go b/pkg/events/parsers/parse_args_test.go similarity index 81% rename from pkg/events/parse_args_test.go rename to pkg/events/parsers/parse_args_test.go index da90e2bf56b8..dc09808637f1 100644 --- a/pkg/events/parse_args_test.go +++ b/pkg/events/parsers/parse_args_test.go @@ -1,4 +1,4 @@ -package events +package parsers import ( "testing" @@ -6,7 +6,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/types/trace" ) @@ -29,14 +28,14 @@ func TestParseArgs(t *testing.T) { Name: "optname", Type: "int", }, - Value: int32(parsers.SO_LOCK_FILTER.Value()), + Value: int32(SO_LOCK_FILTER.Value()), }, { ArgMeta: trace.ArgMeta{ Name: "level", Type: "int", }, - Value: int32(parsers.SOL_IP.Value()), + Value: int32(SOL_IP.Value()), }, }, expectedArgs: []trace.Argument{ @@ -45,14 +44,14 @@ func TestParseArgs(t *testing.T) { Name: "optname", Type: "string", }, - Value: parsers.SO_LOCK_FILTER.String(), + Value: SO_LOCK_FILTER.String(), }, { ArgMeta: trace.ArgMeta{ Name: "level", Type: "string", }, - Value: parsers.SOL_IP.String(), + Value: SOL_IP.String(), }, }, }, @@ -64,7 +63,7 @@ func TestParseArgs(t *testing.T) { Name: "optname", Type: "int", }, - Value: int32(parsers.SO_ATTACH_FILTER.Value()), + Value: int32(SO_ATTACH_FILTER.Value()), }, }, expectedArgs: []trace.Argument{ @@ -85,7 +84,7 @@ func TestParseArgs(t *testing.T) { Name: "optname", Type: "int", }, - Value: int32(parsers.SO_LOCK_FILTER.Value()), + Value: int32(SO_LOCK_FILTER.Value()), }, }, expectedArgs: []trace.Argument{ @@ -94,7 +93,7 @@ func TestParseArgs(t *testing.T) { Name: "optname", Type: "string", }, - Value: parsers.SO_LOCK_FILTER.String(), + Value: SO_LOCK_FILTER.String(), }, }, }, @@ -107,8 +106,8 @@ func TestParseArgs(t *testing.T) { t.Parallel() event := trace.Event{ - EventID: int(Setsockopt), - Args: testCase.args, + EventName: "setsockopt", + Args: testCase.args, } err := ParseArgs(&event) require.NoError(t, err) @@ -136,14 +135,14 @@ func TestParseArgs(t *testing.T) { Name: "optname", Type: "int", }, - Value: int32(parsers.SO_LOCK_FILTER.Value()), + Value: int32(SO_LOCK_FILTER.Value()), }, { ArgMeta: trace.ArgMeta{ Name: "level", Type: "int", }, - Value: int32(parsers.SOL_IP.Value()), + Value: int32(SOL_IP.Value()), }, }, expectedArgs: []trace.Argument{ @@ -152,14 +151,14 @@ func TestParseArgs(t *testing.T) { Name: "optname", Type: "string", }, - Value: parsers.SO_LOCK_FILTER.String(), + Value: SO_LOCK_FILTER.String(), }, { ArgMeta: trace.ArgMeta{ Name: "level", Type: "string", }, - Value: parsers.SOL_IP.String(), + Value: SOL_IP.String(), }, }, }, @@ -171,7 +170,7 @@ func TestParseArgs(t *testing.T) { Name: "optname", Type: "int", }, - Value: int32(parsers.SO_GET_FILTER.Value()), + Value: int32(SO_GET_FILTER.Value()), }, }, expectedArgs: []trace.Argument{ @@ -193,8 +192,8 @@ func TestParseArgs(t *testing.T) { t.Parallel() event := &trace.Event{ - EventID: int(Getsockopt), - Args: testCase.args, + EventName: "getsockopt", + Args: testCase.args, } err := ParseArgs(event) require.NoError(t, err)