From 58a8fb46a6519a0163124660ca762aea043ef91a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Geyslan=20Greg=C3=B3rio?= Date: Mon, 16 Sep 2024 16:58:02 -0300 Subject: [PATCH] chore: fix: improve data parsers - perf: improvements include reducing the size of the parser logic by using slices instead of maps whenever possible. This allows for direct access to values via index, and when direct access isn't feasible, iterating through slices is generally more efficient than fetching values from a map. - perf: return string only instead of the Argument type since it's the only value used. - fix ParseOpenFlagArgument that wasn't printing O_RDONLY flag alone. - fix ParseAccessMode that wasn't printing F_OK flag alone. - fix ParseExecFlag (now ParseExecveatFlag) to check only related flags. - fix Faccessat and Fchmodat to parse flags arg too. - feat: *at syscalls with dirfd arg now parse for special case AT_FDCWD when ParseArgumentsFDs is true. - chore: try as much as possible to use values defined in the C system, avoiding entering incorrect values. - chore: add to ParseCapability the missing flags: CAP_PERFMON, CAP_BPF and CAP_CHECKPOINT_RESTORE. - chore: add to ParsePrctlOption the missing flags: PR_SET_IO_FLUSHER, PR_GET_IO_FLUSHER, PR_SET_SYSCALL_USER_DISPATCH, PR_PAC_SET_ENABLED_KEYS, PR_PAC_GET_ENABLED_KEYS, PR_SCHED_CORE, PR_SME_SET_VL, PR_SME_GET_VL, PR_SET_MDWE, PR_GET_MDWE, PR_SET_MEMORY_MERGE and PR_GET_MEMORY_MERGE. - chore: add to ParseBPF the missing flags: BPF_PROG_BIND_MAP, BPF_TOKEN_CREATE - chore ParsePtraceRequestArgument including missing flags PTRACE_GET_THREAD_AREA, PTRACE_SET_THREAD_AREA, PTRACE_ARCH_PRCTL, PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP, PTRACE_SINGLEBLOCK, PTRACE_GET_RSEQ_CONFIGURATION, PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG and PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG. - chore: add to ParseSocketDomainArgument the missing: AF_MCTP. This commit reduces the size of the final binary by ~56KB. --- pkg/bufferdecoder/eventsreader.go | 4 +- pkg/events/parse_args.go | 35 +- pkg/events/parse_args_helpers.go | 58 +- pkg/events/parsers/data_parsers.go | 2019 ++++++++--------- pkg/events/parsers/data_parsers_bench_test.go | 37 + pkg/events/parsers/data_parsers_test.go | 204 ++ 6 files changed, 1211 insertions(+), 1146 deletions(-) diff --git a/pkg/bufferdecoder/eventsreader.go b/pkg/bufferdecoder/eventsreader.go index cf829e4c07a5..3d3f077485bc 100644 --- a/pkg/bufferdecoder/eventsreader.go +++ b/pkg/bufferdecoder/eventsreader.go @@ -255,9 +255,9 @@ func readSockaddrFromBuff(ebpfMsgDecoder *EbpfDecoder) (map[string]string, error } socketDomainArg, err := parsers.ParseSocketDomainArgument(uint64(family)) if err != nil { - socketDomainArg = parsers.AF_UNSPEC + socketDomainArg = parsers.AF_UNSPEC.String() } - res["sa_family"] = socketDomainArg.String() + res["sa_family"] = socketDomainArg switch family { case 1: // AF_UNIX /* diff --git a/pkg/events/parse_args.go b/pkg/events/parse_args.go index 5f9f184101d9..d49c2238c6b9 100644 --- a/pkg/events/parse_args.go +++ b/pkg/events/parse_args.go @@ -23,7 +23,8 @@ func ParseArgs(event *trace.Event) error { } } - switch ID(event.EventID) { + evtID := ID(event.EventID) + switch evtID { case MemProtAlert: if alertArg := GetArg(event, "alert"); alertArg != nil { if alert, isUint32 := alertArg.Value.(uint32); isUint32 { @@ -83,8 +84,8 @@ func ParseArgs(event *trace.Event) error { } case Prctl: if optArg := GetArg(event, "option"); optArg != nil { - if opt, isInt32 := optArg.Value.(int32); isInt32 { - parsePrctlOption(optArg, uint64(opt)) + if option, isInt32 := optArg.Value.(int32); isInt32 { + parsePrctlOption(optArg, uint64(option)) } } case Socketcall: @@ -115,16 +116,27 @@ func ParseArgs(event *trace.Event) error { parseSocketType(typeArg, uint64(typ)) } } - case Access, Faccessat: + case Access: if modeArg := GetArg(event, "mode"); modeArg != nil { if mode, isInt32 := modeArg.Value.(int32); isInt32 { parseAccessMode(modeArg, uint64(mode)) } } + case Faccessat: + if modeArg := GetArg(event, "mode"); modeArg != nil { + if mode, isInt32 := modeArg.Value.(int32); isInt32 { + parseAccessMode(modeArg, uint64(mode)) + } + } + if flagsArg := GetArg(event, "flags"); flagsArg != nil { + if flags, isInt32 := flagsArg.Value.(int32); isInt32 { + parseFaccessatFlag(flagsArg, uint64(flags)) + } + } case Execveat: if flagsArg := GetArg(event, "flags"); flagsArg != nil { if flags, isInt32 := flagsArg.Value.(int32); isInt32 { - parseExecFlag(flagsArg, uint64(flags)) + parseExecveatFlag(flagsArg, uint64(flags)) } } case Open, Openat, SecurityFileOpen: @@ -139,6 +151,13 @@ func ParseArgs(event *trace.Event) error { parseInodeMode(modeArg, uint64(mode)) } } + if evtID == Fchmodat { + if flagsArg := GetArg(event, "flags"); flagsArg != nil { + if flags, isInt32 := flagsArg.Value.(int32); isInt32 { + parseFchmodatFlag(flagsArg, uint64(flags)) + } + } + } case SecurityInodeMknod: if modeArg := GetArg(event, "mode"); modeArg != nil { if mode, isUint16 := modeArg.Value.(uint16); isUint16 { @@ -245,6 +264,12 @@ func ParseArgsFDs(event *trace.Event, origTimestamp uint64, fdArgPathMap *bpf.BP } } + if dirfdArg := GetArg(event, "dirfd"); dirfdArg != nil { + if dirfd, isInt32 := dirfdArg.Value.(int32); isInt32 { + parseDirfdAt(dirfdArg, uint64(dirfd)) + } + } + return nil } diff --git a/pkg/events/parse_args_helpers.go b/pkg/events/parse_args_helpers.go index 8e0279b58406..4a973a652ec5 100644 --- a/pkg/events/parse_args_helpers.go +++ b/pkg/events/parse_args_helpers.go @@ -1,6 +1,8 @@ package events import ( + "golang.org/x/sys/unix" + "github.com/aquasecurity/tracee/pkg/events/parsers" "github.com/aquasecurity/tracee/pkg/logger" "github.com/aquasecurity/tracee/types/trace" @@ -19,7 +21,7 @@ func parseSocketDomainArgument(arg *trace.Argument, domain uint64) { arg.Value = "" return } - arg.Value = socketDomainArgument.String() + arg.Value = socketDomainArgument } func parseSocketType(arg *trace.Argument, typ uint64) { @@ -59,7 +61,7 @@ func parseCapability(arg *trace.Argument, capability uint64) { arg.Value = "" return } - arg.Value = capabilityFlagArgument.String() + arg.Value = capabilityFlagArgument } func parseMemProtAlert(arg *trace.Argument, alert uint32) { @@ -90,17 +92,17 @@ func parsePtraceRequestArgument(arg *trace.Argument, req uint64) { arg.Value = "" return } - arg.Value = ptraceRequestArgument.String() + arg.Value = ptraceRequestArgument } -func parsePrctlOption(arg *trace.Argument, opt uint64) { +func parsePrctlOption(arg *trace.Argument, option uint64) { arg.Type = "string" - prctlOptionArgument, err := parsers.ParsePrctlOption(opt) + prctlOptionArgument, err := parsers.ParsePrctlOption(option) if err != nil { arg.Value = "" return } - arg.Value = prctlOptionArgument.String() + arg.Value = prctlOptionArgument } func parseSocketcallCall(arg *trace.Argument, call uint64) { @@ -110,7 +112,7 @@ func parseSocketcallCall(arg *trace.Argument, call uint64) { arg.Value = "" return } - arg.Value = socketcallArgument.String() + arg.Value = socketcallArgument } func parseAccessMode(arg *trace.Argument, mode uint64) { @@ -120,17 +122,45 @@ func parseAccessMode(arg *trace.Argument, mode uint64) { arg.Value = "" return } - arg.Value = accessModeArgument.String() + arg.Value = accessModeArgument +} + +func parseDirfdAt(arg *trace.Argument, dirfd uint64) { + if int32(dirfd) == unix.AT_FDCWD { + arg.Type = "string" + arg.Value = "AT_FDCWD" + return + } +} + +func parseFaccessatFlag(arg *trace.Argument, flags uint64) { + arg.Type = "string" + faccessatFlagArgument, err := parsers.ParseFaccessatFlag(flags) + if err != nil { + arg.Value = "" + return + } + arg.Value = faccessatFlagArgument +} + +func parseFchmodatFlag(arg *trace.Argument, flags uint64) { + arg.Type = "string" + fchmodatFlagArgument, err := parsers.ParseFchmodatFlag(flags) + if err != nil { + arg.Value = "" + return + } + arg.Value = fchmodatFlagArgument } -func parseExecFlag(arg *trace.Argument, flags uint64) { +func parseExecveatFlag(arg *trace.Argument, flags uint64) { arg.Type = "string" - execFlagArgument, err := parsers.ParseExecFlag(flags) + execFlagArgument, err := parsers.ParseExecveatFlag(flags) if err != nil { arg.Value = "" return } - arg.Value = execFlagArgument.String() + arg.Value = execFlagArgument } func parseOpenFlagArgument(arg *trace.Argument, flags uint64) { @@ -140,7 +170,7 @@ func parseOpenFlagArgument(arg *trace.Argument, flags uint64) { arg.Value = "" return } - arg.Value = openFlagArgument.String() + arg.Value = openFlagArgument } func parseCloneFlags(arg *trace.Argument, flags uint64) { @@ -150,7 +180,7 @@ func parseCloneFlags(arg *trace.Argument, flags uint64) { arg.Value = "" return } - arg.Value = cloneFlagArgument.String() + arg.Value = cloneFlagArgument } func parseBPFCmd(arg *trace.Argument, cmd uint64) { @@ -160,7 +190,7 @@ func parseBPFCmd(arg *trace.Argument, cmd uint64) { arg.Value = "" return } - arg.Value = bpfCommandArgument.String() + arg.Value = bpfCommandArgument } func parseSocketLevel(arg *trace.Argument, level uint64) { diff --git a/pkg/events/parsers/data_parsers.go b/pkg/events/parsers/data_parsers.go index 061fb0f18910..56eca5183e34 100644 --- a/pkg/events/parsers/data_parsers.go +++ b/pkg/events/parsers/data_parsers.go @@ -13,11 +13,49 @@ import ( "github.com/aquasecurity/tracee/pkg/utils/environment" ) -type SystemFunctionArgument interface { +// Prefer using the constants from C include files when possible, +// since unix/syscall constants are not always set to the same values. +// For example, `O_LARGEFILE` is defined as 0x8000 (00100000) in C include, +// but as 0x0 in unix package. + +/* +#include +#include +#include +#include +#include +#include +#include +#include + +// defined in fcntl.h but it conflicts with linux/fcntl.h +#define F_OK 0 +#define X_OK 1 +#define W_OK 2 +#define R_OK 4 +*/ +import "C" + +type systemFunctionArgument interface { fmt.Stringer Value() uint64 } +var _ = systemFunctionArgument(SystemFunctionArgument{}) + +type SystemFunctionArgument struct { + rawValue uint64 + stringValue string +} + +func (a SystemFunctionArgument) Value() uint64 { + return a.rawValue +} + +func (a SystemFunctionArgument) String() string { + return a.stringValue +} + // optionsAreContainedInArgument checks whether the argument (rawArgument) // contains all of the 'options' such as with flags passed to the clone flag. // This function takes an arbitrary number of uint64. @@ -40,1239 +78,970 @@ func optionIsContainedInArgument(rawArgument uint64, option uint64) bool { return rawArgument&option == option } -type CloneFlagArgument struct { - rawValue uint64 - stringValue string -} +// +// Parsers +// -// revive:disable +func buildStringFromValues(sb *strings.Builder, argValues []SystemFunctionArgument, rawArgument uint64) { + for _, arg := range argValues { + if optionIsContainedInArgument(rawArgument, arg.Value()) { + if sb.Len() > 0 { + sb.WriteByte('|') + } + sb.WriteString(arg.String()) + } + } +} var ( - // These values are copied from uapi/linux/sched.h - CLONE_VM CloneFlagArgument = CloneFlagArgument{rawValue: 0x00000100, stringValue: "CLONE_VM"} - CLONE_FS CloneFlagArgument = CloneFlagArgument{rawValue: 0x00000200, stringValue: "CLONE_FS"} - CLONE_FILES CloneFlagArgument = CloneFlagArgument{rawValue: 0x00000400, stringValue: "CLONE_FILES"} - CLONE_SIGHAND CloneFlagArgument = CloneFlagArgument{rawValue: 0x00000800, stringValue: "CLONE_SIGHAND"} - CLONE_PIDFD CloneFlagArgument = CloneFlagArgument{rawValue: 0x00001000, stringValue: "CLONE_PIDFD"} - CLONE_PTRACE CloneFlagArgument = CloneFlagArgument{rawValue: 0x00002000, stringValue: "CLONE_PTRACE"} - CLONE_VFORK CloneFlagArgument = CloneFlagArgument{rawValue: 0x00004000, stringValue: "CLONE_VFORK"} - CLONE_PARENT CloneFlagArgument = CloneFlagArgument{rawValue: 0x00008000, stringValue: "CLONE_PARENT"} - CLONE_THREAD CloneFlagArgument = CloneFlagArgument{rawValue: 0x00010000, stringValue: "CLONE_THREAD"} - CLONE_NEWNS CloneFlagArgument = CloneFlagArgument{rawValue: 0x00020000, stringValue: "CLONE_NEWNS"} - CLONE_SYSVSEM CloneFlagArgument = CloneFlagArgument{rawValue: 0x00040000, stringValue: "CLONE_SYSVSEM"} - CLONE_SETTLS CloneFlagArgument = CloneFlagArgument{rawValue: 0x00080000, stringValue: "CLONE_SETTLS"} - CLONE_PARENT_SETTID CloneFlagArgument = CloneFlagArgument{rawValue: 0x00100000, stringValue: "CLONE_PARENT_SETTID"} - CLONE_CHILD_CLEARTID CloneFlagArgument = CloneFlagArgument{rawValue: 0x00200000, stringValue: "CLONE_CHILD_CLEARTID"} - CLONE_DETACHED CloneFlagArgument = CloneFlagArgument{rawValue: 0x00400000, stringValue: "CLONE_DETACHED"} - CLONE_UNTRACED CloneFlagArgument = CloneFlagArgument{rawValue: 0x00800000, stringValue: "CLONE_UNTRACED"} - CLONE_CHILD_SETTID CloneFlagArgument = CloneFlagArgument{rawValue: 0x01000000, stringValue: "CLONE_CHILD_SETTID"} - CLONE_NEWCGROUP CloneFlagArgument = CloneFlagArgument{rawValue: 0x02000000, stringValue: "CLONE_NEWCGROUP"} - CLONE_NEWUTS CloneFlagArgument = CloneFlagArgument{rawValue: 0x04000000, stringValue: "CLONE_NEWUTS"} - CLONE_NEWIPC CloneFlagArgument = CloneFlagArgument{rawValue: 0x08000000, stringValue: "CLONE_NEWIPC"} - CLONE_NEWUSER CloneFlagArgument = CloneFlagArgument{rawValue: 0x10000000, stringValue: "CLONE_NEWUSER"} - CLONE_NEWPID CloneFlagArgument = CloneFlagArgument{rawValue: 0x20000000, stringValue: "CLONE_NEWPID"} - CLONE_NEWNET CloneFlagArgument = CloneFlagArgument{rawValue: 0x40000000, stringValue: "CLONE_NEWNET"} - CLONE_IO CloneFlagArgument = CloneFlagArgument{rawValue: 0x80000000, stringValue: "CLONE_IO"} + // from linux/sched.h + CLONE_VM = SystemFunctionArgument{rawValue: C.CLONE_VM, stringValue: "CLONE_VM"} + CLONE_FS = SystemFunctionArgument{rawValue: C.CLONE_FS, stringValue: "CLONE_FS"} + CLONE_FILES = SystemFunctionArgument{rawValue: C.CLONE_FILES, stringValue: "CLONE_FILES"} + CLONE_SIGHAND = SystemFunctionArgument{rawValue: C.CLONE_SIGHAND, stringValue: "CLONE_SIGHAND"} + CLONE_PIDFD = SystemFunctionArgument{rawValue: C.CLONE_PIDFD, stringValue: "CLONE_PIDFD"} + CLONE_PTRACE = SystemFunctionArgument{rawValue: C.CLONE_PTRACE, stringValue: "CLONE_PTRACE"} + CLONE_VFORK = SystemFunctionArgument{rawValue: C.CLONE_VFORK, stringValue: "CLONE_VFORK"} + CLONE_PARENT = SystemFunctionArgument{rawValue: C.CLONE_PARENT, stringValue: "CLONE_PARENT"} + CLONE_THREAD = SystemFunctionArgument{rawValue: C.CLONE_THREAD, stringValue: "CLONE_THREAD"} + CLONE_NEWNS = SystemFunctionArgument{rawValue: C.CLONE_NEWNS, stringValue: "CLONE_NEWNS"} + CLONE_SYSVSEM = SystemFunctionArgument{rawValue: C.CLONE_SYSVSEM, stringValue: "CLONE_SYSVSEM"} + CLONE_SETTLS = SystemFunctionArgument{rawValue: C.CLONE_SETTLS, stringValue: "CLONE_SETTLS"} + CLONE_PARENT_SETTID = SystemFunctionArgument{rawValue: C.CLONE_PARENT_SETTID, stringValue: "CLONE_PARENT_SETTID"} + CLONE_CHILD_CLEARTID = SystemFunctionArgument{rawValue: C.CLONE_CHILD_CLEARTID, stringValue: "CLONE_CHILD_CLEARTID"} + CLONE_DETACHED = SystemFunctionArgument{rawValue: C.CLONE_DETACHED, stringValue: "CLONE_DETACHED"} + CLONE_UNTRACED = SystemFunctionArgument{rawValue: C.CLONE_UNTRACED, stringValue: "CLONE_UNTRACED"} + CLONE_CHILD_SETTID = SystemFunctionArgument{rawValue: C.CLONE_CHILD_SETTID, stringValue: "CLONE_CHILD_SETTID"} + CLONE_NEWCGROUP = SystemFunctionArgument{rawValue: C.CLONE_NEWCGROUP, stringValue: "CLONE_NEWCGROUP"} + CLONE_NEWUTS = SystemFunctionArgument{rawValue: C.CLONE_NEWUTS, stringValue: "CLONE_NEWUTS"} + CLONE_NEWIPC = SystemFunctionArgument{rawValue: C.CLONE_NEWIPC, stringValue: "CLONE_NEWIPC"} + CLONE_NEWUSER = SystemFunctionArgument{rawValue: C.CLONE_NEWUSER, stringValue: "CLONE_NEWUSER"} + CLONE_NEWPID = SystemFunctionArgument{rawValue: C.CLONE_NEWPID, stringValue: "CLONE_NEWPID"} + CLONE_NEWNET = SystemFunctionArgument{rawValue: C.CLONE_NEWNET, stringValue: "CLONE_NEWNET"} + CLONE_IO = SystemFunctionArgument{rawValue: C.CLONE_IO, stringValue: "CLONE_IO"} ) -// revive:enable - -func (c CloneFlagArgument) Value() uint64 { return c.rawValue } -func (c CloneFlagArgument) String() string { return c.stringValue } - -func ParseCloneFlags(rawValue uint64) (CloneFlagArgument, error) { - if rawValue == 0 { - return CloneFlagArgument{}, nil +var cloneFlagsValues = []SystemFunctionArgument{ + CLONE_VM, + CLONE_FS, + CLONE_FILES, + CLONE_SIGHAND, + CLONE_PIDFD, + CLONE_PTRACE, + CLONE_VFORK, + CLONE_PARENT, + CLONE_THREAD, + CLONE_NEWNS, + CLONE_SYSVSEM, + CLONE_SETTLS, + CLONE_PARENT_SETTID, + CLONE_CHILD_CLEARTID, + CLONE_DETACHED, + CLONE_UNTRACED, + CLONE_CHILD_SETTID, + CLONE_NEWCGROUP, + CLONE_NEWUTS, + CLONE_NEWIPC, + CLONE_NEWUSER, + CLONE_NEWPID, + CLONE_NEWNET, + CLONE_IO, +} + +// ParseCloneFlags parses the `flags` bitmask argument of the `clone` syscall. +func ParseCloneFlags(flags uint64) (string, error) { + if flags == 0 { + return "", nil } - var f []string - if optionIsContainedInArgument(rawValue, CLONE_VM.Value()) { - f = append(f, CLONE_VM.String()) - } - if optionIsContainedInArgument(rawValue, CLONE_FS.Value()) { - f = append(f, CLONE_FS.String()) - } - if optionIsContainedInArgument(rawValue, CLONE_FILES.Value()) { - f = append(f, CLONE_FILES.String()) - } - if optionIsContainedInArgument(rawValue, CLONE_SIGHAND.Value()) { - f = append(f, CLONE_SIGHAND.String()) - } - if optionIsContainedInArgument(rawValue, CLONE_PIDFD.Value()) { - f = append(f, CLONE_PIDFD.String()) - } - if optionIsContainedInArgument(rawValue, CLONE_PTRACE.Value()) { - f = append(f, CLONE_PTRACE.String()) - } - if optionIsContainedInArgument(rawValue, CLONE_VFORK.Value()) { - f = append(f, CLONE_VFORK.String()) - } - if optionIsContainedInArgument(rawValue, CLONE_PARENT.Value()) { - f = append(f, CLONE_PARENT.String()) - } - if optionIsContainedInArgument(rawValue, CLONE_THREAD.Value()) { - f = append(f, CLONE_THREAD.String()) - } - if optionIsContainedInArgument(rawValue, CLONE_NEWNS.Value()) { - f = append(f, CLONE_NEWNS.String()) - } - if optionIsContainedInArgument(rawValue, CLONE_SYSVSEM.Value()) { - f = append(f, CLONE_SYSVSEM.String()) - } - if optionIsContainedInArgument(rawValue, CLONE_SETTLS.Value()) { - f = append(f, CLONE_SETTLS.String()) - } - if optionIsContainedInArgument(rawValue, CLONE_PARENT_SETTID.Value()) { - f = append(f, CLONE_PARENT_SETTID.String()) - } - if optionIsContainedInArgument(rawValue, CLONE_CHILD_CLEARTID.Value()) { - f = append(f, CLONE_CHILD_CLEARTID.String()) - } - if optionIsContainedInArgument(rawValue, CLONE_DETACHED.Value()) { - f = append(f, CLONE_DETACHED.String()) - } - if optionIsContainedInArgument(rawValue, CLONE_UNTRACED.Value()) { - f = append(f, CLONE_UNTRACED.String()) - } - if optionIsContainedInArgument(rawValue, CLONE_CHILD_SETTID.Value()) { - f = append(f, CLONE_CHILD_SETTID.String()) - } - if optionIsContainedInArgument(rawValue, CLONE_NEWCGROUP.Value()) { - f = append(f, CLONE_NEWCGROUP.String()) - } - if optionIsContainedInArgument(rawValue, CLONE_NEWUTS.Value()) { - f = append(f, CLONE_NEWUTS.String()) - } - if optionIsContainedInArgument(rawValue, CLONE_NEWIPC.Value()) { - f = append(f, CLONE_NEWIPC.String()) - } - if optionIsContainedInArgument(rawValue, CLONE_NEWUSER.Value()) { - f = append(f, CLONE_NEWUSER.String()) - } - if optionIsContainedInArgument(rawValue, CLONE_NEWPID.Value()) { - f = append(f, CLONE_NEWPID.String()) - } - if optionIsContainedInArgument(rawValue, CLONE_NEWNET.Value()) { - f = append(f, CLONE_NEWNET.String()) - } - if optionIsContainedInArgument(rawValue, CLONE_IO.Value()) { - f = append(f, CLONE_IO.String()) - } - if len(f) == 0 { - return CloneFlagArgument{}, fmt.Errorf("no valid clone flag values present in raw value: 0x%x", rawValue) - } + var sb strings.Builder + buildStringFromValues(&sb, cloneFlagsValues, flags) - return CloneFlagArgument{stringValue: strings.Join(f, "|"), rawValue: rawValue}, nil -} + if sb.Len() == 0 { + return "", fmt.Errorf("no valid clone flag values present in flags value: 0x%x", flags) + } -type OpenFlagArgument struct { - rawValue uint64 - stringValue string + return sb.String(), nil } -// revive:disable - var ( - // These values are copied from uapi/asm-generic/fcntl.h - O_ACCMODE OpenFlagArgument = OpenFlagArgument{rawValue: 00000003, stringValue: "O_ACCMODE"} - O_RDONLY OpenFlagArgument = OpenFlagArgument{rawValue: 00000000, stringValue: "O_RDONLY"} - O_WRONLY OpenFlagArgument = OpenFlagArgument{rawValue: 00000001, stringValue: "O_WRONLY"} - O_RDWR OpenFlagArgument = OpenFlagArgument{rawValue: 00000002, stringValue: "O_RDWR"} - O_CREAT OpenFlagArgument = OpenFlagArgument{rawValue: 00000100, stringValue: "O_CREAT"} - O_EXCL OpenFlagArgument = OpenFlagArgument{rawValue: 00000200, stringValue: "O_EXCL"} - O_NOCTTY OpenFlagArgument = OpenFlagArgument{rawValue: 00000400, stringValue: "O_NOCTTY"} - O_TRUNC OpenFlagArgument = OpenFlagArgument{rawValue: 00001000, stringValue: "O_TRUNC"} - O_APPEND OpenFlagArgument = OpenFlagArgument{rawValue: 00002000, stringValue: "O_APPEND"} - O_NONBLOCK OpenFlagArgument = OpenFlagArgument{rawValue: 00004000, stringValue: "O_NONBLOCK"} - O_DSYNC OpenFlagArgument = OpenFlagArgument{rawValue: 00010000, stringValue: "O_DSYNC"} - O_SYNC OpenFlagArgument = OpenFlagArgument{rawValue: 04010000, stringValue: "O_SYNC"} - FASYNC OpenFlagArgument = OpenFlagArgument{rawValue: 00020000, stringValue: "FASYNC"} - O_DIRECT OpenFlagArgument = OpenFlagArgument{rawValue: 00040000, stringValue: "O_DIRECT"} - O_LARGEFILE OpenFlagArgument = OpenFlagArgument{rawValue: 00100000, stringValue: "O_LARGEFILE"} - O_DIRECTORY OpenFlagArgument = OpenFlagArgument{rawValue: 00200000, stringValue: "O_DIRECTORY"} - O_NOFOLLOW OpenFlagArgument = OpenFlagArgument{rawValue: 00400000, stringValue: "O_NOFOLLOW"} - O_NOATIME OpenFlagArgument = OpenFlagArgument{rawValue: 01000000, stringValue: "O_NOATIME"} - O_CLOEXEC OpenFlagArgument = OpenFlagArgument{rawValue: 02000000, stringValue: "O_CLOEXEC"} - O_PATH OpenFlagArgument = OpenFlagArgument{rawValue: 040000000, stringValue: "O_PATH"} - O_TMPFILE OpenFlagArgument = OpenFlagArgument{rawValue: 020000000, stringValue: "O_TMPFILE"} + // from asm-generic/fcntl.h + O_ACCMODE = SystemFunctionArgument{rawValue: C.O_ACCMODE, stringValue: "O_ACCMODE"} + O_RDONLY = SystemFunctionArgument{rawValue: C.O_RDONLY, stringValue: "O_RDONLY"} + O_WRONLY = SystemFunctionArgument{rawValue: C.O_WRONLY, stringValue: "O_WRONLY"} + O_RDWR = SystemFunctionArgument{rawValue: C.O_RDWR, stringValue: "O_RDWR"} + O_CREAT = SystemFunctionArgument{rawValue: C.O_CREAT, stringValue: "O_CREAT"} + O_EXCL = SystemFunctionArgument{rawValue: C.O_EXCL, stringValue: "O_EXCL"} + O_NOCTTY = SystemFunctionArgument{rawValue: C.O_NOCTTY, stringValue: "O_NOCTTY"} + O_TRUNC = SystemFunctionArgument{rawValue: C.O_TRUNC, stringValue: "O_TRUNC"} + O_APPEND = SystemFunctionArgument{rawValue: C.O_APPEND, stringValue: "O_APPEND"} + O_NONBLOCK = SystemFunctionArgument{rawValue: C.O_NONBLOCK, stringValue: "O_NONBLOCK"} + O_DSYNC = SystemFunctionArgument{rawValue: C.O_DSYNC, stringValue: "O_DSYNC"} + O_SYNC = SystemFunctionArgument{rawValue: C.O_SYNC, stringValue: "O_SYNC"} + FASYNC = SystemFunctionArgument{rawValue: C.FASYNC, stringValue: "FASYNC"} + O_DIRECT = SystemFunctionArgument{rawValue: C.O_DIRECT, stringValue: "O_DIRECT"} + O_LARGEFILE = SystemFunctionArgument{rawValue: C.O_LARGEFILE, stringValue: "O_LARGEFILE"} + O_DIRECTORY = SystemFunctionArgument{rawValue: C.O_DIRECTORY, stringValue: "O_DIRECTORY"} + O_NOFOLLOW = SystemFunctionArgument{rawValue: C.O_NOFOLLOW, stringValue: "O_NOFOLLOW"} + O_NOATIME = SystemFunctionArgument{rawValue: C.O_NOATIME, stringValue: "O_NOATIME"} + O_CLOEXEC = SystemFunctionArgument{rawValue: C.O_CLOEXEC, stringValue: "O_CLOEXEC"} + O_PATH = SystemFunctionArgument{rawValue: C.O_PATH, stringValue: "O_PATH"} + O_TMPFILE = SystemFunctionArgument{rawValue: C.O_TMPFILE, stringValue: "O_TMPFILE"} ) -// revive:enable - -func (o OpenFlagArgument) Value() uint64 { return o.rawValue } -func (o OpenFlagArgument) String() string { return o.stringValue } - -// ParseOpenFlagArgument parses the `flags` bitmask argument of the `open` syscall +var openFlagsValues = []SystemFunctionArgument{ + // O_ACCMODE, // macro for access mode, so not included + + // special cases checked before the loop in ParseOpenFlagArgument + // O_RDONLY, + // O_WRONLY, + // O_RDWR, + O_CREAT, + O_EXCL, + O_NOCTTY, + O_TRUNC, + O_APPEND, + O_NONBLOCK, + O_DSYNC, + O_SYNC, + FASYNC, + O_DIRECT, + O_LARGEFILE, + O_DIRECTORY, + O_NOFOLLOW, + O_NOATIME, + O_CLOEXEC, + O_PATH, + O_TMPFILE, +} + +// ParseOpenFlagArgument parses the `flags` bitmask argument of the `open` syscall. // http://man7.org/linux/man-pages/man2/open.2.html // https://elixir.bootlin.com/linux/v5.5.3/source/include/uapi/asm-generic/fcntl.h -func ParseOpenFlagArgument(rawValue uint64) (OpenFlagArgument, error) { - if rawValue == 0 { - return OpenFlagArgument{}, nil +func ParseOpenFlagArgument(flags uint64) (string, error) { + if flags == 0 { + return O_RDONLY.String(), nil } - var f []string + + var sb strings.Builder // access mode switch { - case optionIsContainedInArgument(rawValue, O_WRONLY.Value()): - f = append(f, O_WRONLY.String()) - case optionIsContainedInArgument(rawValue, O_RDWR.Value()): - f = append(f, O_RDWR.String()) + case optionIsContainedInArgument(flags, O_WRONLY.Value()): + sb.WriteString(O_WRONLY.String()) + case optionIsContainedInArgument(flags, O_RDWR.Value()): + sb.WriteString(O_RDWR.String()) default: - f = append(f, O_RDONLY.String()) + sb.WriteString(O_RDONLY.String()) } // file creation and status flags - if optionIsContainedInArgument(rawValue, O_CREAT.Value()) { - f = append(f, O_CREAT.String()) - } - if optionIsContainedInArgument(rawValue, O_EXCL.Value()) { - f = append(f, O_EXCL.String()) - } - if optionIsContainedInArgument(rawValue, O_NOCTTY.Value()) { - f = append(f, O_NOCTTY.String()) - } - if optionIsContainedInArgument(rawValue, O_TRUNC.Value()) { - f = append(f, O_TRUNC.String()) - } - if optionIsContainedInArgument(rawValue, O_APPEND.Value()) { - f = append(f, O_APPEND.String()) - } - if optionIsContainedInArgument(rawValue, O_NONBLOCK.Value()) { - f = append(f, O_NONBLOCK.String()) - } - if optionIsContainedInArgument(rawValue, O_SYNC.Value()) { - f = append(f, O_SYNC.String()) - } - if optionIsContainedInArgument(rawValue, FASYNC.Value()) { - f = append(f, FASYNC.String()) - } - if optionIsContainedInArgument(rawValue, O_LARGEFILE.Value()) { - f = append(f, O_LARGEFILE.String()) - } - if optionIsContainedInArgument(rawValue, O_DIRECTORY.Value()) { - f = append(f, O_DIRECTORY.String()) - } - if optionIsContainedInArgument(rawValue, O_NOFOLLOW.Value()) { - f = append(f, O_NOFOLLOW.String()) - } - if optionIsContainedInArgument(rawValue, O_CLOEXEC.Value()) { - f = append(f, O_CLOEXEC.String()) - } - if optionIsContainedInArgument(rawValue, O_DIRECT.Value()) { - f = append(f, O_DIRECT.String()) - } - if optionIsContainedInArgument(rawValue, O_NOATIME.Value()) { - f = append(f, O_NOATIME.String()) - } - if optionIsContainedInArgument(rawValue, O_PATH.Value()) { - f = append(f, O_PATH.String()) - } - if optionIsContainedInArgument(rawValue, O_TMPFILE.Value()) { - f = append(f, O_TMPFILE.String()) - } - - if len(f) == 0 { - return OpenFlagArgument{}, fmt.Errorf("no valid open flag values present in raw value: 0x%x", rawValue) + for _, a := range openFlagsValues { + if optionIsContainedInArgument(flags, a.Value()) { + sb.WriteByte('|') + sb.WriteString(a.String()) + } } - return OpenFlagArgument{rawValue: rawValue, stringValue: strings.Join(f, "|")}, nil -} - -type AccessModeArgument struct { - rawValue uint64 - stringValue string + return sb.String(), nil } -// revive:disable - var ( - F_OK AccessModeArgument = AccessModeArgument{rawValue: 0, stringValue: "F_OK"} - X_OK AccessModeArgument = AccessModeArgument{rawValue: 1, stringValue: "X_OK"} - W_OK AccessModeArgument = AccessModeArgument{rawValue: 2, stringValue: "W_OK"} - R_OK AccessModeArgument = AccessModeArgument{rawValue: 4, stringValue: "R_OK"} + // from this file + F_OK = SystemFunctionArgument{rawValue: C.F_OK, stringValue: "F_OK"} + X_OK = SystemFunctionArgument{rawValue: C.X_OK, stringValue: "X_OK"} + W_OK = SystemFunctionArgument{rawValue: C.W_OK, stringValue: "W_OK"} + R_OK = SystemFunctionArgument{rawValue: C.R_OK, stringValue: "R_OK"} ) -// revive:enable - -func (a AccessModeArgument) Value() uint64 { return a.rawValue } - -func (a AccessModeArgument) String() string { return a.stringValue } +var accessModeValues = []SystemFunctionArgument{ + // F_OK, // special case checked before the loop in ParseAccessMode + X_OK, + W_OK, + R_OK, +} -// ParseAccessMode parses the mode from the `access` system call +// ParseAccessMode parses the mode from the `access` system call. // http://man7.org/linux/man-pages/man2/access.2.html -func ParseAccessMode(rawValue uint64) (AccessModeArgument, error) { - if rawValue == 0 { - return AccessModeArgument{}, nil - } - var f []string - if rawValue == 0x0 { - f = append(f, F_OK.String()) - } else { - if optionIsContainedInArgument(rawValue, R_OK.Value()) { - f = append(f, R_OK.String()) - } - if optionIsContainedInArgument(rawValue, W_OK.Value()) { - f = append(f, W_OK.String()) - } - if optionIsContainedInArgument(rawValue, X_OK.Value()) { - f = append(f, X_OK.String()) - } +func ParseAccessMode(mode uint64) (string, error) { + if mode == 0 { + return F_OK.String(), nil } - if len(f) == 0 { - return AccessModeArgument{}, fmt.Errorf("no valid access mode values present in raw value: 0x%x", rawValue) - } + var sb strings.Builder - return AccessModeArgument{stringValue: strings.Join(f, "|"), rawValue: rawValue}, nil -} + buildStringFromValues(&sb, accessModeValues, mode) -type ExecFlagArgument struct { - rawValue uint64 - stringValue string -} + if sb.Len() == 0 { + return "", fmt.Errorf("no valid access mode values present in mode value: 0x%x", mode) + } -// revive:disable + return sb.String(), nil +} var ( - AT_SYMLINK_NOFOLLOW ExecFlagArgument = ExecFlagArgument{stringValue: "AT_SYMLINK_NOFOLLOW", rawValue: 0x100} - AT_EACCESS ExecFlagArgument = ExecFlagArgument{stringValue: "AT_EACCESS", rawValue: 0x200} - AT_REMOVEDIR ExecFlagArgument = ExecFlagArgument{stringValue: "AT_REMOVEDIR", rawValue: 0x200} - AT_SYMLINK_FOLLOW ExecFlagArgument = ExecFlagArgument{stringValue: "AT_SYMLINK_FOLLOW", rawValue: 0x400} - AT_NO_AUTOMOUNT ExecFlagArgument = ExecFlagArgument{stringValue: "AT_NO_AUTOMOUNT", rawValue: 0x800} - AT_EMPTY_PATH ExecFlagArgument = ExecFlagArgument{stringValue: "AT_EMPTY_PATH", rawValue: 0x1000} - AT_STATX_SYNC_TYPE ExecFlagArgument = ExecFlagArgument{stringValue: "AT_STATX_SYNC_TYPE", rawValue: 0x6000} - AT_STATX_SYNC_AS_STAT ExecFlagArgument = ExecFlagArgument{stringValue: "AT_STATX_SYNC_AS_STAT", rawValue: 0x0000} - AT_STATX_FORCE_SYNC ExecFlagArgument = ExecFlagArgument{stringValue: "AT_STATX_FORCE_SYNC", rawValue: 0x2000} - AT_STATX_DONT_SYNC ExecFlagArgument = ExecFlagArgument{stringValue: "AT_STATX_DONT_SYNC", rawValue: 0x4000} - AT_RECURSIVE ExecFlagArgument = ExecFlagArgument{stringValue: "AT_RECURSIVE", rawValue: 0x8000} + // from linux/fcntl.h + AT_SYMLINK_NOFOLLOW = SystemFunctionArgument{rawValue: C.AT_SYMLINK_NOFOLLOW, stringValue: "AT_SYMLINK_NOFOLLOW"} + AT_EACCESS = SystemFunctionArgument{rawValue: C.AT_EACCESS, stringValue: "AT_EACCESS"} + AT_REMOVEDIR = SystemFunctionArgument{rawValue: C.AT_REMOVEDIR, stringValue: "AT_REMOVEDIR"} + AT_SYMLINK_FOLLOW = SystemFunctionArgument{rawValue: C.AT_SYMLINK_FOLLOW, stringValue: "AT_SYMLINK_FOLLOW"} + AT_NO_AUTOMOUNT = SystemFunctionArgument{rawValue: C.AT_NO_AUTOMOUNT, stringValue: "AT_NO_AUTOMOUNT"} + AT_EMPTY_PATH = SystemFunctionArgument{rawValue: C.AT_EMPTY_PATH, stringValue: "AT_EMPTY_PATH"} + AT_STATX_SYNC_TYPE = SystemFunctionArgument{rawValue: C.AT_STATX_SYNC_TYPE, stringValue: "AT_STATX_SYNC_TYPE"} + AT_STATX_SYNC_AS_STAT = SystemFunctionArgument{rawValue: C.AT_STATX_SYNC_AS_STAT, stringValue: "AT_STATX_SYNC_AS_STAT"} + AT_STATX_FORCE_SYNC = SystemFunctionArgument{rawValue: C.AT_STATX_FORCE_SYNC, stringValue: "AT_STATX_FORCE_SYNC"} + AT_STATX_DONT_SYNC = SystemFunctionArgument{rawValue: C.AT_STATX_DONT_SYNC, stringValue: "AT_STATX_DONT_SYNC"} + AT_RECURSIVE = SystemFunctionArgument{rawValue: C.AT_RECURSIVE, stringValue: "AT_RECURSIVE"} ) -// revive:enable +var atFlagsValues = []SystemFunctionArgument{ + AT_SYMLINK_NOFOLLOW, + AT_EACCESS, + AT_REMOVEDIR, + AT_SYMLINK_FOLLOW, + AT_NO_AUTOMOUNT, + AT_EMPTY_PATH, + AT_STATX_SYNC_TYPE, + AT_STATX_SYNC_AS_STAT, + AT_STATX_FORCE_SYNC, + AT_STATX_DONT_SYNC, + AT_RECURSIVE, +} -func (e ExecFlagArgument) Value() uint64 { return e.rawValue } -func (e ExecFlagArgument) String() string { return e.stringValue } +var faccessatFlagsValues = []SystemFunctionArgument{ + AT_EACCESS, + AT_EMPTY_PATH, + AT_SYMLINK_NOFOLLOW, +} -func ParseExecFlag(rawValue uint64) (ExecFlagArgument, error) { - if rawValue == 0 { - return ExecFlagArgument{}, nil +// ParseFaccessatFlag parses the `flags` bitmask argument of the `faccessat` syscall. +// It uses the same mode values as ParseAccessMode, but also includes AT_* flags. +func ParseFaccessatFlag(flags uint64) (string, error) { + if flags == 0 { + return "", nil } - var f []string - if optionIsContainedInArgument(rawValue, AT_EMPTY_PATH.Value()) { - f = append(f, AT_EMPTY_PATH.String()) - } - if optionIsContainedInArgument(rawValue, AT_SYMLINK_NOFOLLOW.Value()) { - f = append(f, AT_SYMLINK_NOFOLLOW.String()) - } - if optionIsContainedInArgument(rawValue, AT_EACCESS.Value()) { - f = append(f, AT_EACCESS.String()) - } - if optionIsContainedInArgument(rawValue, AT_REMOVEDIR.Value()) { - f = append(f, AT_REMOVEDIR.String()) - } - if optionIsContainedInArgument(rawValue, AT_NO_AUTOMOUNT.Value()) { - f = append(f, AT_NO_AUTOMOUNT.String()) - } - if optionIsContainedInArgument(rawValue, AT_STATX_SYNC_TYPE.Value()) { - f = append(f, AT_STATX_SYNC_TYPE.String()) - } - if optionIsContainedInArgument(rawValue, AT_STATX_FORCE_SYNC.Value()) { - f = append(f, AT_STATX_FORCE_SYNC.String()) - } - if optionIsContainedInArgument(rawValue, AT_STATX_DONT_SYNC.Value()) { - f = append(f, AT_STATX_DONT_SYNC.String()) - } - if optionIsContainedInArgument(rawValue, AT_RECURSIVE.Value()) { - f = append(f, AT_RECURSIVE.String()) - } - if len(f) == 0 { - return ExecFlagArgument{}, fmt.Errorf("no valid exec flag values present in raw value: 0x%x", rawValue) + var sb strings.Builder + + buildStringFromValues(&sb, faccessatFlagsValues, flags) + + if sb.Len() == 0 { + return "", fmt.Errorf("no valid faccessat flag values present in flags value: 0x%x", flags) } - return ExecFlagArgument{stringValue: strings.Join(f, "|"), rawValue: rawValue}, nil + + return sb.String(), nil } -type CapabilityFlagArgument uint64 +var fchmodatFlagsValues = []SystemFunctionArgument{ + AT_SYMLINK_NOFOLLOW, +} -const ( - CAP_CHOWN CapabilityFlagArgument = iota - CAP_DAC_OVERRIDE - CAP_DAC_READ_SEARCH - CAP_FOWNER - CAP_FSETID - CAP_KILL - CAP_SETGID - CAP_SETUID - CAP_SETPCAP - CAP_LINUX_IMMUTABLE - CAP_NET_BIND_SERVICE - CAP_NET_BROADCAST - CAP_NET_ADMIN - CAP_NET_RAW - CAP_IPC_LOCK - CAP_IPC_OWNER - CAP_SYS_MODULE - CAP_SYS_RAWIO - CAP_SYS_CHROOT - CAP_SYS_PTRACE - CAP_SYS_PACCT - CAP_SYS_ADMIN - CAP_SYS_BOOT - CAP_SYS_NICE - CAP_SYS_RESOURCE - CAP_SYS_TIME - CAP_SYS_TTY_CONFIG - CAP_MKNOD - CAP_LEASE - CAP_AUDIT_WRITE - CAP_AUDIT_CONTROL - CAP_SETFCAP - CAP_MAC_OVERRIDE - CAP_MAC_ADMIN - CAP_SYSLOG - CAP_WAKE_ALARM - CAP_BLOCK_SUSPEND - CAP_AUDIT_READ -) +func ParseFchmodatFlag(flags uint64) (string, error) { + if flags == 0 { + return "", nil + } -func (c CapabilityFlagArgument) Value() uint64 { return uint64(c) } - -var capFlagStringMap = map[CapabilityFlagArgument]string{ - CAP_CHOWN: "CAP_CHOWN", - CAP_DAC_OVERRIDE: "CAP_DAC_OVERRIDE", - CAP_DAC_READ_SEARCH: "CAP_DAC_READ_SEARCH", - CAP_FOWNER: "CAP_FOWNER", - CAP_FSETID: "CAP_FSETID", - CAP_KILL: "CAP_KILL", - CAP_SETGID: "CAP_SETGID", - CAP_SETUID: "CAP_SETUID", - CAP_SETPCAP: "CAP_SETPCAP", - CAP_LINUX_IMMUTABLE: "CAP_LINUX_IMMUTABLE", - CAP_NET_BIND_SERVICE: "CAP_NET_BIND_SERVICE", - CAP_NET_BROADCAST: "CAP_NET_BROADCAST", - CAP_NET_ADMIN: "CAP_NET_ADMIN", - CAP_NET_RAW: "CAP_NET_RAW", - CAP_IPC_LOCK: "CAP_IPC_LOCK", - CAP_IPC_OWNER: "CAP_IPC_OWNER", - CAP_SYS_MODULE: "CAP_SYS_MODULE", - CAP_SYS_RAWIO: "CAP_SYS_RAWIO", - CAP_SYS_CHROOT: "CAP_SYS_CHROOT", - CAP_SYS_PTRACE: "CAP_SYS_PTRACE", - CAP_SYS_PACCT: "CAP_SYS_PACCT", - CAP_SYS_ADMIN: "CAP_SYS_ADMIN", - CAP_SYS_BOOT: "CAP_SYS_BOOT", - CAP_SYS_NICE: "CAP_SYS_NICE", - CAP_SYS_RESOURCE: "CAP_SYS_RESOURCE", - CAP_SYS_TIME: "CAP_SYS_TIME", - CAP_SYS_TTY_CONFIG: "CAP_SYS_TTY_CONFIG", - CAP_MKNOD: "CAP_MKNOD", - CAP_LEASE: "CAP_LEASE", - CAP_AUDIT_WRITE: "CAP_AUDIT_WRITE", - CAP_AUDIT_CONTROL: "CAP_AUDIT_CONTROL", - CAP_SETFCAP: "CAP_SETFCAP", - CAP_MAC_OVERRIDE: "CAP_MAC_OVERRIDE", - CAP_MAC_ADMIN: "CAP_MAC_ADMIN", - CAP_SYSLOG: "CAP_SYSLOG", - CAP_WAKE_ALARM: "CAP_WAKE_ALARM", - CAP_BLOCK_SUSPEND: "CAP_BLOCK_SUSPEND", - CAP_AUDIT_READ: "CAP_AUDIT_READ", -} - -func (c CapabilityFlagArgument) String() string { - var res string + var sb strings.Builder - if capName, ok := capFlagStringMap[c]; ok { - res = capName - } else { - res = strconv.Itoa(int(c)) + buildStringFromValues(&sb, fchmodatFlagsValues, flags) + + if sb.Len() == 0 { + return "", fmt.Errorf("no valid fchmodat flag values present in flags value: 0x%x", flags) } - return res + + return sb.String(), nil } -var capabilitiesMap = map[uint64]CapabilityFlagArgument{ - CAP_CHOWN.Value(): CAP_CHOWN, - CAP_DAC_OVERRIDE.Value(): CAP_DAC_OVERRIDE, - CAP_DAC_READ_SEARCH.Value(): CAP_DAC_READ_SEARCH, - CAP_FOWNER.Value(): CAP_FOWNER, - CAP_FSETID.Value(): CAP_FSETID, - CAP_KILL.Value(): CAP_KILL, - CAP_SETGID.Value(): CAP_SETGID, - CAP_SETUID.Value(): CAP_SETUID, - CAP_SETPCAP.Value(): CAP_SETPCAP, - CAP_LINUX_IMMUTABLE.Value(): CAP_LINUX_IMMUTABLE, - CAP_NET_BIND_SERVICE.Value(): CAP_NET_BIND_SERVICE, - CAP_NET_BROADCAST.Value(): CAP_NET_BROADCAST, - CAP_NET_ADMIN.Value(): CAP_NET_ADMIN, - CAP_NET_RAW.Value(): CAP_NET_RAW, - CAP_IPC_LOCK.Value(): CAP_IPC_LOCK, - CAP_IPC_OWNER.Value(): CAP_IPC_OWNER, - CAP_SYS_MODULE.Value(): CAP_SYS_MODULE, - CAP_SYS_RAWIO.Value(): CAP_SYS_RAWIO, - CAP_SYS_CHROOT.Value(): CAP_SYS_CHROOT, - CAP_SYS_PTRACE.Value(): CAP_SYS_PTRACE, - CAP_SYS_PACCT.Value(): CAP_SYS_PACCT, - CAP_SYS_ADMIN.Value(): CAP_SYS_ADMIN, - CAP_SYS_BOOT.Value(): CAP_SYS_BOOT, - CAP_SYS_NICE.Value(): CAP_SYS_NICE, - CAP_SYS_RESOURCE.Value(): CAP_SYS_RESOURCE, - CAP_SYS_TIME.Value(): CAP_SYS_TIME, - CAP_SYS_TTY_CONFIG.Value(): CAP_SYS_TTY_CONFIG, - CAP_MKNOD.Value(): CAP_MKNOD, - CAP_LEASE.Value(): CAP_LEASE, - CAP_AUDIT_WRITE.Value(): CAP_AUDIT_WRITE, - CAP_AUDIT_CONTROL.Value(): CAP_AUDIT_CONTROL, - CAP_SETFCAP.Value(): CAP_SETFCAP, - CAP_MAC_OVERRIDE.Value(): CAP_MAC_OVERRIDE, - CAP_MAC_ADMIN.Value(): CAP_MAC_ADMIN, - CAP_SYSLOG.Value(): CAP_SYSLOG, - CAP_WAKE_ALARM.Value(): CAP_WAKE_ALARM, - CAP_BLOCK_SUSPEND.Value(): CAP_BLOCK_SUSPEND, - CAP_AUDIT_READ.Value(): CAP_AUDIT_READ, +var execveAtFlagsValues = []SystemFunctionArgument{ + AT_SYMLINK_NOFOLLOW, + AT_EMPTY_PATH, } -// ParseCapability parses the `capability` bitmask argument of the -// `cap_capable` function -func ParseCapability(rawValue uint64) (CapabilityFlagArgument, error) { - v, ok := capabilitiesMap[rawValue] - if !ok { - return 0, fmt.Errorf("not a valid capability value: %d", rawValue) +// ParseExecveatFlag parses the `flags` bitmask argument of the `execveat` syscall. +// http://man7.org/linux/man-pages/man2/execveat.2.html +func ParseExecveatFlag(flags uint64) (string, error) { + if flags == 0 { + return "", nil } - return v, nil -} -type PrctlOptionArgument uint64 + var sb strings.Builder -const ( - PR_SET_PDEATHSIG PrctlOptionArgument = iota + 1 - PR_GET_PDEATHSIG - PR_GET_DUMPABLE - PR_SET_DUMPABLE - PR_GET_UNALIGN - PR_SET_UNALIGN - PR_GET_KEEPCAPS - PR_SET_KEEPCAPS - PR_GET_FPEMU - PR_SET_FPEMU - PR_GET_FPEXC - PR_SET_FPEXC - PR_GET_TIMING - PR_SET_TIMING - PR_SET_NAME - PR_GET_NAME - PR_GET_ENDIAN - PR_SET_ENDIAN - PR_GET_SECCOMP - PR_SET_SECCOMP - PR_CAPBSET_READ - PR_CAPBSET_DROP - PR_GET_TSC - PR_SET_TSC - PR_GET_SECUREBITS - PR_SET_SECUREBITS - PR_SET_TIMERSLACK - PR_GET_TIMERSLACK - PR_TASK_PERF_EVENTS_DISABLE - PR_TASK_PERF_EVENTS_ENABLE - PR_MCE_KILL - PR_MCE_KILL_GET - PR_SET_MM - PR_SET_CHILD_SUBREAPER - PR_GET_CHILD_SUBREAPER - PR_SET_NO_NEW_PRIVS - PR_GET_NO_NEW_PRIVS - PR_GET_TID_ADDRESS - PR_SET_THP_DISABLE - PR_GET_THP_DISABLE - PR_MPX_ENABLE_MANAGEMENT - PR_MPX_DISABLE_MANAGEMENT - PR_SET_FP_MODE - PR_GET_FP_MODE - PR_CAP_AMBIENT - PR_SVE_SET_VL - PR_SVE_GET_VL - PR_GET_SPECULATION_CTRL - PR_SET_SPECULATION_CTRL - PR_PAC_RESET_KEYS - PR_SET_TAGGED_ADDR_CTRL - PR_GET_TAGGED_ADDR_CTRL -) + buildStringFromValues(&sb, execveAtFlagsValues, flags) -func (p PrctlOptionArgument) Value() uint64 { return uint64(p) } - -var prctlOptionStringMap = map[PrctlOptionArgument]string{ - PR_SET_PDEATHSIG: "PR_SET_PDEATHSIG", - PR_GET_PDEATHSIG: "PR_GET_PDEATHSIG", - PR_GET_DUMPABLE: "PR_GET_DUMPABLE", - PR_SET_DUMPABLE: "PR_SET_DUMPABLE", - PR_GET_UNALIGN: "PR_GET_UNALIGN", - PR_SET_UNALIGN: "PR_SET_UNALIGN", - PR_GET_KEEPCAPS: "PR_GET_KEEPCAPS", - PR_SET_KEEPCAPS: "PR_SET_KEEPCAPS", - PR_GET_FPEMU: "PR_GET_FPEMU", - PR_SET_FPEMU: "PR_SET_FPEMU", - PR_GET_FPEXC: "PR_GET_FPEXC", - PR_SET_FPEXC: "PR_SET_FPEXC", - PR_GET_TIMING: "PR_GET_TIMING", - PR_SET_TIMING: "PR_SET_TIMING", - PR_SET_NAME: "PR_SET_NAME", - PR_GET_NAME: "PR_GET_NAME", - PR_GET_ENDIAN: "PR_GET_ENDIAN", - PR_SET_ENDIAN: "PR_SET_ENDIAN", - PR_GET_SECCOMP: "PR_GET_SECCOMP", - PR_SET_SECCOMP: "PR_SET_SECCOMP", - PR_CAPBSET_READ: "PR_CAPBSET_READ", - PR_CAPBSET_DROP: "PR_CAPBSET_DROP", - PR_GET_TSC: "PR_GET_TSC", - PR_SET_TSC: "PR_SET_TSC", - PR_GET_SECUREBITS: "PR_GET_SECUREBITS", - PR_SET_SECUREBITS: "PR_SET_SECUREBITS", - PR_SET_TIMERSLACK: "PR_SET_TIMERSLACK", - PR_GET_TIMERSLACK: "PR_GET_TIMERSLACK", - PR_TASK_PERF_EVENTS_DISABLE: "PR_TASK_PERF_EVENTS_DISABLE", - PR_TASK_PERF_EVENTS_ENABLE: "PR_TASK_PERF_EVENTS_ENABLE", - PR_MCE_KILL: "PR_MCE_KILL", - PR_MCE_KILL_GET: "PR_MCE_KILL_GET", - PR_SET_MM: "PR_SET_MM", - PR_SET_CHILD_SUBREAPER: "PR_SET_CHILD_SUBREAPER", - PR_GET_CHILD_SUBREAPER: "PR_GET_CHILD_SUBREAPER", - PR_SET_NO_NEW_PRIVS: "PR_SET_NO_NEW_PRIVS", - PR_GET_NO_NEW_PRIVS: "PR_GET_NO_NEW_PRIVS", - PR_GET_TID_ADDRESS: "PR_GET_TID_ADDRESS", - PR_SET_THP_DISABLE: "PR_SET_THP_DISABLE", - PR_GET_THP_DISABLE: "PR_GET_THP_DISABLE", - PR_MPX_ENABLE_MANAGEMENT: "PR_MPX_ENABLE_MANAGEMENT", - PR_MPX_DISABLE_MANAGEMENT: "PR_MPX_DISABLE_MANAGEMENT", - PR_SET_FP_MODE: "PR_SET_FP_MODE", - PR_GET_FP_MODE: "PR_GET_FP_MODE", - PR_CAP_AMBIENT: "PR_CAP_AMBIENT", - PR_SVE_SET_VL: "PR_SVE_SET_VL", - PR_SVE_GET_VL: "PR_SVE_GET_VL", - PR_GET_SPECULATION_CTRL: "PR_GET_SPECULATION_CTRL", - PR_SET_SPECULATION_CTRL: "PR_SET_SPECULATION_CTRL", - PR_PAC_RESET_KEYS: "PR_PAC_RESET_KEYS", - PR_SET_TAGGED_ADDR_CTRL: "PR_SET_TAGGED_ADDR_CTRL", - PR_GET_TAGGED_ADDR_CTRL: "PR_GET_TAGGED_ADDR_CTRL", -} - -func (p PrctlOptionArgument) String() string { - var res string - if opName, ok := prctlOptionStringMap[p]; ok { - res = opName - } else { - res = strconv.Itoa(int(p)) + if sb.Len() == 0 { + return "", fmt.Errorf("no valid execveat flag values present in flags value: 0x%x", flags) } - return res + return sb.String(), nil } -var prctlOptionsMap = map[uint64]PrctlOptionArgument{ - PR_SET_PDEATHSIG.Value(): PR_SET_PDEATHSIG, - PR_GET_PDEATHSIG.Value(): PR_GET_PDEATHSIG, - PR_GET_DUMPABLE.Value(): PR_GET_DUMPABLE, - PR_SET_DUMPABLE.Value(): PR_SET_DUMPABLE, - PR_GET_UNALIGN.Value(): PR_GET_UNALIGN, - PR_SET_UNALIGN.Value(): PR_SET_UNALIGN, - PR_GET_KEEPCAPS.Value(): PR_GET_KEEPCAPS, - PR_SET_KEEPCAPS.Value(): PR_SET_KEEPCAPS, - PR_GET_FPEMU.Value(): PR_GET_FPEMU, - PR_SET_FPEMU.Value(): PR_SET_FPEMU, - PR_GET_FPEXC.Value(): PR_GET_FPEXC, - PR_SET_FPEXC.Value(): PR_SET_FPEXC, - PR_GET_TIMING.Value(): PR_GET_TIMING, - PR_SET_TIMING.Value(): PR_SET_TIMING, - PR_SET_NAME.Value(): PR_SET_NAME, - PR_GET_NAME.Value(): PR_GET_NAME, - PR_GET_ENDIAN.Value(): PR_GET_ENDIAN, - PR_SET_ENDIAN.Value(): PR_SET_ENDIAN, - PR_GET_SECCOMP.Value(): PR_GET_SECCOMP, - PR_SET_SECCOMP.Value(): PR_SET_SECCOMP, - PR_CAPBSET_READ.Value(): PR_CAPBSET_READ, - PR_CAPBSET_DROP.Value(): PR_CAPBSET_DROP, - PR_GET_TSC.Value(): PR_GET_TSC, - PR_SET_TSC.Value(): PR_SET_TSC, - PR_GET_SECUREBITS.Value(): PR_GET_SECUREBITS, - PR_SET_SECUREBITS.Value(): PR_SET_SECUREBITS, - PR_SET_TIMERSLACK.Value(): PR_SET_TIMERSLACK, - PR_GET_TIMERSLACK.Value(): PR_GET_TIMERSLACK, - PR_TASK_PERF_EVENTS_DISABLE.Value(): PR_TASK_PERF_EVENTS_DISABLE, - PR_TASK_PERF_EVENTS_ENABLE.Value(): PR_TASK_PERF_EVENTS_ENABLE, - PR_MCE_KILL.Value(): PR_MCE_KILL, - PR_MCE_KILL_GET.Value(): PR_MCE_KILL_GET, - PR_SET_MM.Value(): PR_SET_MM, - PR_SET_CHILD_SUBREAPER.Value(): PR_SET_CHILD_SUBREAPER, - PR_GET_CHILD_SUBREAPER.Value(): PR_GET_CHILD_SUBREAPER, - PR_SET_NO_NEW_PRIVS.Value(): PR_SET_NO_NEW_PRIVS, - PR_GET_NO_NEW_PRIVS.Value(): PR_GET_NO_NEW_PRIVS, - PR_GET_TID_ADDRESS.Value(): PR_GET_TID_ADDRESS, - PR_SET_THP_DISABLE.Value(): PR_SET_THP_DISABLE, - PR_GET_THP_DISABLE.Value(): PR_GET_THP_DISABLE, - PR_MPX_ENABLE_MANAGEMENT.Value(): PR_MPX_ENABLE_MANAGEMENT, - PR_MPX_DISABLE_MANAGEMENT.Value(): PR_MPX_DISABLE_MANAGEMENT, - PR_SET_FP_MODE.Value(): PR_SET_FP_MODE, - PR_GET_FP_MODE.Value(): PR_GET_FP_MODE, - PR_CAP_AMBIENT.Value(): PR_CAP_AMBIENT, - PR_SVE_SET_VL.Value(): PR_SVE_SET_VL, - PR_SVE_GET_VL.Value(): PR_SVE_GET_VL, - PR_GET_SPECULATION_CTRL.Value(): PR_GET_SPECULATION_CTRL, - PR_SET_SPECULATION_CTRL.Value(): PR_SET_SPECULATION_CTRL, - PR_PAC_RESET_KEYS.Value(): PR_PAC_RESET_KEYS, - PR_SET_TAGGED_ADDR_CTRL.Value(): PR_SET_TAGGED_ADDR_CTRL, - PR_GET_TAGGED_ADDR_CTRL.Value(): PR_GET_TAGGED_ADDR_CTRL, -} +var ( + // from linux/capability.h + // sequential values starting from 0 + CAP_CHOWN = SystemFunctionArgument{rawValue: C.CAP_CHOWN, stringValue: "CAP_CHOWN"} + CAP_DAC_OVERRIDE = SystemFunctionArgument{rawValue: C.CAP_DAC_OVERRIDE, stringValue: "CAP_DAC_OVERRIDE"} + CAP_DAC_READ_SEARCH = SystemFunctionArgument{rawValue: C.CAP_DAC_READ_SEARCH, stringValue: "CAP_DAC_READ_SEARCH"} + CAP_FOWNER = SystemFunctionArgument{rawValue: C.CAP_FOWNER, stringValue: "CAP_FOWNER"} + CAP_FSETID = SystemFunctionArgument{rawValue: C.CAP_FSETID, stringValue: "CAP_FSETID"} + CAP_KILL = SystemFunctionArgument{rawValue: C.CAP_KILL, stringValue: "CAP_KILL"} + CAP_SETGID = SystemFunctionArgument{rawValue: C.CAP_SETGID, stringValue: "CAP_SETGID"} + CAP_SETUID = SystemFunctionArgument{rawValue: C.CAP_SETUID, stringValue: "CAP_SETUID"} + CAP_SETPCAP = SystemFunctionArgument{rawValue: C.CAP_SETPCAP, stringValue: "CAP_SETPCAP"} + CAP_LINUX_IMMUTABLE = SystemFunctionArgument{rawValue: C.CAP_LINUX_IMMUTABLE, stringValue: "CAP_LINUX_IMMUTABLE"} + CAP_NET_BIND_SERVICE = SystemFunctionArgument{rawValue: C.CAP_NET_BIND_SERVICE, stringValue: "CAP_NET_BIND_SERVICE"} + CAP_NET_BROADCAST = SystemFunctionArgument{rawValue: C.CAP_NET_BROADCAST, stringValue: "CAP_NET_BROADCAST"} + CAP_NET_ADMIN = SystemFunctionArgument{rawValue: C.CAP_NET_ADMIN, stringValue: "CAP_NET_ADMIN"} + CAP_NET_RAW = SystemFunctionArgument{rawValue: C.CAP_NET_RAW, stringValue: "CAP_NET_RAW"} + CAP_IPC_LOCK = SystemFunctionArgument{rawValue: C.CAP_IPC_LOCK, stringValue: "CAP_IPC_LOCK"} + CAP_IPC_OWNER = SystemFunctionArgument{rawValue: C.CAP_IPC_OWNER, stringValue: "CAP_IPC_OWNER"} + CAP_SYS_MODULE = SystemFunctionArgument{rawValue: C.CAP_SYS_MODULE, stringValue: "CAP_SYS_MODULE"} + CAP_SYS_RAWIO = SystemFunctionArgument{rawValue: C.CAP_SYS_RAWIO, stringValue: "CAP_SYS_RAWIO"} + CAP_SYS_CHROOT = SystemFunctionArgument{rawValue: C.CAP_SYS_CHROOT, stringValue: "CAP_SYS_CHROOT"} + CAP_SYS_PTRACE = SystemFunctionArgument{rawValue: C.CAP_SYS_PTRACE, stringValue: "CAP_SYS_PTRACE"} + CAP_SYS_PACCT = SystemFunctionArgument{rawValue: C.CAP_SYS_PACCT, stringValue: "CAP_SYS_PACCT"} + CAP_SYS_ADMIN = SystemFunctionArgument{rawValue: C.CAP_SYS_ADMIN, stringValue: "CAP_SYS_ADMIN"} + CAP_SYS_BOOT = SystemFunctionArgument{rawValue: C.CAP_SYS_BOOT, stringValue: "CAP_SYS_BOOT"} + CAP_SYS_NICE = SystemFunctionArgument{rawValue: C.CAP_SYS_NICE, stringValue: "CAP_SYS_NICE"} + CAP_SYS_RESOURCE = SystemFunctionArgument{rawValue: C.CAP_SYS_RESOURCE, stringValue: "CAP_SYS_RESOURCE"} + CAP_SYS_TIME = SystemFunctionArgument{rawValue: C.CAP_SYS_TIME, stringValue: "CAP_SYS_TIME"} + CAP_SYS_TTY_CONFIG = SystemFunctionArgument{rawValue: C.CAP_SYS_TTY_CONFIG, stringValue: "CAP_SYS_TTY_CONFIG"} + CAP_MKNOD = SystemFunctionArgument{rawValue: C.CAP_MKNOD, stringValue: "CAP_MKNOD"} + CAP_LEASE = SystemFunctionArgument{rawValue: C.CAP_LEASE, stringValue: "CAP_LEASE"} + CAP_AUDIT_WRITE = SystemFunctionArgument{rawValue: C.CAP_AUDIT_WRITE, stringValue: "CAP_AUDIT_WRITE"} + CAP_AUDIT_CONTROL = SystemFunctionArgument{rawValue: C.CAP_AUDIT_CONTROL, stringValue: "CAP_AUDIT_CONTROL"} + CAP_SETFCAP = SystemFunctionArgument{rawValue: C.CAP_SETFCAP, stringValue: "CAP_SETFCAP"} + CAP_MAC_OVERRIDE = SystemFunctionArgument{rawValue: C.CAP_MAC_OVERRIDE, stringValue: "CAP_MAC_OVERRIDE"} + CAP_MAC_ADMIN = SystemFunctionArgument{rawValue: C.CAP_MAC_ADMIN, stringValue: "CAP_MAC_ADMIN"} + CAP_SYSLOG = SystemFunctionArgument{rawValue: C.CAP_SYSLOG, stringValue: "CAP_SYSLOG"} + CAP_WAKE_ALARM = SystemFunctionArgument{rawValue: C.CAP_WAKE_ALARM, stringValue: "CAP_WAKE_ALARM"} + CAP_BLOCK_SUSPEND = SystemFunctionArgument{rawValue: C.CAP_BLOCK_SUSPEND, stringValue: "CAP_BLOCK_SUSPEND"} + CAP_AUDIT_READ = SystemFunctionArgument{rawValue: C.CAP_AUDIT_READ, stringValue: "CAP_AUDIT_READ"} + + // not available in all kernels versions, so set directly + CAP_PERFMON = SystemFunctionArgument{rawValue: 38, stringValue: "CAP_PERFMON"} + CAP_BPF = SystemFunctionArgument{rawValue: 39, stringValue: "CAP_BPF"} + CAP_CHECKPOINT_RESTORE = SystemFunctionArgument{rawValue: 40, stringValue: "CAP_CHECKPOINT_RESTORE"} +) -// ParsePrctlOption parses the `option` argument of the `prctl` syscall -// http://man7.org/linux/man-pages/man2/prctl.2.html -func ParsePrctlOption(rawValue uint64) (PrctlOptionArgument, error) { - v, ok := prctlOptionsMap[rawValue] - if !ok { - return 0, fmt.Errorf("not a valid prctl option value: %d", rawValue) - } - return v, nil +var capabilityValues = []SystemFunctionArgument{ + CAP_CHOWN, + CAP_DAC_OVERRIDE, + CAP_DAC_READ_SEARCH, + CAP_FOWNER, + CAP_FSETID, + CAP_KILL, + CAP_SETGID, + CAP_SETUID, + CAP_SETPCAP, + CAP_LINUX_IMMUTABLE, + CAP_NET_BIND_SERVICE, + CAP_NET_BROADCAST, + CAP_NET_ADMIN, + CAP_NET_RAW, + CAP_IPC_LOCK, + CAP_IPC_OWNER, + CAP_SYS_MODULE, + CAP_SYS_RAWIO, + CAP_SYS_CHROOT, + CAP_SYS_PTRACE, + CAP_SYS_PACCT, + CAP_SYS_ADMIN, + CAP_SYS_BOOT, + CAP_SYS_NICE, + CAP_SYS_RESOURCE, + CAP_SYS_TIME, + CAP_SYS_TTY_CONFIG, + CAP_MKNOD, + CAP_LEASE, + CAP_AUDIT_WRITE, + CAP_AUDIT_CONTROL, + CAP_SETFCAP, + CAP_MAC_OVERRIDE, + CAP_MAC_ADMIN, + CAP_SYSLOG, + CAP_WAKE_ALARM, + CAP_BLOCK_SUSPEND, + CAP_AUDIT_READ, + CAP_PERFMON, + CAP_BPF, + CAP_CHECKPOINT_RESTORE, } -type BPFCommandArgument uint64 - -const ( - BPF_MAP_CREATE BPFCommandArgument = iota - BPF_MAP_LOOKUP_ELEM - BPF_MAP_UPDATE_ELEM - BPF_MAP_DELETE_ELEM - BPF_MAP_GET_NEXT_KEY - BPF_PROG_LOAD - BPF_OBJ_PIN - BPF_OBJ_GET - BPF_PROG_ATTACH - BPF_PROG_DETACH - BPF_PROG_TEST_RUN - BPF_PROG_GET_NEXT_ID - BPF_MAP_GET_NEXT_ID - BPF_PROG_GET_FD_BY_ID - BPF_MAP_GET_FD_BY_ID - BPF_OBJ_GET_INFO_BY_FD - BPF_PROG_QUERY - BPF_RAW_TRACEPOINT_OPEN - BPF_BTF_LOAD - BPF_BTF_GET_FD_BY_ID - BPF_TASK_FD_QUERY - BPF_MAP_LOOKUP_AND_DELETE_ELEM - BPF_MAP_FREEZE - BPF_BTF_GET_NEXT_ID - BPF_MAP_LOOKUP_BATCH - BPF_MAP_LOOKUP_AND_DELETE_BATCH - BPF_MAP_UPDATE_BATCH - BPF_MAP_DELETE_BATCH - BPF_LINK_CREATE - BPF_LINK_UPDATE - BPF_LINK_GET_FD_BY_ID - BPF_LINK_GET_NEXT_ID - BPF_ENABLE_STATS - BPF_ITER_CREATE - BPF_LINK_DETACH +var ( + CAP_FIRST_CAP = CAP_CHOWN.Value() + CAP_LAST_CAP = CAP_CHECKPOINT_RESTORE.Value() ) -func (b BPFCommandArgument) Value() uint64 { return uint64(b) } - -var bpfCmdStringMap = map[BPFCommandArgument]string{ - BPF_MAP_CREATE: "BPF_MAP_CREATE", - BPF_MAP_LOOKUP_ELEM: "BPF_MAP_LOOKUP_ELEM", - BPF_MAP_UPDATE_ELEM: "BPF_MAP_UPDATE_ELEM", - BPF_MAP_DELETE_ELEM: "BPF_MAP_DELETE_ELEM", - BPF_MAP_GET_NEXT_KEY: "BPF_MAP_GET_NEXT_KEY", - BPF_PROG_LOAD: "BPF_PROG_LOAD", - BPF_OBJ_PIN: "BPF_OBJ_PIN", - BPF_OBJ_GET: "BPF_OBJ_GET", - BPF_PROG_ATTACH: "BPF_PROG_ATTACH", - BPF_PROG_DETACH: "BPF_PROG_DETACH", - BPF_PROG_TEST_RUN: "BPF_PROG_TEST_RUN", - BPF_PROG_GET_NEXT_ID: "BPF_PROG_GET_NEXT_ID", - BPF_MAP_GET_NEXT_ID: "BPF_MAP_GET_NEXT_ID", - BPF_PROG_GET_FD_BY_ID: "BPF_PROG_GET_FD_BY_ID", - BPF_MAP_GET_FD_BY_ID: "BPF_MAP_GET_FD_BY_ID", - BPF_OBJ_GET_INFO_BY_FD: "BPF_OBJ_GET_INFO_BY_FD", - BPF_PROG_QUERY: "BPF_PROG_QUERY", - BPF_RAW_TRACEPOINT_OPEN: "BPF_RAW_TRACEPOINT_OPEN", - BPF_BTF_LOAD: "BPF_BTF_LOAD", - BPF_BTF_GET_FD_BY_ID: "BPF_BTF_GET_FD_BY_ID", - BPF_TASK_FD_QUERY: "BPF_TASK_FD_QUERY", - BPF_MAP_LOOKUP_AND_DELETE_ELEM: "BPF_MAP_LOOKUP_AND_DELETE_ELEM", - BPF_MAP_FREEZE: "BPF_MAP_FREEZE", - BPF_BTF_GET_NEXT_ID: "BPF_BTF_GET_NEXT_ID", - BPF_MAP_LOOKUP_BATCH: "BPF_MAP_LOOKUP_BATCH", - BPF_MAP_LOOKUP_AND_DELETE_BATCH: "BPF_MAP_LOOKUP_AND_DELETE_BATCH", - BPF_MAP_UPDATE_BATCH: "BPF_MAP_UPDATE_BATCH", - BPF_MAP_DELETE_BATCH: "BPF_MAP_DELETE_BATCH", - BPF_LINK_CREATE: "BPF_LINK_CREATE", - BPF_LINK_UPDATE: "BPF_LINK_UPDATE", - BPF_LINK_GET_FD_BY_ID: "BPF_LINK_GET_FD_BY_ID", - BPF_LINK_GET_NEXT_ID: "BPF_LINK_GET_NEXT_ID", - BPF_ENABLE_STATS: "BPF_ENABLE_STATS", - BPF_ITER_CREATE: "BPF_ITER_CREATE", - BPF_LINK_DETACH: "BPF_LINK_DETACH", -} - -// String parses the `cmd` argument of the `bpf` syscall -// https://man7.org/linux/man-pages/man2/bpf.2.html -func (b BPFCommandArgument) String() string { - var res string - if cmdName, ok := bpfCmdStringMap[b]; ok { - res = cmdName - } else { - res = strconv.Itoa(int(b)) +// ParseCapability parses the `capability` bitmask argument of the +// `cap_capable` function +func ParseCapability(cap uint64) (string, error) { + if cap > CAP_LAST_CAP { + return "", fmt.Errorf("not a valid capability value: %d", cap) } - return res + idx := int(cap - CAP_FIRST_CAP) + return capabilityValues[idx].String(), nil } -var bpfCmdMap = map[uint64]BPFCommandArgument{ - BPF_MAP_CREATE.Value(): BPF_MAP_CREATE, - BPF_MAP_LOOKUP_ELEM.Value(): BPF_MAP_LOOKUP_ELEM, - BPF_MAP_UPDATE_ELEM.Value(): BPF_MAP_UPDATE_ELEM, - BPF_MAP_DELETE_ELEM.Value(): BPF_MAP_DELETE_ELEM, - BPF_MAP_GET_NEXT_KEY.Value(): BPF_MAP_GET_NEXT_KEY, - BPF_PROG_LOAD.Value(): BPF_PROG_LOAD, - BPF_OBJ_PIN.Value(): BPF_OBJ_PIN, - BPF_OBJ_GET.Value(): BPF_OBJ_GET, - BPF_PROG_ATTACH.Value(): BPF_PROG_ATTACH, - BPF_PROG_DETACH.Value(): BPF_PROG_DETACH, - BPF_PROG_TEST_RUN.Value(): BPF_PROG_TEST_RUN, - BPF_PROG_GET_NEXT_ID.Value(): BPF_PROG_GET_NEXT_ID, - BPF_MAP_GET_NEXT_ID.Value(): BPF_MAP_GET_NEXT_ID, - BPF_PROG_GET_FD_BY_ID.Value(): BPF_PROG_GET_FD_BY_ID, - BPF_MAP_GET_FD_BY_ID.Value(): BPF_MAP_GET_FD_BY_ID, - BPF_OBJ_GET_INFO_BY_FD.Value(): BPF_OBJ_GET_INFO_BY_FD, - BPF_PROG_QUERY.Value(): BPF_PROG_QUERY, - BPF_RAW_TRACEPOINT_OPEN.Value(): BPF_RAW_TRACEPOINT_OPEN, - BPF_BTF_LOAD.Value(): BPF_BTF_LOAD, - BPF_BTF_GET_FD_BY_ID.Value(): BPF_BTF_GET_FD_BY_ID, - BPF_TASK_FD_QUERY.Value(): BPF_TASK_FD_QUERY, - BPF_MAP_LOOKUP_AND_DELETE_ELEM.Value(): BPF_MAP_LOOKUP_AND_DELETE_ELEM, - BPF_MAP_FREEZE.Value(): BPF_MAP_FREEZE, - BPF_BTF_GET_NEXT_ID.Value(): BPF_BTF_GET_NEXT_ID, - BPF_MAP_LOOKUP_BATCH.Value(): BPF_MAP_LOOKUP_BATCH, - BPF_MAP_LOOKUP_AND_DELETE_BATCH.Value(): BPF_MAP_LOOKUP_AND_DELETE_BATCH, - BPF_MAP_UPDATE_BATCH.Value(): BPF_MAP_UPDATE_BATCH, - BPF_MAP_DELETE_BATCH.Value(): BPF_MAP_DELETE_BATCH, - BPF_LINK_CREATE.Value(): BPF_LINK_CREATE, - BPF_LINK_UPDATE.Value(): BPF_LINK_UPDATE, - BPF_LINK_GET_FD_BY_ID.Value(): BPF_LINK_GET_FD_BY_ID, - BPF_LINK_GET_NEXT_ID.Value(): BPF_LINK_GET_NEXT_ID, - BPF_ENABLE_STATS.Value(): BPF_ENABLE_STATS, - BPF_ITER_CREATE.Value(): BPF_ITER_CREATE, - BPF_LINK_DETACH.Value(): BPF_LINK_DETACH, +var ( + // from linux/prctl.h + // NOT sequential values + PR_SET_PDEATHSIG = SystemFunctionArgument{rawValue: C.PR_SET_PDEATHSIG, stringValue: "PR_SET_PDEATHSIG"} + PR_GET_PDEATHSIG = SystemFunctionArgument{rawValue: C.PR_GET_PDEATHSIG, stringValue: "PR_GET_PDEATHSIG"} + PR_GET_DUMPABLE = SystemFunctionArgument{rawValue: C.PR_GET_DUMPABLE, stringValue: "PR_GET_DUMPABLE"} + PR_SET_DUMPABLE = SystemFunctionArgument{rawValue: C.PR_SET_DUMPABLE, stringValue: "PR_SET_DUMPABLE"} + PR_GET_UNALIGN = SystemFunctionArgument{rawValue: C.PR_GET_UNALIGN, stringValue: "PR_GET_UNALIGN"} + PR_SET_UNALIGN = SystemFunctionArgument{rawValue: C.PR_SET_UNALIGN, stringValue: "PR_SET_UNALIGN"} + PR_GET_KEEPCAPS = SystemFunctionArgument{rawValue: C.PR_GET_KEEPCAPS, stringValue: "PR_GET_KEEPCAPS"} + PR_SET_KEEPCAPS = SystemFunctionArgument{rawValue: C.PR_SET_KEEPCAPS, stringValue: "PR_SET_KEEPCAPS"} + PR_GET_FPEMU = SystemFunctionArgument{rawValue: C.PR_GET_FPEMU, stringValue: "PR_GET_FPEMU"} + PR_SET_FPEMU = SystemFunctionArgument{rawValue: C.PR_SET_FPEMU, stringValue: "PR_SET_FPEMU"} + PR_GET_FPEXC = SystemFunctionArgument{rawValue: C.PR_GET_FPEXC, stringValue: "PR_GET_FPEXC"} + PR_SET_FPEXC = SystemFunctionArgument{rawValue: C.PR_SET_FPEXC, stringValue: "PR_SET_FPEXC"} + PR_GET_TIMING = SystemFunctionArgument{rawValue: C.PR_GET_TIMING, stringValue: "PR_GET_TIMING"} + PR_SET_TIMING = SystemFunctionArgument{rawValue: C.PR_SET_TIMING, stringValue: "PR_SET_TIMING"} + PR_SET_NAME = SystemFunctionArgument{rawValue: C.PR_SET_NAME, stringValue: "PR_SET_NAME"} + PR_GET_NAME = SystemFunctionArgument{rawValue: C.PR_GET_NAME, stringValue: "PR_GET_NAME"} + PR_GET_ENDIAN = SystemFunctionArgument{rawValue: C.PR_GET_ENDIAN, stringValue: "PR_GET_ENDIAN"} + PR_SET_ENDIAN = SystemFunctionArgument{rawValue: C.PR_SET_ENDIAN, stringValue: "PR_SET_ENDIAN"} + PR_GET_SECCOMP = SystemFunctionArgument{rawValue: C.PR_GET_SECCOMP, stringValue: "PR_GET_SECCOMP"} + PR_SET_SECCOMP = SystemFunctionArgument{rawValue: C.PR_SET_SECCOMP, stringValue: "PR_SET_SECCOMP"} + PR_CAPBSET_READ = SystemFunctionArgument{rawValue: C.PR_CAPBSET_READ, stringValue: "PR_CAPBSET_READ"} + PR_CAPBSET_DROP = SystemFunctionArgument{rawValue: C.PR_CAPBSET_DROP, stringValue: "PR_CAPBSET_DROP"} + PR_GET_TSC = SystemFunctionArgument{rawValue: C.PR_GET_TSC, stringValue: "PR_GET_TSC"} + PR_SET_TSC = SystemFunctionArgument{rawValue: C.PR_SET_TSC, stringValue: "PR_SET_TSC"} + PR_GET_SECUREBITS = SystemFunctionArgument{rawValue: C.PR_GET_SECUREBITS, stringValue: "PR_GET_SECUREBITS"} + PR_SET_SECUREBITS = SystemFunctionArgument{rawValue: C.PR_SET_SECUREBITS, stringValue: "PR_SET_SECUREBITS"} + PR_SET_TIMERSLACK = SystemFunctionArgument{rawValue: C.PR_SET_TIMERSLACK, stringValue: "PR_SET_TIMERSLACK"} + PR_GET_TIMERSLACK = SystemFunctionArgument{rawValue: C.PR_GET_TIMERSLACK, stringValue: "PR_GET_TIMERSLACK"} + PR_TASK_PERF_EVENTS_DISABLE = SystemFunctionArgument{rawValue: C.PR_TASK_PERF_EVENTS_DISABLE, stringValue: "PR_TASK_PERF_EVENTS_DISABLE"} + PR_TASK_PERF_EVENTS_ENABLE = SystemFunctionArgument{rawValue: C.PR_TASK_PERF_EVENTS_ENABLE, stringValue: "PR_TASK_PERF_EVENTS_ENABLE"} + PR_MCE_KILL = SystemFunctionArgument{rawValue: C.PR_MCE_KILL, stringValue: "PR_MCE_KILL"} + PR_MCE_KILL_GET = SystemFunctionArgument{rawValue: C.PR_MCE_KILL_GET, stringValue: "PR_MCE_KILL_GET"} + PR_SET_MM = SystemFunctionArgument{rawValue: C.PR_SET_MM, stringValue: "PR_SET_MM"} + PR_SET_PTRACER = SystemFunctionArgument{rawValue: C.PR_SET_PTRACER, stringValue: "PR_SET_PTRACER"} + PR_SET_CHILD_SUBREAPER = SystemFunctionArgument{rawValue: C.PR_SET_CHILD_SUBREAPER, stringValue: "PR_SET_CHILD_SUBREAPER"} + PR_GET_CHILD_SUBREAPER = SystemFunctionArgument{rawValue: C.PR_GET_CHILD_SUBREAPER, stringValue: "PR_GET_CHILD_SUBREAPER"} + PR_SET_NO_NEW_PRIVS = SystemFunctionArgument{rawValue: C.PR_SET_NO_NEW_PRIVS, stringValue: "PR_SET_NO_NEW_PRIVS"} + PR_GET_NO_NEW_PRIVS = SystemFunctionArgument{rawValue: C.PR_GET_NO_NEW_PRIVS, stringValue: "PR_GET_NO_NEW_PRIVS"} + PR_GET_TID_ADDRESS = SystemFunctionArgument{rawValue: C.PR_GET_TID_ADDRESS, stringValue: "PR_GET_TID_ADDRESS"} + PR_SET_THP_DISABLE = SystemFunctionArgument{rawValue: C.PR_SET_THP_DISABLE, stringValue: "PR_SET_THP_DISABLE"} + PR_GET_THP_DISABLE = SystemFunctionArgument{rawValue: C.PR_GET_THP_DISABLE, stringValue: "PR_GET_THP_DISABLE"} + PR_MPX_ENABLE_MANAGEMENT = SystemFunctionArgument{rawValue: C.PR_MPX_ENABLE_MANAGEMENT, stringValue: "PR_MPX_ENABLE_MANAGEMENT"} + PR_MPX_DISABLE_MANAGEMENT = SystemFunctionArgument{rawValue: C.PR_MPX_DISABLE_MANAGEMENT, stringValue: "PR_MPX_DISABLE_MANAGEMENT"} + PR_SET_FP_MODE = SystemFunctionArgument{rawValue: C.PR_SET_FP_MODE, stringValue: "PR_SET_FP_MODE"} + PR_GET_FP_MODE = SystemFunctionArgument{rawValue: C.PR_GET_FP_MODE, stringValue: "PR_GET_FP_MODE"} + PR_CAP_AMBIENT = SystemFunctionArgument{rawValue: C.PR_CAP_AMBIENT, stringValue: "PR_CAP_AMBIENT"} + PR_SVE_SET_VL = SystemFunctionArgument{rawValue: C.PR_SVE_SET_VL, stringValue: "PR_SVE_SET_VL"} + PR_SVE_GET_VL = SystemFunctionArgument{rawValue: C.PR_SVE_GET_VL, stringValue: "PR_SVE_GET_VL"} + PR_GET_SPECULATION_CTRL = SystemFunctionArgument{rawValue: C.PR_GET_SPECULATION_CTRL, stringValue: "PR_GET_SPECULATION_CTRL"} + PR_SET_SPECULATION_CTRL = SystemFunctionArgument{rawValue: C.PR_SET_SPECULATION_CTRL, stringValue: "PR_SET_SPECULATION_CTRL"} + PR_PAC_RESET_KEYS = SystemFunctionArgument{rawValue: C.PR_PAC_RESET_KEYS, stringValue: "PR_PAC_RESET_KEYS"} + + // not available in all kernels (arch or version), so set directly + PR_SET_TAGGED_ADDR_CTRL = SystemFunctionArgument{rawValue: 55, stringValue: "PR_SET_TAGGED_ADDR_CTRL"} + PR_GET_TAGGED_ADDR_CTRL = SystemFunctionArgument{rawValue: 56, stringValue: "PR_GET_TAGGED_ADDR_CTRL"} + PR_SET_IO_FLUSHER = SystemFunctionArgument{rawValue: 57, stringValue: "PR_SET_IO_FLUSHER"} + PR_GET_IO_FLUSHER = SystemFunctionArgument{rawValue: 58, stringValue: "PR_GET_IO_FLUSHER"} + PR_SET_SYSCALL_USER_DISPATCH = SystemFunctionArgument{rawValue: 59, stringValue: "PR_SET_SYSCALL_USER_DISPATCH"} + PR_PAC_SET_ENABLED_KEYS = SystemFunctionArgument{rawValue: 60, stringValue: "PR_PAC_SET_ENABLED_KEYS"} + PR_PAC_GET_ENABLED_KEYS = SystemFunctionArgument{rawValue: 61, stringValue: "PR_PAC_GET_ENABLED_KEYS"} + PR_SCHED_CORE = SystemFunctionArgument{rawValue: 62, stringValue: "PR_SCHED_CORE"} + PR_SME_SET_VL = SystemFunctionArgument{rawValue: 63, stringValue: "PR_SME_SET_VL"} + PR_SME_GET_VL = SystemFunctionArgument{rawValue: 64, stringValue: "PR_SME_GET_VL"} + PR_SET_MDWE = SystemFunctionArgument{rawValue: 65, stringValue: "PR_SET_MDWE"} + PR_GET_MDWE = SystemFunctionArgument{rawValue: 66, stringValue: "PR_GET_MDWE"} + PR_SET_MEMORY_MERGE = SystemFunctionArgument{rawValue: 67, stringValue: "PR_SET_MEMORY_MERGE"} + PR_GET_MEMORY_MERGE = SystemFunctionArgument{rawValue: 68, stringValue: "PR_GET_MEMORY_MERGE"} + + // architecure specific (not supported) + // PR_RISCV_V_SET_CONTROL + // PR_RISCV_V_GET_CONTROL + // PR_RISCV_SET_ICACHE_FLUSH_CTX + // PR_PPC_GET_DEXCR + // PR_PPC_SET_DEXCR +) + +var prctlOptionValues = []SystemFunctionArgument{ + PR_SET_PDEATHSIG, + PR_GET_PDEATHSIG, + PR_GET_DUMPABLE, + PR_SET_DUMPABLE, + PR_GET_UNALIGN, + PR_SET_UNALIGN, + PR_GET_KEEPCAPS, + PR_SET_KEEPCAPS, + PR_GET_FPEMU, + PR_SET_FPEMU, + PR_GET_FPEXC, + PR_SET_FPEXC, + PR_GET_TIMING, + PR_SET_TIMING, + PR_SET_NAME, + PR_GET_NAME, + PR_GET_ENDIAN, + PR_SET_ENDIAN, + PR_GET_SECCOMP, + PR_SET_SECCOMP, + PR_CAPBSET_READ, + PR_CAPBSET_DROP, + PR_GET_TSC, + PR_SET_TSC, + PR_GET_SECUREBITS, + PR_SET_SECUREBITS, + PR_SET_TIMERSLACK, + PR_GET_TIMERSLACK, + PR_TASK_PERF_EVENTS_DISABLE, + PR_TASK_PERF_EVENTS_ENABLE, + PR_MCE_KILL, + PR_MCE_KILL_GET, + PR_SET_MM, + PR_SET_CHILD_SUBREAPER, + PR_GET_CHILD_SUBREAPER, + PR_SET_NO_NEW_PRIVS, + PR_GET_NO_NEW_PRIVS, + PR_GET_TID_ADDRESS, + PR_SET_THP_DISABLE, + PR_GET_THP_DISABLE, + PR_MPX_ENABLE_MANAGEMENT, + PR_MPX_DISABLE_MANAGEMENT, + PR_SET_FP_MODE, + PR_GET_FP_MODE, + PR_CAP_AMBIENT, + PR_SVE_SET_VL, + PR_SVE_GET_VL, + PR_GET_SPECULATION_CTRL, + PR_SET_SPECULATION_CTRL, + PR_PAC_RESET_KEYS, + PR_SET_TAGGED_ADDR_CTRL, + PR_GET_TAGGED_ADDR_CTRL, + PR_SET_IO_FLUSHER, + PR_GET_IO_FLUSHER, + PR_SET_SYSCALL_USER_DISPATCH, + PR_PAC_SET_ENABLED_KEYS, + PR_PAC_GET_ENABLED_KEYS, + PR_SCHED_CORE, + PR_SME_SET_VL, + PR_SME_GET_VL, + PR_SET_MDWE, + PR_GET_MDWE, + PR_SET_MEMORY_MERGE, + PR_GET_MEMORY_MERGE, } -// ParseBPFCmd parses the raw value of the `cmd` argument of the `bpf` syscall -// https://man7.org/linux/man-pages/man2/bpf.2.html -func ParseBPFCmd(cmd uint64) (BPFCommandArgument, error) { - v, ok := bpfCmdMap[cmd] - if !ok { - return 0, fmt.Errorf("not a valid BPF command argument: %d", cmd) +// ParsePrctlOption parses the `option` argument of the `prctl` syscall +// http://man7.org/linux/man-pages/man2/prctl.2.html +func ParsePrctlOption(option uint64) (string, error) { + for idx := range prctlOptionValues { + if option == prctlOptionValues[idx].Value() { + return prctlOptionValues[idx].String(), nil + } } - return v, nil + + return "", fmt.Errorf("not a valid prctl option value: %d", option) } -type PtraceRequestArgument uint64 +var ( + // from linux/bpf.h + // sequential values starting from 0 + BPF_MAP_CREATE = SystemFunctionArgument{rawValue: C.BPF_MAP_CREATE, stringValue: "BPF_MAP_CREATE"} + BPF_MAP_LOOKUP_ELEM = SystemFunctionArgument{rawValue: C.BPF_MAP_LOOKUP_ELEM, stringValue: "BPF_MAP_LOOKUP_ELEM"} + BPF_MAP_UPDATE_ELEM = SystemFunctionArgument{rawValue: C.BPF_MAP_UPDATE_ELEM, stringValue: "BPF_MAP_UPDATE_ELEM"} + BPF_MAP_DELETE_ELEM = SystemFunctionArgument{rawValue: C.BPF_MAP_DELETE_ELEM, stringValue: "BPF_MAP_DELETE_ELEM"} + BPF_MAP_GET_NEXT_KEY = SystemFunctionArgument{rawValue: C.BPF_MAP_GET_NEXT_KEY, stringValue: "BPF_MAP_GET_NEXT_KEY"} + BPF_PROG_LOAD = SystemFunctionArgument{rawValue: C.BPF_PROG_LOAD, stringValue: "BPF_PROG_LOAD"} + BPF_OBJ_PIN = SystemFunctionArgument{rawValue: C.BPF_OBJ_PIN, stringValue: "BPF_OBJ_PIN"} + BPF_OBJ_GET = SystemFunctionArgument{rawValue: C.BPF_OBJ_GET, stringValue: "BPF_OBJ_GET"} + BPF_PROG_ATTACH = SystemFunctionArgument{rawValue: C.BPF_PROG_ATTACH, stringValue: "BPF_PROG_ATTACH"} + BPF_PROG_DETACH = SystemFunctionArgument{rawValue: C.BPF_PROG_DETACH, stringValue: "BPF_PROG_DETACH"} + BPF_PROG_TEST_RUN = SystemFunctionArgument{rawValue: C.BPF_PROG_TEST_RUN, stringValue: "BPF_PROG_TEST_RUN"} + BPF_PROG_GET_NEXT_ID = SystemFunctionArgument{rawValue: C.BPF_PROG_GET_NEXT_ID, stringValue: "BPF_PROG_GET_NEXT_ID"} + BPF_MAP_GET_NEXT_ID = SystemFunctionArgument{rawValue: C.BPF_MAP_GET_NEXT_ID, stringValue: "BPF_MAP_GET_NEXT_ID"} + BPF_PROG_GET_FD_BY_ID = SystemFunctionArgument{rawValue: C.BPF_PROG_GET_FD_BY_ID, stringValue: "BPF_PROG_GET_FD_BY_ID"} + BPF_MAP_GET_FD_BY_ID = SystemFunctionArgument{rawValue: C.BPF_MAP_GET_FD_BY_ID, stringValue: "BPF_MAP_GET_FD_BY_ID"} + BPF_OBJ_GET_INFO_BY_FD = SystemFunctionArgument{rawValue: C.BPF_OBJ_GET_INFO_BY_FD, stringValue: "BPF_OBJ_GET_INFO_BY_FD"} + BPF_PROG_QUERY = SystemFunctionArgument{rawValue: C.BPF_PROG_QUERY, stringValue: "BPF_PROG_QUERY"} + BPF_RAW_TRACEPOINT_OPEN = SystemFunctionArgument{rawValue: C.BPF_RAW_TRACEPOINT_OPEN, stringValue: "BPF_RAW_TRACEPOINT_OPEN"} + BPF_BTF_LOAD = SystemFunctionArgument{rawValue: C.BPF_BTF_LOAD, stringValue: "BPF_BTF_LOAD"} + BPF_BTF_GET_FD_BY_ID = SystemFunctionArgument{rawValue: C.BPF_BTF_GET_FD_BY_ID, stringValue: "BPF_BTF_GET_FD_BY_ID"} + BPF_TASK_FD_QUERY = SystemFunctionArgument{rawValue: C.BPF_TASK_FD_QUERY, stringValue: "BPF_TASK_FD_QUERY"} + BPF_MAP_LOOKUP_AND_DELETE_ELEM = SystemFunctionArgument{rawValue: C.BPF_MAP_LOOKUP_AND_DELETE_ELEM, stringValue: "BPF_MAP_LOOKUP_AND_DELETE_ELEM"} + BPF_MAP_FREEZE = SystemFunctionArgument{rawValue: C.BPF_MAP_FREEZE, stringValue: "BPF_MAP_FREEZE"} + BPF_BTF_GET_NEXT_ID = SystemFunctionArgument{rawValue: C.BPF_BTF_GET_NEXT_ID, stringValue: "BPF_BTF_GET_NEXT_ID"} + BPF_MAP_LOOKUP_BATCH = SystemFunctionArgument{rawValue: C.BPF_MAP_LOOKUP_BATCH, stringValue: "BPF_MAP_LOOKUP_BATCH"} + BPF_MAP_LOOKUP_AND_DELETE_BATCH = SystemFunctionArgument{rawValue: C.BPF_MAP_LOOKUP_AND_DELETE_BATCH, stringValue: "BPF_MAP_LOOKUP_AND_DELETE_BATCH"} + BPF_MAP_UPDATE_BATCH = SystemFunctionArgument{rawValue: C.BPF_MAP_UPDATE_BATCH, stringValue: "BPF_MAP_UPDATE_BATCH"} + BPF_MAP_DELETE_BATCH = SystemFunctionArgument{rawValue: C.BPF_MAP_DELETE_BATCH, stringValue: "BPF_MAP_DELETE_BATCH"} + BPF_LINK_CREATE = SystemFunctionArgument{rawValue: C.BPF_LINK_CREATE, stringValue: "BPF_LINK_CREATE"} + BPF_LINK_UPDATE = SystemFunctionArgument{rawValue: C.BPF_LINK_UPDATE, stringValue: "BPF_LINK_UPDATE"} + BPF_LINK_GET_FD_BY_ID = SystemFunctionArgument{rawValue: C.BPF_LINK_GET_FD_BY_ID, stringValue: "BPF_LINK_GET_FD_BY_ID"} + BPF_LINK_GET_NEXT_ID = SystemFunctionArgument{rawValue: C.BPF_LINK_GET_NEXT_ID, stringValue: "BPF_LINK_GET_NEXT_ID"} + BPF_ENABLE_STATS = SystemFunctionArgument{rawValue: C.BPF_ENABLE_STATS, stringValue: "BPF_ENABLE_STATS"} + BPF_ITER_CREATE = SystemFunctionArgument{rawValue: C.BPF_ITER_CREATE, stringValue: "BPF_ITER_CREATE"} + BPF_LINK_DETACH = SystemFunctionArgument{rawValue: C.BPF_LINK_DETACH, stringValue: "BPF_LINK_DETACH"} + BPF_PROG_BIND_MAP = SystemFunctionArgument{rawValue: C.BPF_PROG_BIND_MAP, stringValue: "BPF_PROG_BIND_MAP"} + + // not available in all kernels, so set directly + BPF_TOKEN_CREATE = SystemFunctionArgument{rawValue: 36, stringValue: "BPF_TOKEN_CREATE"} +) -// revive:disable +var bpfCmdValues = []SystemFunctionArgument{ + BPF_MAP_CREATE, + BPF_MAP_LOOKUP_ELEM, + BPF_MAP_UPDATE_ELEM, + BPF_MAP_DELETE_ELEM, + BPF_MAP_GET_NEXT_KEY, + BPF_PROG_LOAD, + BPF_OBJ_PIN, + BPF_OBJ_GET, + BPF_PROG_ATTACH, + BPF_PROG_DETACH, + BPF_PROG_TEST_RUN, + BPF_PROG_GET_NEXT_ID, + BPF_MAP_GET_NEXT_ID, + BPF_PROG_GET_FD_BY_ID, + BPF_MAP_GET_FD_BY_ID, + BPF_OBJ_GET_INFO_BY_FD, + BPF_PROG_QUERY, + BPF_RAW_TRACEPOINT_OPEN, + BPF_BTF_LOAD, + BPF_BTF_GET_FD_BY_ID, + BPF_TASK_FD_QUERY, + BPF_MAP_LOOKUP_AND_DELETE_ELEM, + BPF_MAP_FREEZE, + BPF_BTF_GET_NEXT_ID, + BPF_MAP_LOOKUP_BATCH, + BPF_MAP_LOOKUP_AND_DELETE_BATCH, + BPF_MAP_UPDATE_BATCH, + BPF_MAP_DELETE_BATCH, + BPF_LINK_CREATE, + BPF_LINK_UPDATE, + BPF_LINK_GET_FD_BY_ID, + BPF_LINK_GET_NEXT_ID, + BPF_ENABLE_STATS, + BPF_ITER_CREATE, + BPF_LINK_DETACH, + BPF_PROG_BIND_MAP, + BPF_TOKEN_CREATE, +} var ( - PTRACE_TRACEME PtraceRequestArgument = 0 - PTRACE_PEEKTEXT PtraceRequestArgument = 1 - PTRACE_PEEKDATA PtraceRequestArgument = 2 - PTRACE_PEEKUSER PtraceRequestArgument = 3 - PTRACE_POKETEXT PtraceRequestArgument = 4 - PTRACE_POKEDATA PtraceRequestArgument = 5 - PTRACE_POKEUSER PtraceRequestArgument = 6 - PTRACE_CONT PtraceRequestArgument = 7 - PTRACE_KILL PtraceRequestArgument = 8 - PTRACE_SINGLESTEP PtraceRequestArgument = 9 - PTRACE_GETREGS PtraceRequestArgument = 12 - PTRACE_SETREGS PtraceRequestArgument = 13 - PTRACE_GETFPREGS PtraceRequestArgument = 14 - PTRACE_SETFPREGS PtraceRequestArgument = 15 - PTRACE_ATTACH PtraceRequestArgument = 16 - PTRACE_DETACH PtraceRequestArgument = 17 - PTRACE_GETFPXREGS PtraceRequestArgument = 18 - PTRACE_SETFPXREGS PtraceRequestArgument = 19 - PTRACE_SYSCALL PtraceRequestArgument = 24 - PTRACE_SETOPTIONS PtraceRequestArgument = 0x4200 - PTRACE_GETEVENTMSG PtraceRequestArgument = 0x4201 - PTRACE_GETSIGINFO PtraceRequestArgument = 0x4202 - PTRACE_SETSIGINFO PtraceRequestArgument = 0x4203 - PTRACE_GETREGSET PtraceRequestArgument = 0x4204 - PTRACE_SETREGSET PtraceRequestArgument = 0x4205 - PTRACE_SEIZE PtraceRequestArgument = 0x4206 - PTRACE_INTERRUPT PtraceRequestArgument = 0x4207 - PTRACE_LISTEN PtraceRequestArgument = 0x4208 - PTRACE_PEEKSIGINFO PtraceRequestArgument = 0x4209 - PTRACE_GETSIGMASK PtraceRequestArgument = 0x420a - PTRACE_SETSIGMASK PtraceRequestArgument = 0x420b - PTRACE_SECCOMP_GET_FILTER PtraceRequestArgument = 0x420c - PTRACE_SECCOMP_GET_METADATA PtraceRequestArgument = 0x420d - PTRACE_GET_SYSCALL_INFO PtraceRequestArgument = 0x420e + BPF_FIRST_BPF = BPF_MAP_CREATE.Value() + BPF_LAST_BPF = BPF_TOKEN_CREATE.Value() ) -// revive:enable - -func (p PtraceRequestArgument) Value() uint64 { return uint64(p) } - -var ptraceRequestStringMap = map[PtraceRequestArgument]string{ - PTRACE_TRACEME: "PTRACE_TRACEME", - PTRACE_PEEKTEXT: "PTRACE_PEEKTEXT", - PTRACE_PEEKDATA: "PTRACE_PEEKDATA", - PTRACE_PEEKUSER: "PTRACE_PEEKUSER", - PTRACE_POKETEXT: "PTRACE_POKETEXT", - PTRACE_POKEDATA: "PTRACE_POKEDATA", - PTRACE_POKEUSER: "PTRACE_POKEUSER", - PTRACE_CONT: "PTRACE_CONT", - PTRACE_KILL: "PTRACE_KILL", - PTRACE_SINGLESTEP: "PTRACE_SINGLESTEP", - PTRACE_GETREGS: "PTRACE_GETREGS", - PTRACE_SETREGS: "PTRACE_SETREGS", - PTRACE_GETFPREGS: "PTRACE_GETFPREGS", - PTRACE_SETFPREGS: "PTRACE_SETFPREGS", - PTRACE_ATTACH: "PTRACE_ATTACH", - PTRACE_DETACH: "PTRACE_DETACH", - PTRACE_GETFPXREGS: "PTRACE_GETFPXREGS", - PTRACE_SETFPXREGS: "PTRACE_SETFPXREGS", - PTRACE_SYSCALL: "PTRACE_SYSCALL", - PTRACE_SETOPTIONS: "PTRACE_SETOPTIONS", - PTRACE_GETEVENTMSG: "PTRACE_GETEVENTMSG", - PTRACE_GETSIGINFO: "PTRACE_GETSIGINFO", - PTRACE_SETSIGINFO: "PTRACE_SETSIGINFO", - PTRACE_GETREGSET: "PTRACE_GETREGSET", - PTRACE_SETREGSET: "PTRACE_SETREGSET", - PTRACE_SEIZE: "PTRACE_SEIZE", - PTRACE_INTERRUPT: "PTRACE_INTERRUPT", - PTRACE_LISTEN: "PTRACE_LISTEN", - PTRACE_PEEKSIGINFO: "PTRACE_PEEKSIGINFO", - PTRACE_GETSIGMASK: "PTRACE_GETSIGMASK", - PTRACE_SETSIGMASK: "PTRACE_SETSIGMASK", - PTRACE_SECCOMP_GET_FILTER: "PTRACE_SECCOMP_GET_FILTER", - PTRACE_SECCOMP_GET_METADATA: "PTRACE_SECCOMP_GET_METADATA", - PTRACE_GET_SYSCALL_INFO: "PTRACE_GET_SYSCALL_INFO", -} - -func (p PtraceRequestArgument) String() string { - var res string - if reqName, ok := ptraceRequestStringMap[p]; ok { - res = reqName - } else { - res = strconv.Itoa(int(p)) +// ParseBPFCmd parses the raw value of the `cmd` argument of the `bpf` syscall +// https://man7.org/linux/man-pages/man2/bpf.2.html +func ParseBPFCmd(cmd uint64) (string, error) { + if cmd > BPF_LAST_BPF { + return "", fmt.Errorf("not a valid bpf command value: %d", cmd) } - return res + idx := int(cmd - BPF_FIRST_BPF) + return bpfCmdValues[idx].String(), nil } -var ptraceRequestArgMap = map[uint64]PtraceRequestArgument{ - PTRACE_TRACEME.Value(): PTRACE_TRACEME, - PTRACE_PEEKTEXT.Value(): PTRACE_PEEKTEXT, - PTRACE_PEEKDATA.Value(): PTRACE_PEEKDATA, - PTRACE_PEEKUSER.Value(): PTRACE_PEEKUSER, - PTRACE_POKETEXT.Value(): PTRACE_POKETEXT, - PTRACE_POKEDATA.Value(): PTRACE_POKEDATA, - PTRACE_POKEUSER.Value(): PTRACE_POKEUSER, - PTRACE_CONT.Value(): PTRACE_CONT, - PTRACE_KILL.Value(): PTRACE_KILL, - PTRACE_SINGLESTEP.Value(): PTRACE_SINGLESTEP, - PTRACE_GETREGS.Value(): PTRACE_GETREGS, - PTRACE_SETREGS.Value(): PTRACE_SETREGS, - PTRACE_GETFPREGS.Value(): PTRACE_GETFPREGS, - PTRACE_SETFPREGS.Value(): PTRACE_SETFPREGS, - PTRACE_ATTACH.Value(): PTRACE_ATTACH, - PTRACE_DETACH.Value(): PTRACE_DETACH, - PTRACE_GETFPXREGS.Value(): PTRACE_GETFPXREGS, - PTRACE_SETFPXREGS.Value(): PTRACE_SETFPXREGS, - PTRACE_SYSCALL.Value(): PTRACE_SYSCALL, - PTRACE_SETOPTIONS.Value(): PTRACE_SETOPTIONS, - PTRACE_GETEVENTMSG.Value(): PTRACE_GETEVENTMSG, - PTRACE_GETSIGINFO.Value(): PTRACE_GETSIGINFO, - PTRACE_SETSIGINFO.Value(): PTRACE_SETSIGINFO, - PTRACE_GETREGSET.Value(): PTRACE_GETREGSET, - PTRACE_SETREGSET.Value(): PTRACE_SETREGSET, - PTRACE_SEIZE.Value(): PTRACE_SEIZE, - PTRACE_INTERRUPT.Value(): PTRACE_INTERRUPT, - PTRACE_LISTEN.Value(): PTRACE_LISTEN, - PTRACE_PEEKSIGINFO.Value(): PTRACE_PEEKSIGINFO, - PTRACE_GETSIGMASK.Value(): PTRACE_GETSIGMASK, - PTRACE_SETSIGMASK.Value(): PTRACE_SETSIGMASK, - PTRACE_SECCOMP_GET_FILTER.Value(): PTRACE_SECCOMP_GET_FILTER, - PTRACE_SECCOMP_GET_METADATA.Value(): PTRACE_SECCOMP_GET_METADATA, - PTRACE_GET_SYSCALL_INFO.Value(): PTRACE_GET_SYSCALL_INFO, -} - -func ParsePtraceRequestArgument(rawValue uint64) (PtraceRequestArgument, error) { - if reqName, ok := ptraceRequestArgMap[rawValue]; ok { - return reqName, nil - } - return 0, fmt.Errorf("not a valid ptrace request value: %d", rawValue) -} - -type SocketcallCallArgument uint64 - -const ( - SYS_SOCKET SocketcallCallArgument = iota + 1 - SYS_BIND - SYS_CONNECT - SYS_LISTEN - SYS_ACCEPT - SYS_GETSOCKNAME - SYS_GETPEERNAME - SYS_SOCKETPAIR - SYS_SEND - SYS_RECV - SYS_SENDTO - SYS_RECVFROM - SYS_SHUTDOWN - SYS_SETSOCKOPT - SYS_GETSOCKOPT - SYS_SENDMSG - SYS_RECVMSG - SYS_ACCEPT4 - SYS_RECVMMSG - SYS_SENDMMSG +var ( + // from linux/ptrace.h and sys/ptrace.h + // NOT sequential values + PTRACE_TRACEME = SystemFunctionArgument{rawValue: C.PTRACE_TRACEME, stringValue: "PTRACE_TRACEME"} + PTRACE_PEEKTEXT = SystemFunctionArgument{rawValue: C.PTRACE_PEEKTEXT, stringValue: "PTRACE_PEEKTEXT"} + PTRACE_PEEKDATA = SystemFunctionArgument{rawValue: C.PTRACE_PEEKDATA, stringValue: "PTRACE_PEEKDATA"} + PTRACE_PEEKUSR = SystemFunctionArgument{rawValue: C.PTRACE_PEEKUSR, stringValue: "PTRACE_PEEKUSER"} + PTRACE_POKETEXT = SystemFunctionArgument{rawValue: C.PTRACE_POKETEXT, stringValue: "PTRACE_POKETEXT"} + PTRACE_POKEDATA = SystemFunctionArgument{rawValue: C.PTRACE_POKEDATA, stringValue: "PTRACE_POKEDATA"} + PTRACE_POKEUSR = SystemFunctionArgument{rawValue: C.PTRACE_POKEUSR, stringValue: "PTRACE_POKEUSER"} + PTRACE_CONT = SystemFunctionArgument{rawValue: C.PTRACE_CONT, stringValue: "PTRACE_CONT"} + PTRACE_KILL = SystemFunctionArgument{rawValue: C.PTRACE_KILL, stringValue: "PTRACE_KILL"} + PTRACE_SINGLESTEP = SystemFunctionArgument{rawValue: C.PTRACE_SINGLESTEP, stringValue: "PTRACE_SINGLESTEP"} + + // not available in all architectures, so set directly + PTRACE_GETREGS = SystemFunctionArgument{rawValue: 12, stringValue: "PTRACE_GETREGS"} + PTRACE_SETREGS = SystemFunctionArgument{rawValue: 13, stringValue: "PTRACE_SETREGS"} + PTRACE_GETFPREGS = SystemFunctionArgument{rawValue: 14, stringValue: "PTRACE_GETFPREGS"} + PTRACE_SETFPREGS = SystemFunctionArgument{rawValue: 15, stringValue: "PTRACE_SETFPREGS"} + + PTRACE_ATTACH = SystemFunctionArgument{rawValue: C.PTRACE_ATTACH, stringValue: "PTRACE_ATTACH"} + PTRACE_DETACH = SystemFunctionArgument{rawValue: C.PTRACE_DETACH, stringValue: "PTRACE_DETACH"} + + // not available in all architectures, so set directly + PTRACE_GETFPXREGS = SystemFunctionArgument{rawValue: 18, stringValue: "PTRACE_GETFPXREGS"} + PTRACE_SETFPXREGS = SystemFunctionArgument{rawValue: 19, stringValue: "PTRACE_SETFPXREGS"} + + PTRACE_SYSCALL = SystemFunctionArgument{rawValue: C.PTRACE_SYSCALL, stringValue: "PTRACE_SYSCALL"} + + // not available in all architectures, so set directly + PTRACE_GET_THREAD_AREA = SystemFunctionArgument{rawValue: 25, stringValue: "PTRACE_GET_THREAD_AREA"} + PTRACE_SET_THREAD_AREA = SystemFunctionArgument{rawValue: 26, stringValue: "PTRACE_SET_THREAD_AREA"} + + // x86_64 specific, so set directly + PTRACE_ARCH_PRCTL = SystemFunctionArgument{rawValue: 30, stringValue: "PTRACE_ARCH_PRCTL"} + + PTRACE_SYSEMU = SystemFunctionArgument{rawValue: C.PTRACE_SYSEMU, stringValue: "PTRACE_SYSEMU"} + PTRACE_SYSEMU_SINGLESTEP = SystemFunctionArgument{rawValue: C.PTRACE_SYSEMU_SINGLESTEP, stringValue: "PTRACE_SYSEMU_SINGLESTEP"} + + // not available in all architectures, so set directly + PTRACE_SINGLEBLOCK = SystemFunctionArgument{rawValue: 33, stringValue: "PTRACE_SINGLEBLOCK"} + + // architecture-independent + PTRACE_SETOPTIONS = SystemFunctionArgument{rawValue: C.PTRACE_SETOPTIONS, stringValue: "PTRACE_SETOPTIONS"} + PTRACE_GETEVENTMSG = SystemFunctionArgument{rawValue: C.PTRACE_GETEVENTMSG, stringValue: "PTRACE_GETEVENTMSG"} + PTRACE_GETSIGINFO = SystemFunctionArgument{rawValue: C.PTRACE_GETSIGINFO, stringValue: "PTRACE_GETSIGINFO"} + PTRACE_SETSIGINFO = SystemFunctionArgument{rawValue: C.PTRACE_SETSIGINFO, stringValue: "PTRACE_SETSIGINFO"} + PTRACE_GETREGSET = SystemFunctionArgument{rawValue: C.PTRACE_GETREGSET, stringValue: "PTRACE_GETREGSET"} + PTRACE_SETREGSET = SystemFunctionArgument{rawValue: C.PTRACE_SETREGSET, stringValue: "PTRACE_SETREGSET"} + PTRACE_SEIZE = SystemFunctionArgument{rawValue: C.PTRACE_SEIZE, stringValue: "PTRACE_SEIZE"} + PTRACE_INTERRUPT = SystemFunctionArgument{rawValue: C.PTRACE_INTERRUPT, stringValue: "PTRACE_INTERRUPT"} + PTRACE_LISTEN = SystemFunctionArgument{rawValue: C.PTRACE_LISTEN, stringValue: "PTRACE_LISTEN"} + PTRACE_PEEKSIGINFO = SystemFunctionArgument{rawValue: C.PTRACE_PEEKSIGINFO, stringValue: "PTRACE_PEEKSIGINFO"} + PTRACE_GETSIGMASK = SystemFunctionArgument{rawValue: C.PTRACE_GETSIGMASK, stringValue: "PTRACE_GETSIGMASK"} + PTRACE_SETSIGMASK = SystemFunctionArgument{rawValue: C.PTRACE_SETSIGMASK, stringValue: "PTRACE_SETSIGMASK"} + PTRACE_SECCOMP_GET_FILTER = SystemFunctionArgument{rawValue: C.PTRACE_SECCOMP_GET_FILTER, stringValue: "PTRACE_SECCOMP_GET_FILTER"} + PTRACE_SECCOMP_GET_METADATA = SystemFunctionArgument{rawValue: C.PTRACE_SECCOMP_GET_METADATA, stringValue: "PTRACE_SECCOMP_GET_METADATA"} + // not available in all kernel versions, so set directly + PTRACE_GET_SYSCALL_INFO = SystemFunctionArgument{rawValue: 0x420e, stringValue: "PTRACE_GET_SYSCALL_INFO"} + PTRACE_GET_RSEQ_CONFIGURATION = SystemFunctionArgument{rawValue: 0x420f, stringValue: "PTRACE_GET_RSEQ_CONFIGURATION"} + PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG = SystemFunctionArgument{rawValue: 0x4210, stringValue: "PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG"} + PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG = SystemFunctionArgument{rawValue: 0x4211, stringValue: "PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG"} ) -func (s SocketcallCallArgument) Value() uint64 { - return uint64(s) -} - -var socketcallCallStringMap = map[SocketcallCallArgument]string{ - SYS_SOCKET: "SYS_SOCKET", - SYS_BIND: "SYS_BIND", - SYS_CONNECT: "SYS_CONNECT", - SYS_LISTEN: "SYS_LISTEN", - SYS_ACCEPT: "SYS_ACCEPT", - SYS_GETSOCKNAME: "SYS_GETSOCKNAME", - SYS_GETPEERNAME: "SYS_GETPEERNAME", - SYS_SOCKETPAIR: "SYS_SOCKETPAIR", - SYS_SEND: "SYS_SEND", - SYS_RECV: "SYS_RECV", - SYS_SENDTO: "SYS_SENDTO", - SYS_RECVFROM: "SYS_RECVFROM", - SYS_SHUTDOWN: "SYS_SHUTDOWN", - SYS_SETSOCKOPT: "SYS_SETSOCKOPT", - SYS_GETSOCKOPT: "SYS_GETSOCKOPT", - SYS_SENDMSG: "SYS_SENDMSG", - SYS_RECVMSG: "SYS_RECVMSG", - SYS_ACCEPT4: "SYS_ACCEPT4", - SYS_RECVMMSG: "SYS_RECVMMSG", - SYS_SENDMMSG: "SYS_SENDMMSG", -} - -func (s SocketcallCallArgument) String() string { - var res string - - if sdName, ok := socketcallCallStringMap[s]; ok { - res = sdName - } else { - res = strconv.Itoa(int(s)) +var ptraceRequestValues = []SystemFunctionArgument{ + PTRACE_TRACEME, + PTRACE_PEEKTEXT, + PTRACE_PEEKDATA, + PTRACE_PEEKUSR, + PTRACE_POKETEXT, + PTRACE_POKEDATA, + PTRACE_POKEUSR, + PTRACE_CONT, + PTRACE_KILL, + PTRACE_SINGLESTEP, + PTRACE_GETREGS, + PTRACE_SETREGS, + PTRACE_GETFPREGS, + PTRACE_SETFPREGS, + PTRACE_ATTACH, + PTRACE_DETACH, + PTRACE_GETFPXREGS, + PTRACE_SETFPXREGS, + PTRACE_SYSCALL, + PTRACE_GET_THREAD_AREA, + PTRACE_SET_THREAD_AREA, + PTRACE_ARCH_PRCTL, + PTRACE_SYSEMU, + PTRACE_SYSEMU_SINGLESTEP, + PTRACE_SINGLEBLOCK, + PTRACE_SETOPTIONS, + PTRACE_GETEVENTMSG, + PTRACE_GETSIGINFO, + PTRACE_SETSIGINFO, + PTRACE_GETREGSET, + PTRACE_SETREGSET, + PTRACE_SEIZE, + PTRACE_INTERRUPT, + PTRACE_LISTEN, + PTRACE_PEEKSIGINFO, + PTRACE_GETSIGMASK, + PTRACE_SETSIGMASK, + PTRACE_SECCOMP_GET_FILTER, + PTRACE_SECCOMP_GET_METADATA, + PTRACE_GET_SYSCALL_INFO, + PTRACE_GET_RSEQ_CONFIGURATION, + PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG, + PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG, +} + +func ParsePtraceRequestArgument(request uint64) (string, error) { + for idx := range ptraceRequestValues { + if ptraceRequestValues[idx].Value() == request { + return ptraceRequestValues[idx].String(), nil + } } - return res + return "", fmt.Errorf("not a valid ptrace request value: %d", request) } -var socketcallCallMap = map[uint64]SocketcallCallArgument{ - SYS_SOCKET.Value(): SYS_SOCKET, - SYS_BIND.Value(): SYS_BIND, - SYS_CONNECT.Value(): SYS_CONNECT, - SYS_LISTEN.Value(): SYS_LISTEN, - SYS_ACCEPT.Value(): SYS_ACCEPT, - SYS_GETSOCKNAME.Value(): SYS_GETSOCKNAME, - SYS_GETPEERNAME.Value(): SYS_GETPEERNAME, - SYS_SOCKETPAIR.Value(): SYS_SOCKETPAIR, - SYS_SEND.Value(): SYS_SEND, - SYS_RECV.Value(): SYS_RECV, - SYS_SENDTO.Value(): SYS_SENDTO, - SYS_RECVFROM.Value(): SYS_RECVFROM, - SYS_SHUTDOWN.Value(): SYS_SHUTDOWN, - SYS_SETSOCKOPT.Value(): SYS_SETSOCKOPT, - SYS_GETSOCKOPT.Value(): SYS_GETSOCKOPT, - SYS_SENDMSG.Value(): SYS_SENDMSG, - SYS_RECVMSG.Value(): SYS_RECVMSG, - SYS_ACCEPT4.Value(): SYS_ACCEPT4, - SYS_RECVMMSG.Value(): SYS_RECVMMSG, - SYS_SENDMMSG.Value(): SYS_SENDMMSG, +var ( + // from linux/net.h + // sequential values starting from 1 + SYS_SOCKET = SystemFunctionArgument{rawValue: C.SYS_SOCKET, stringValue: "SYS_SOCKET"} + SYS_BIND = SystemFunctionArgument{rawValue: C.SYS_BIND, stringValue: "SYS_BIND"} + SYS_CONNECT = SystemFunctionArgument{rawValue: C.SYS_CONNECT, stringValue: "SYS_CONNECT"} + SYS_LISTEN = SystemFunctionArgument{rawValue: C.SYS_LISTEN, stringValue: "SYS_LISTEN"} + SYS_ACCEPT = SystemFunctionArgument{rawValue: C.SYS_ACCEPT, stringValue: "SYS_ACCEPT"} + SYS_GETSOCKNAME = SystemFunctionArgument{rawValue: C.SYS_GETSOCKNAME, stringValue: "SYS_GETSOCKNAME"} + SYS_GETPEERNAME = SystemFunctionArgument{rawValue: C.SYS_GETPEERNAME, stringValue: "SYS_GETPEERNAME"} + SYS_SOCKETPAIR = SystemFunctionArgument{rawValue: C.SYS_SOCKETPAIR, stringValue: "SYS_SOCKETPAIR"} + SYS_SEND = SystemFunctionArgument{rawValue: C.SYS_SEND, stringValue: "SYS_SEND"} + SYS_RECV = SystemFunctionArgument{rawValue: C.SYS_RECV, stringValue: "SYS_RECV"} + SYS_SENDTO = SystemFunctionArgument{rawValue: C.SYS_SENDTO, stringValue: "SYS_SENDTO"} + SYS_RECVFROM = SystemFunctionArgument{rawValue: C.SYS_RECVFROM, stringValue: "SYS_RECVFROM"} + SYS_SHUTDOWN = SystemFunctionArgument{rawValue: C.SYS_SHUTDOWN, stringValue: "SYS_SHUTDOWN"} + SYS_SETSOCKOPT = SystemFunctionArgument{rawValue: C.SYS_SETSOCKOPT, stringValue: "SYS_SETSOCKOPT"} + SYS_GETSOCKOPT = SystemFunctionArgument{rawValue: C.SYS_GETSOCKOPT, stringValue: "SYS_GETSOCKOPT"} + SYS_SENDMSG = SystemFunctionArgument{rawValue: C.SYS_SENDMSG, stringValue: "SYS_SENDMSG"} + SYS_RECVMSG = SystemFunctionArgument{rawValue: C.SYS_RECVMSG, stringValue: "SYS_RECVMSG"} + SYS_ACCEPT4 = SystemFunctionArgument{rawValue: C.SYS_ACCEPT4, stringValue: "SYS_ACCEPT4"} + SYS_RECVMMSG = SystemFunctionArgument{rawValue: C.SYS_RECVMMSG, stringValue: "SYS_RECVMMSG"} + SYS_SENDMMSG = SystemFunctionArgument{rawValue: C.SYS_SENDMMSG, stringValue: "SYS_SENDMMSG"} +) + +var sysNetValues = []SystemFunctionArgument{ + SYS_SOCKET, + SYS_BIND, + SYS_CONNECT, + SYS_LISTEN, + SYS_ACCEPT, + SYS_GETSOCKNAME, + SYS_GETPEERNAME, + SYS_SOCKETPAIR, + SYS_SEND, + SYS_RECV, + SYS_SENDTO, + SYS_RECVFROM, + SYS_SHUTDOWN, + SYS_SETSOCKOPT, + SYS_GETSOCKOPT, + SYS_SENDMSG, + SYS_RECVMSG, + SYS_ACCEPT4, + SYS_RECVMMSG, + SYS_SENDMMSG, } +const ( + SYS_NET_FIRST = C.SYS_SOCKET + SYS_NET_LAST = C.SYS_SENDMMSG +) + // ParseSocketcallCall parses the `call` argument of the `socketcall` syscall // http://man7.org/linux/man-pages/man2/socketcall.2.html // https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/net.h -func ParseSocketcallCall(rawValue uint64) (SocketcallCallArgument, error) { - if v, ok := socketcallCallMap[rawValue]; ok { - return v, nil +func ParseSocketcallCall(call uint64) (string, error) { + if call > SYS_NET_LAST { + return "", fmt.Errorf("not a valid socketcall call value: %d", call) } - return 0, fmt.Errorf("not a valid socketcall call value: %d", rawValue) + idx := int(call - SYS_NET_FIRST) + return sysNetValues[idx].String(), nil } -type SocketDomainArgument uint64 - -const ( - AF_UNSPEC SocketDomainArgument = iota - AF_UNIX - AF_INET - AF_AX25 - AF_IPX - AF_APPLETALK - AF_NETROM - AF_BRIDGE - AF_ATMPVC - AF_X25 - AF_INET6 - AF_ROSE - AF_DECnet - AF_NETBEUI - AF_SECURITY - AF_KEY - AF_NETLINK - AF_PACKET - AF_ASH - AF_ECONET - AF_ATMSVC - AF_RDS - AF_SNA - AF_IRDA - AF_PPPOX - AF_WANPIPE - AF_LLC - AF_IB - AF_MPLS - AF_CAN - AF_TIPC - AF_BLUETOOTH - AF_IUCV - AF_RXRPC - AF_ISDN - AF_PHONET - AF_IEEE802154 - AF_CAIF - AF_ALG - AF_NFC - AF_VSOCK - AF_KCM - AF_QIPCRTR - AF_SMC - AF_XDP +var ( + // from bits/socket.h via sys/socket.h + // sequential values starting from 0 + AF_UNSPEC = SystemFunctionArgument{rawValue: C.AF_UNSPEC, stringValue: "AF_UNSPEC"} + AF_UNIX = SystemFunctionArgument{rawValue: C.AF_UNIX, stringValue: "AF_UNIX"} + AF_INET = SystemFunctionArgument{rawValue: C.AF_INET, stringValue: "AF_INET"} + AF_AX25 = SystemFunctionArgument{rawValue: C.AF_AX25, stringValue: "AF_AX25"} + AF_IPX = SystemFunctionArgument{rawValue: C.AF_IPX, stringValue: "AF_IPX"} + AF_APPLETALK = SystemFunctionArgument{rawValue: C.AF_APPLETALK, stringValue: "AF_APPLETALK"} + AF_NETROM = SystemFunctionArgument{rawValue: C.AF_NETROM, stringValue: "AF_NETROM"} + AF_BRIDGE = SystemFunctionArgument{rawValue: C.AF_BRIDGE, stringValue: "AF_BRIDGE"} + AF_ATMPVC = SystemFunctionArgument{rawValue: C.AF_ATMPVC, stringValue: "AF_ATMPVC"} + AF_X25 = SystemFunctionArgument{rawValue: C.AF_X25, stringValue: "AF_X25"} + AF_INET6 = SystemFunctionArgument{rawValue: C.AF_INET6, stringValue: "AF_INET6"} + AF_ROSE = SystemFunctionArgument{rawValue: C.AF_ROSE, stringValue: "AF_ROSE"} + AF_DECnet = SystemFunctionArgument{rawValue: C.AF_DECnet, stringValue: "AF_DECnet"} + AF_NETBEUI = SystemFunctionArgument{rawValue: C.AF_NETBEUI, stringValue: "AF_NETBEUI"} + AF_SECURITY = SystemFunctionArgument{rawValue: C.AF_SECURITY, stringValue: "AF_SECURITY"} + AF_KEY = SystemFunctionArgument{rawValue: C.AF_KEY, stringValue: "AF_KEY"} + AF_NETLINK = SystemFunctionArgument{rawValue: C.AF_NETLINK, stringValue: "AF_NETLINK"} + AF_PACKET = SystemFunctionArgument{rawValue: C.AF_PACKET, stringValue: "AF_PACKET"} + AF_ASH = SystemFunctionArgument{rawValue: C.AF_ASH, stringValue: "AF_ASH"} + AF_ECONET = SystemFunctionArgument{rawValue: C.AF_ECONET, stringValue: "AF_ECONET"} + AF_ATMSVC = SystemFunctionArgument{rawValue: C.AF_ATMSVC, stringValue: "AF_ATMSVC"} + AF_RDS = SystemFunctionArgument{rawValue: C.AF_RDS, stringValue: "AF_RDS"} + AF_SNA = SystemFunctionArgument{rawValue: C.AF_SNA, stringValue: "AF_SNA"} + AF_IRDA = SystemFunctionArgument{rawValue: C.AF_IRDA, stringValue: "AF_IRDA"} + AF_PPPOX = SystemFunctionArgument{rawValue: C.AF_PPPOX, stringValue: "AF_PPPOX"} + AF_WANPIPE = SystemFunctionArgument{rawValue: C.AF_WANPIPE, stringValue: "AF_WANPIPE"} + AF_LLC = SystemFunctionArgument{rawValue: C.AF_LLC, stringValue: "AF_LLC"} + AF_IB = SystemFunctionArgument{rawValue: C.AF_IB, stringValue: "AF_IB"} + AF_MPLS = SystemFunctionArgument{rawValue: C.AF_MPLS, stringValue: "AF_MPLS"} + AF_CAN = SystemFunctionArgument{rawValue: C.AF_CAN, stringValue: "AF_CAN"} + AF_TIPC = SystemFunctionArgument{rawValue: C.AF_TIPC, stringValue: "AF_TIPC"} + AF_BLUETOOTH = SystemFunctionArgument{rawValue: C.AF_BLUETOOTH, stringValue: "AF_BLUETOOTH"} + AF_IUCV = SystemFunctionArgument{rawValue: C.AF_IUCV, stringValue: "AF_IUCV"} + AF_RXRPC = SystemFunctionArgument{rawValue: C.AF_RXRPC, stringValue: "AF_RXRPC"} + AF_ISDN = SystemFunctionArgument{rawValue: C.AF_ISDN, stringValue: "AF_ISDN"} + AF_PHONET = SystemFunctionArgument{rawValue: C.AF_PHONET, stringValue: "AF_PHONET"} + AF_IEEE802154 = SystemFunctionArgument{rawValue: C.AF_IEEE802154, stringValue: "AF_IEEE802154"} + AF_CAIF = SystemFunctionArgument{rawValue: C.AF_CAIF, stringValue: "AF_CAIF"} + AF_ALG = SystemFunctionArgument{rawValue: C.AF_ALG, stringValue: "AF_ALG"} + AF_NFC = SystemFunctionArgument{rawValue: C.AF_NFC, stringValue: "AF_NFC"} + AF_VSOCK = SystemFunctionArgument{rawValue: C.AF_VSOCK, stringValue: "AF_VSOCK"} + AF_KCM = SystemFunctionArgument{rawValue: C.AF_KCM, stringValue: "AF_KCM"} + AF_QIPCRTR = SystemFunctionArgument{rawValue: C.AF_QIPCRTR, stringValue: "AF_QIPCRTR"} + AF_SMC = SystemFunctionArgument{rawValue: C.AF_SMC, stringValue: "AF_SMC"} + AF_XDP = SystemFunctionArgument{rawValue: C.AF_XDP, stringValue: "AF_XDP"} + + // not available in all kernels, so set directly + AF_MCTP = SystemFunctionArgument{rawValue: 45, stringValue: "AF_MCTP"} ) -func (s SocketDomainArgument) Value() uint64 { return uint64(s) } - -var socketDomainStringMap = map[SocketDomainArgument]string{ - AF_UNSPEC: "AF_UNSPEC", - AF_UNIX: "AF_UNIX", - AF_INET: "AF_INET", - AF_AX25: "AF_AX25", - AF_IPX: "AF_IPX", - AF_APPLETALK: "AF_APPLETALK", - AF_NETROM: "AF_NETROM", - AF_BRIDGE: "AF_BRIDGE", - AF_ATMPVC: "AF_ATMPVC", - AF_X25: "AF_X25", - AF_INET6: "AF_INET6", - AF_ROSE: "AF_ROSE", - AF_DECnet: "AF_DECnet", - AF_NETBEUI: "AF_NETBEUI", - AF_SECURITY: "AF_SECURITY", - AF_KEY: "AF_KEY", - AF_NETLINK: "AF_NETLINK", - AF_PACKET: "AF_PACKET", - AF_ASH: "AF_ASH", - AF_ECONET: "AF_ECONET", - AF_ATMSVC: "AF_ATMSVC", - AF_RDS: "AF_RDS", - AF_SNA: "AF_SNA", - AF_IRDA: "AF_IRDA", - AF_PPPOX: "AF_PPPOX", - AF_WANPIPE: "AF_WANPIPE", - AF_LLC: "AF_LLC", - AF_IB: "AF_IB", - AF_MPLS: "AF_MPLS", - AF_CAN: "AF_CAN", - AF_TIPC: "AF_TIPC", - AF_BLUETOOTH: "AF_BLUETOOTH", - AF_IUCV: "AF_IUCV", - AF_RXRPC: "AF_RXRPC", - AF_ISDN: "AF_ISDN", - AF_PHONET: "AF_PHONET", - AF_IEEE802154: "AF_IEEE802154", - AF_CAIF: "AF_CAIF", - AF_ALG: "AF_ALG", - AF_NFC: "AF_NFC", - AF_VSOCK: "AF_VSOCK", - AF_KCM: "AF_KCM", - AF_QIPCRTR: "AF_QIPCRTR", - AF_SMC: "AF_SMC", - AF_XDP: "AF_XDP", -} - -func (s SocketDomainArgument) String() string { - var res string - - if sdName, ok := socketDomainStringMap[s]; ok { - res = sdName - } else { - res = strconv.Itoa(int(s)) - } - - return res +var socketDomainValues = []SystemFunctionArgument{ + AF_UNSPEC, + AF_UNIX, + AF_INET, + AF_AX25, + AF_IPX, + AF_APPLETALK, + AF_NETROM, + AF_BRIDGE, + AF_ATMPVC, + AF_X25, + AF_INET6, + AF_ROSE, + AF_DECnet, + AF_NETBEUI, + AF_SECURITY, + AF_KEY, + AF_NETLINK, + AF_PACKET, + AF_ASH, + AF_ECONET, + AF_ATMSVC, + AF_RDS, + AF_SNA, + AF_IRDA, + AF_PPPOX, + AF_WANPIPE, + AF_LLC, + AF_IB, + AF_MPLS, + AF_CAN, + AF_TIPC, + AF_BLUETOOTH, + AF_IUCV, + AF_RXRPC, + AF_ISDN, + AF_PHONET, + AF_IEEE802154, + AF_CAIF, + AF_ALG, + AF_NFC, + AF_VSOCK, + AF_KCM, + AF_QIPCRTR, + AF_SMC, + AF_XDP, + AF_MCTP, } -var socketDomainMap = map[uint64]SocketDomainArgument{ - AF_UNSPEC.Value(): AF_UNSPEC, - AF_UNIX.Value(): AF_UNIX, - AF_INET.Value(): AF_INET, - AF_AX25.Value(): AF_AX25, - AF_IPX.Value(): AF_IPX, - AF_APPLETALK.Value(): AF_APPLETALK, - AF_NETROM.Value(): AF_NETROM, - AF_BRIDGE.Value(): AF_BRIDGE, - AF_ATMPVC.Value(): AF_ATMPVC, - AF_X25.Value(): AF_X25, - AF_INET6.Value(): AF_INET6, - AF_ROSE.Value(): AF_ROSE, - AF_DECnet.Value(): AF_DECnet, - AF_NETBEUI.Value(): AF_NETBEUI, - AF_SECURITY.Value(): AF_SECURITY, - AF_KEY.Value(): AF_KEY, - AF_NETLINK.Value(): AF_NETLINK, - AF_PACKET.Value(): AF_PACKET, - AF_ASH.Value(): AF_ASH, - AF_ECONET.Value(): AF_ECONET, - AF_ATMSVC.Value(): AF_ATMSVC, - AF_RDS.Value(): AF_RDS, - AF_SNA.Value(): AF_SNA, - AF_IRDA.Value(): AF_IRDA, - AF_PPPOX.Value(): AF_PPPOX, - AF_WANPIPE.Value(): AF_WANPIPE, - AF_LLC.Value(): AF_LLC, - AF_IB.Value(): AF_IB, - AF_MPLS.Value(): AF_MPLS, - AF_CAN.Value(): AF_CAN, - AF_TIPC.Value(): AF_TIPC, - AF_BLUETOOTH.Value(): AF_BLUETOOTH, - AF_IUCV.Value(): AF_IUCV, - AF_RXRPC.Value(): AF_RXRPC, - AF_ISDN.Value(): AF_ISDN, - AF_PHONET.Value(): AF_PHONET, - AF_IEEE802154.Value(): AF_IEEE802154, - AF_CAIF.Value(): AF_CAIF, - AF_ALG.Value(): AF_ALG, - AF_NFC.Value(): AF_NFC, - AF_VSOCK.Value(): AF_VSOCK, - AF_KCM.Value(): AF_KCM, - AF_QIPCRTR.Value(): AF_QIPCRTR, - AF_SMC.Value(): AF_SMC, - AF_XDP.Value(): AF_XDP, -} +var ( + AF_SOCKET_FIRST = AF_UNSPEC.Value() + AF_SOCKET_LAST = AF_MCTP.Value() +) // ParseSocketDomainArgument parses the `domain` bitmask argument of the `socket` syscall // http://man7.org/linux/man-pages/man2/socket.2.html -func ParseSocketDomainArgument(rawValue uint64) (SocketDomainArgument, error) { - v, ok := socketDomainMap[rawValue] - if !ok { - return 0, fmt.Errorf("not a valid argument: %d", rawValue) +func ParseSocketDomainArgument(domain uint64) (string, error) { + if domain > AF_SOCKET_LAST { + return "", fmt.Errorf("not a valid socket domain value: %d", domain) } - return v, nil + + idx := int(domain - AF_SOCKET_FIRST) + return socketDomainValues[idx].String(), nil } type SocketTypeArgument struct { @@ -3274,7 +3043,7 @@ const gupFlagsChangeVersion = "6.3.0" // ParseGUPFlagsCurrentOS parse the GUP flags received according to current machine OS version. // It uses optimizations to perform better than ParseGUPFlagsForOS -func ParseGUPFlagsCurrentOS(rawValue uint64) (SystemFunctionArgument, error) { +func ParseGUPFlagsCurrentOS(rawValue uint64) (systemFunctionArgument, error) { const ( newVersionsParsing = iota legacyParsing @@ -3313,7 +3082,7 @@ 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) { +func ParseGUPFlagsForOS(osInfo *environment.OSInfo, rawValue uint64) (systemFunctionArgument, error) { compare, err := osInfo.CompareOSBaseKernelRelease(gupFlagsChangeVersion) if err != nil { return nil, fmt.Errorf( diff --git a/pkg/events/parsers/data_parsers_bench_test.go b/pkg/events/parsers/data_parsers_bench_test.go index c3bbe09db8c8..5df807b6f8b5 100644 --- a/pkg/events/parsers/data_parsers_bench_test.go +++ b/pkg/events/parsers/data_parsers_bench_test.go @@ -24,6 +24,43 @@ func BenchmarkParseMmapProt(b *testing.B) { } } +var parseCloneFlagsBenchTestArgs = []struct { + rawArgument uint64 +}{ + { + rawArgument: CLONE_VM.Value(), + }, + { + rawArgument: CLONE_FS.Value(), + }, + { + rawArgument: CLONE_VM.Value() | CLONE_FS.Value(), + }, + { + rawArgument: CLONE_VM.Value() | CLONE_FS.Value() | CLONE_FILES.Value(), + }, + { + rawArgument: CLONE_VM.Value() | CLONE_FILES.Value() | CLONE_THREAD.Value(), + }, + { + rawArgument: CLONE_VM.Value() | CLONE_FS.Value() | CLONE_FILES.Value() | CLONE_SIGHAND.Value(), + }, + { + rawArgument: CLONE_VM.Value() | CLONE_FS.Value() | CLONE_FILES.Value() | CLONE_SIGHAND.Value() | CLONE_PTRACE.Value(), + }, + { + rawArgument: CLONE_VM.Value() | CLONE_FS.Value() | CLONE_FILES.Value() | CLONE_SIGHAND.Value() | CLONE_PTRACE.Value() | CLONE_VFORK.Value(), + }, +} + +func BenchmarkParseCloneFlags(b *testing.B) { + for i := 0; i < b.N; i++ { + for _, tt := range parseCloneFlagsBenchTestArgs { + _, _ = ParseCloneFlags(tt.rawArgument) + } + } +} + var optionsAreContainedInArgumentTestTable = []struct { rawArgument uint64 options []uint64 diff --git a/pkg/events/parsers/data_parsers_test.go b/pkg/events/parsers/data_parsers_test.go index 70edb89f70fe..f0387fac6429 100644 --- a/pkg/events/parsers/data_parsers_test.go +++ b/pkg/events/parsers/data_parsers_test.go @@ -132,6 +132,210 @@ func Test_optionIsContainedInArgument(t *testing.T) { } } +func TestParseCloneFlags(t *testing.T) { + testCases := []struct { + name string + rawArgument uint64 + expectedSting string + expectedError bool + }{ + { + name: "No value", + rawArgument: 0, + expectedSting: "", + expectedError: false, + }, + { + name: "Single value", + rawArgument: CLONE_CHILD_CLEARTID.Value(), + expectedSting: "CLONE_CHILD_CLEARTID", + expectedError: false, + }, + { + name: "Multiple values", + rawArgument: CLONE_VM.Value() | CLONE_FS.Value(), + expectedSting: "CLONE_VM|CLONE_FS", + expectedError: false, + }, + { + name: "Non existing value", + rawArgument: 1, + expectedSting: "", + expectedError: true, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + opt, err := ParseCloneFlags(testCase.rawArgument) + if testCase.expectedError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + assert.Equal(t, testCase.expectedSting, opt) + }) + } +} + +func TestParseOpenFlagArgument(t *testing.T) { + tests := []struct { + name string + rawArgument uint64 + expectedString string + expectedErr bool + }{ + { + name: "Test O_RDONLY", + rawArgument: 0, + expectedString: O_RDONLY.String(), + }, + { + name: "Test O_WRONLY", + rawArgument: O_WRONLY.Value(), + expectedString: O_WRONLY.String(), + }, + { + name: "Test O_RDWR", + rawArgument: O_RDWR.Value(), + expectedString: O_RDWR.String(), + }, + { + name: "Test O_CREAT", + rawArgument: O_CREAT.Value(), + expectedString: O_RDONLY.String() + "|" + O_CREAT.String(), + }, + { + name: "Test O_RDWR | O_CREAT", + rawArgument: O_RDWR.Value() | O_CREAT.Value(), + expectedString: O_RDWR.String() + "|" + O_CREAT.String(), + }, + { + name: "Test O_WRONLY | O_CREAT | O_EXCL", + rawArgument: O_WRONLY.Value() | O_CREAT.Value() | O_EXCL.Value(), + expectedString: O_WRONLY.String() + "|" + O_CREAT.String() + "|" + O_EXCL.String(), + }, + { + name: "Test O_RDWR | O_CREAT | O_DSYNC | O_LARGEFILE", + rawArgument: O_RDWR.Value() | O_CREAT.Value() | O_DSYNC.Value() | O_LARGEFILE.Value(), + expectedString: O_RDWR.String() + "|" + O_CREAT.String() + "|" + O_DSYNC.String() + "|" + O_LARGEFILE.String(), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + opt, err := ParseOpenFlagArgument(tt.rawArgument) + if tt.expectedErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + assert.Equal(t, tt.expectedString, opt) + }) + } +} + +func TestParseAccessMode(t *testing.T) { + tests := []struct { + name string + rawArgument uint64 + expectedString string + expectedErr bool + }{ + { + name: "Test F_OK", + rawArgument: F_OK.Value(), + expectedString: F_OK.String(), + }, + { + name: "Test X_OK", + rawArgument: X_OK.Value(), + expectedString: X_OK.String(), + }, + { + name: "Test W_OK", + rawArgument: W_OK.Value(), + expectedString: W_OK.String(), + }, + { + name: "Test R_OK", + rawArgument: R_OK.Value(), + expectedString: R_OK.String(), + }, + { + name: "Test W_OK | R_OK", + rawArgument: W_OK.Value() | R_OK.Value(), + expectedString: W_OK.String() + "|" + R_OK.String(), + }, + { + name: "Test X_OK | W_OK | R_OK", + rawArgument: X_OK.Value() | W_OK.Value() | R_OK.Value(), + expectedString: X_OK.String() + "|" + W_OK.String() + "|" + R_OK.String(), + }, + { + name: "Test Invalid", + rawArgument: 0xff000000, + expectedString: "", + expectedErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + opt, err := ParseAccessMode(tt.rawArgument) + if tt.expectedErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + assert.Equal(t, tt.expectedString, opt) + }) + } +} + +func TestParseExecveatFlag(t *testing.T) { + tests := []struct { + name string + rawArgument uint64 + expectedString string + expectedErr bool + }{ + { + name: "Test AT_SYMLINK_NOFOLLOW", + rawArgument: AT_SYMLINK_NOFOLLOW.Value(), + expectedString: AT_SYMLINK_NOFOLLOW.String(), + }, + { + name: "Test AT_EMPTY_PATH", + rawArgument: AT_EMPTY_PATH.Value(), + expectedString: AT_EMPTY_PATH.String(), + }, + { + name: "Test AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH", + rawArgument: AT_SYMLINK_NOFOLLOW.Value() | AT_EMPTY_PATH.Value(), + expectedString: AT_SYMLINK_NOFOLLOW.String() + "|" + AT_EMPTY_PATH.String(), + }, + { + name: "Test Invalid", + rawArgument: 0xff000000, + expectedString: "", + expectedErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + opt, err := ParseExecveatFlag(tt.rawArgument) + if tt.expectedErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + assert.Equal(t, tt.expectedString, opt) + }) + } +} + func TestParseSetSocketOption(t *testing.T) { testCases := []struct { name string