From e93b7ded05f8db3c36aeb557e8e07c23aa9dda22 Mon Sep 17 00:00:00 2001 From: Nadav Strahilevitz Date: Thu, 2 Jun 2022 12:41:49 +0000 Subject: [PATCH] probes: add required dependency field This is done through the following steps: 1. Split the probes into a separate module 2. Probes are handled implicitly through handles 3. Events have probe dependencies which includes a handle and a required field 4. Attaching failure is handled according to the required field --- pkg/ebpf/events_definitions.go | 271 ++++++++++++++++----------------- pkg/ebpf/probes.go | 120 --------------- pkg/ebpf/tracee.go | 112 +++++++------- pkg/probes/probes.go | 220 ++++++++++++++++++++++++++ 4 files changed, 406 insertions(+), 317 deletions(-) delete mode 100644 pkg/ebpf/probes.go create mode 100644 pkg/probes/probes.go diff --git a/pkg/ebpf/events_definitions.go b/pkg/ebpf/events_definitions.go index 47f99f2b93c8..ecd9e084dd18 100644 --- a/pkg/ebpf/events_definitions.go +++ b/pkg/ebpf/events_definitions.go @@ -1,6 +1,9 @@ package ebpf -import "github.com/aquasecurity/tracee/types/trace" +import ( + "github.com/aquasecurity/tracee/pkg/probes" + "github.com/aquasecurity/tracee/types/trace" +) type dependencies struct { events []eventDependency // Events required to be loaded and/or submitted for the event to happen @@ -8,6 +11,11 @@ type dependencies struct { tailCalls []tailCall } +type probeDependency struct { + handle probes.Handle + required bool +} + type eventDependency struct { eventID int32 } @@ -24,7 +32,7 @@ type EventDefinition struct { Name string Internal bool Syscall bool - Probes []probe + Probes []probeDependency Dependencies dependencies Sets []string Params []trace.ArgMeta @@ -4809,8 +4817,8 @@ var EventsDefinitions = map[int32]EventDefinition{ SysEnterEventID: { ID32Bit: sys32undefined, Name: "sys_enter", - Probes: []probe{ - {event: "raw_syscalls:sys_enter", attach: rawTracepoint, fn: "tracepoint__raw_syscalls__sys_enter"}, + Probes: []probeDependency{ + {probes.SysEnter, true}, }, Sets: []string{}, Params: []trace.ArgMeta{ @@ -4820,8 +4828,8 @@ var EventsDefinitions = map[int32]EventDefinition{ SysExitEventID: { ID32Bit: sys32undefined, Name: "sys_exit", - Probes: []probe{ - {event: "raw_syscalls:sys_exit", attach: rawTracepoint, fn: "tracepoint__raw_syscalls__sys_exit"}, + Probes: []probeDependency{ + {probes.SysExit, true}, }, Sets: []string{}, Params: []trace.ArgMeta{ @@ -4831,8 +4839,8 @@ var EventsDefinitions = map[int32]EventDefinition{ SchedProcessForkEventID: { ID32Bit: sys32undefined, Name: "sched_process_fork", - Probes: []probe{ - {event: "sched:sched_process_fork", attach: rawTracepoint, fn: "tracepoint__sched__sched_process_fork"}, + Probes: []probeDependency{ + {probes.SchedProcessFork, true}, }, Sets: []string{}, Params: []trace.ArgMeta{ @@ -4850,9 +4858,9 @@ var EventsDefinitions = map[int32]EventDefinition{ SchedProcessExecEventID: { ID32Bit: sys32undefined, Name: "sched_process_exec", - Probes: []probe{ - {event: "sched:sched_process_exec", attach: rawTracepoint, fn: "tracepoint__sched__sched_process_exec"}, - {event: "load_elf_phdrs", attach: kprobe, fn: "trace_load_elf_phdrs"}, + Probes: []probeDependency{ + {probes.SchedProcessExec, true}, + {probes.LoadElfPhdrs, true}, }, Sets: []string{"default", "proc"}, Params: []trace.ArgMeta{ @@ -4873,8 +4881,8 @@ var EventsDefinitions = map[int32]EventDefinition{ SchedProcessExitEventID: { ID32Bit: sys32undefined, Name: "sched_process_exit", - Probes: []probe{ - {event: "sched:sched_process_exit", attach: rawTracepoint, fn: "tracepoint__sched__sched_process_exit"}, + Probes: []probeDependency{ + {probes.SchedProcessExit, true}, }, Sets: []string{"default", "proc", "proc_life"}, Params: []trace.ArgMeta{ @@ -4888,8 +4896,8 @@ var EventsDefinitions = map[int32]EventDefinition{ SchedSwitchEventID: { ID32Bit: sys32undefined, Name: "sched_switch", - Probes: []probe{ - {event: "sched:sched_switch", attach: rawTracepoint, fn: "tracepoint__sched__sched_switch"}, + Probes: []probeDependency{ + {probes.SchedSwitch, true}, }, Sets: []string{}, Params: []trace.ArgMeta{ @@ -4903,8 +4911,8 @@ var EventsDefinitions = map[int32]EventDefinition{ DoExitEventID: { ID32Bit: sys32undefined, Name: "do_exit", - Probes: []probe{ - {event: "do_exit", attach: kprobe, fn: "trace_do_exit"}, + Probes: []probeDependency{ + {probes.DoExit, true}, }, Sets: []string{"proc", "proc_life"}, Params: []trace.ArgMeta{}, @@ -4912,8 +4920,8 @@ var EventsDefinitions = map[int32]EventDefinition{ CapCapableEventID: { ID32Bit: sys32undefined, Name: "cap_capable", - Probes: []probe{ - {event: "cap_capable", attach: kprobe, fn: "trace_cap_capable"}, + Probes: []probeDependency{ + {probes.CapCapable, true}, }, Sets: []string{"default"}, Params: []trace.ArgMeta{ @@ -4924,9 +4932,9 @@ var EventsDefinitions = map[int32]EventDefinition{ VfsWriteEventID: { ID32Bit: sys32undefined, Name: "vfs_write", - Probes: []probe{ - {event: "vfs_write", attach: kprobe, fn: "trace_vfs_write"}, - {event: "vfs_write", attach: kretprobe, fn: "trace_ret_vfs_write"}, + Probes: []probeDependency{ + {probes.VfsWrite, true}, + {probes.VfsWriteRet, true}, }, Sets: []string{}, Params: []trace.ArgMeta{ @@ -4940,9 +4948,9 @@ var EventsDefinitions = map[int32]EventDefinition{ VfsWritevEventID: { ID32Bit: sys32undefined, Name: "vfs_writev", - Probes: []probe{ - {event: "vfs_writev", attach: kprobe, fn: "trace_vfs_writev"}, - {event: "vfs_writev", attach: kretprobe, fn: "trace_ret_vfs_writev"}, + Probes: []probeDependency{ + {probes.VfsWriteV, true}, + {probes.VfsWriteVRet, true}, }, Sets: []string{}, Params: []trace.ArgMeta{ @@ -4956,9 +4964,9 @@ var EventsDefinitions = map[int32]EventDefinition{ MemProtAlertEventID: { ID32Bit: sys32undefined, Name: "mem_prot_alert", - Probes: []probe{ - {event: "security_mmap_addr", attach: kprobe, fn: "trace_mmap_alert"}, - {event: "security_file_mprotect", attach: kprobe, fn: "trace_security_file_mprotect"}, + Probes: []probeDependency{ + {probes.SecurityMmapAddr, true}, + {probes.SecurityFileMProtect, true}, }, Sets: []string{}, Params: []trace.ArgMeta{ @@ -4968,8 +4976,8 @@ var EventsDefinitions = map[int32]EventDefinition{ CommitCredsEventID: { ID32Bit: sys32undefined, Name: "commit_creds", - Probes: []probe{ - {event: "commit_creds", attach: kprobe, fn: "trace_commit_creds"}, + Probes: []probeDependency{ + {probes.CommitCreds, true}, }, Sets: []string{}, Params: []trace.ArgMeta{ @@ -4981,8 +4989,8 @@ var EventsDefinitions = map[int32]EventDefinition{ SwitchTaskNSEventID: { ID32Bit: sys32undefined, Name: "switch_task_ns", - Probes: []probe{ - {event: "switch_task_namespaces", attach: kprobe, fn: "trace_switch_task_namespaces"}, + Probes: []probeDependency{ + {probes.SwitchTaskNS, true}, }, Sets: []string{}, Params: []trace.ArgMeta{ @@ -4998,13 +5006,13 @@ var EventsDefinitions = map[int32]EventDefinition{ MagicWriteEventID: { ID32Bit: sys32undefined, Name: "magic_write", - Probes: []probe{ - {event: "vfs_write", attach: kprobe, fn: "trace_vfs_write"}, - {event: "vfs_write", attach: kretprobe, fn: "trace_ret_vfs_write"}, - {event: "vfs_writev", attach: kprobe, fn: "trace_vfs_writev"}, - {event: "vfs_writev", attach: kretprobe, fn: "trace_ret_vfs_writev"}, - {event: "__kernel_write", attach: kprobe, fn: "trace_kernel_write"}, - {event: "__kernel_write", attach: kretprobe, fn: "trace_ret_kernel_write"}, + Probes: []probeDependency{ + {probes.VfsWrite, false}, + {probes.VfsWriteRet, false}, + {probes.VfsWriteV, false}, + {probes.VfsWriteVRet, false}, + {probes.KernelWrite, false}, + {probes.KernelWriteRet, false}, }, Sets: []string{}, Params: []trace.ArgMeta{ @@ -5017,8 +5025,8 @@ var EventsDefinitions = map[int32]EventDefinition{ CgroupAttachTaskEventID: { ID32Bit: sys32undefined, Name: "cgroup_attach_task", - Probes: []probe{ - {event: "cgroup:cgroup_attach_task", attach: rawTracepoint, fn: "tracepoint__cgroup__cgroup_attach_task"}, + Probes: []probeDependency{ + {probes.CgroupAttachTask, true}, }, Sets: []string{}, Params: []trace.ArgMeta{ @@ -5030,8 +5038,8 @@ var EventsDefinitions = map[int32]EventDefinition{ CgroupMkdirEventID: { ID32Bit: sys32undefined, Name: "cgroup_mkdir", - Probes: []probe{ - {event: "cgroup:cgroup_mkdir", attach: rawTracepoint, fn: "tracepoint__cgroup__cgroup_mkdir"}, + Probes: []probeDependency{ + {probes.CgroupMkdir, true}, }, Sets: []string{}, Params: []trace.ArgMeta{ @@ -5043,8 +5051,8 @@ var EventsDefinitions = map[int32]EventDefinition{ CgroupRmdirEventID: { ID32Bit: sys32undefined, Name: "cgroup_rmdir", - Probes: []probe{ - {event: "cgroup:cgroup_rmdir", attach: rawTracepoint, fn: "tracepoint__cgroup__cgroup_rmdir"}, + Probes: []probeDependency{ + {probes.CgroupRmdir, true}, }, Sets: []string{}, Params: []trace.ArgMeta{ @@ -5056,8 +5064,8 @@ var EventsDefinitions = map[int32]EventDefinition{ SecurityBprmCheckEventID: { ID32Bit: sys32undefined, Name: "security_bprm_check", - Probes: []probe{ - {event: "security_bprm_check", attach: kprobe, fn: "trace_security_bprm_check"}, + Probes: []probeDependency{ + {probes.SecurityBPRMCheck, true}, }, Sets: []string{"default", "lsm_hooks", "proc", "proc_life"}, Params: []trace.ArgMeta{ @@ -5069,8 +5077,8 @@ var EventsDefinitions = map[int32]EventDefinition{ SecurityFileOpenEventID: { ID32Bit: sys32undefined, Name: "security_file_open", - Probes: []probe{ - {event: "security_file_open", attach: kprobe, fn: "trace_security_file_open"}, + Probes: []probeDependency{ + {probes.SecurityFileOpen, true}, }, Sets: []string{"default", "lsm_hooks", "fs", "fs_file_ops"}, Params: []trace.ArgMeta{ @@ -5085,8 +5093,8 @@ var EventsDefinitions = map[int32]EventDefinition{ SecurityInodeUnlinkEventID: { ID32Bit: sys32undefined, Name: "security_inode_unlink", - Probes: []probe{ - {event: "security_inode_unlink", attach: kprobe, fn: "trace_security_inode_unlink"}, + Probes: []probeDependency{ + {probes.SecurityInodeUnlink, true}, }, Sets: []string{"default", "lsm_hooks", "fs", "fs_file_ops"}, Params: []trace.ArgMeta{ @@ -5096,8 +5104,8 @@ var EventsDefinitions = map[int32]EventDefinition{ SecuritySocketCreateEventID: { ID32Bit: sys32undefined, Name: "security_socket_create", - Probes: []probe{ - {event: "security_socket_create", attach: kprobe, fn: "trace_security_socket_create"}, + Probes: []probeDependency{ + {probes.SecuritySocketCreate, true}, }, Sets: []string{"default", "lsm_hooks", "net", "net_sock"}, Params: []trace.ArgMeta{ @@ -5110,8 +5118,8 @@ var EventsDefinitions = map[int32]EventDefinition{ SecuritySocketListenEventID: { ID32Bit: sys32undefined, Name: "security_socket_listen", - Probes: []probe{ - {event: "security_socket_listen", attach: kprobe, fn: "trace_security_socket_listen"}, + Probes: []probeDependency{ + {probes.SecuritySocketListen, true}, }, Sets: []string{"default", "lsm_hooks", "net", "net_sock"}, Params: []trace.ArgMeta{ @@ -5123,8 +5131,8 @@ var EventsDefinitions = map[int32]EventDefinition{ SecuritySocketConnectEventID: { ID32Bit: sys32undefined, Name: "security_socket_connect", - Probes: []probe{ - {event: "security_socket_connect", attach: kprobe, fn: "trace_security_socket_connect"}, + Probes: []probeDependency{ + {probes.SecuritySocketConnect, true}, }, Sets: []string{"default", "lsm_hooks", "net", "net_sock"}, Params: []trace.ArgMeta{ @@ -5135,8 +5143,8 @@ var EventsDefinitions = map[int32]EventDefinition{ SecuritySocketAcceptEventID: { ID32Bit: sys32undefined, Name: "security_socket_accept", - Probes: []probe{ - {event: "security_socket_accept", attach: kprobe, fn: "trace_security_socket_accept"}, + Probes: []probeDependency{ + {probes.SecuritySocketAccept, true}, }, Sets: []string{"default", "lsm_hooks", "net", "net_sock"}, Params: []trace.ArgMeta{ @@ -5147,8 +5155,8 @@ var EventsDefinitions = map[int32]EventDefinition{ SecuritySocketBindEventID: { ID32Bit: sys32undefined, Name: "security_socket_bind", - Probes: []probe{ - {event: "security_socket_bind", attach: kprobe, fn: "trace_security_socket_bind"}, + Probes: []probeDependency{ + {probes.SecuritySocketBind, true}, }, Sets: []string{"default", "lsm_hooks", "net", "net_sock"}, Params: []trace.ArgMeta{ @@ -5159,8 +5167,8 @@ var EventsDefinitions = map[int32]EventDefinition{ SecuritySbMountEventID: { ID32Bit: sys32undefined, Name: "security_sb_mount", - Probes: []probe{ - {event: "security_sb_mount", attach: kprobe, fn: "trace_security_sb_mount"}, + Probes: []probeDependency{ + {probes.SecuritySbMount, true}, }, Sets: []string{"default", "lsm_hooks", "fs"}, Params: []trace.ArgMeta{ @@ -5173,8 +5181,8 @@ var EventsDefinitions = map[int32]EventDefinition{ SecurityBPFEventID: { ID32Bit: sys32undefined, Name: "security_bpf", - Probes: []probe{ - {event: "security_bpf", attach: kprobe, fn: "trace_security_bpf"}, + Probes: []probeDependency{ + {probes.SecurityBPF, true}, }, Sets: []string{"lsm_hooks"}, Params: []trace.ArgMeta{ @@ -5184,8 +5192,8 @@ var EventsDefinitions = map[int32]EventDefinition{ SecurityBPFMapEventID: { ID32Bit: sys32undefined, Name: "security_bpf_map", - Probes: []probe{ - {event: "security_bpf_map", attach: kprobe, fn: "trace_security_bpf_map"}, + Probes: []probeDependency{ + {probes.SecurityBPFMap, true}, }, Sets: []string{"lsm_hooks"}, Params: []trace.ArgMeta{ @@ -5196,8 +5204,8 @@ var EventsDefinitions = map[int32]EventDefinition{ SecurityKernelReadFileEventID: { ID32Bit: sys32undefined, Name: "security_kernel_read_file", - Probes: []probe{ - {event: "security_kernel_read_file", attach: kprobe, fn: "trace_security_kernel_read_file"}, + Probes: []probeDependency{ + {probes.SecurityKernelReadFile, true}, }, Sets: []string{"lsm_hooks"}, Params: []trace.ArgMeta{ @@ -5211,8 +5219,8 @@ var EventsDefinitions = map[int32]EventDefinition{ SecurityPostReadFileEventID: { ID32Bit: sys32undefined, Name: "security_kernel_post_read_file", - Probes: []probe{ - {event: "security_kernel_post_read_file", attach: kprobe, fn: "trace_security_kernel_post_read_file"}, + Probes: []probeDependency{ + {probes.SecurityKernelPostReadFile, true}, }, Sets: []string{"lsm_hooks"}, Params: []trace.ArgMeta{ @@ -5224,8 +5232,8 @@ var EventsDefinitions = map[int32]EventDefinition{ SecurityInodeMknodEventID: { ID32Bit: sys32undefined, Name: "security_inode_mknod", - Probes: []probe{ - {event: "security_inode_mknod", attach: kprobe, fn: "trace_security_inode_mknod"}, + Probes: []probeDependency{ + {probes.SecurityInodeMknod, true}, }, Sets: []string{"lsm_hooks"}, Params: []trace.ArgMeta{ @@ -5237,8 +5245,8 @@ var EventsDefinitions = map[int32]EventDefinition{ SecurityInodeSymlinkEventId: { ID32Bit: sys32undefined, Name: "security_inode_symlink", - Probes: []probe{ - {event: "security_inode_symlink", attach: kprobe, fn: "trace_security_inode_symlink"}, + Probes: []probeDependency{ + {probes.SecurityInodeSymlink, true}, }, Sets: []string{"lsm_hooks", "fs", "fs_file_ops"}, Params: []trace.ArgMeta{ @@ -5249,8 +5257,8 @@ var EventsDefinitions = map[int32]EventDefinition{ SecurityMmapFileEventID: { ID32Bit: sys32undefined, Name: "security_mmap_file", - Probes: []probe{ - {event: "security_mmap_file", attach: kprobe, fn: "trace_security_mmap_file"}, + Probes: []probeDependency{ + {probes.SecurityMmapFile, true}, }, Sets: []string{"lsm_hooks", "fs", "fs_file_ops", "proc", "proc_mem"}, Params: []trace.ArgMeta{ @@ -5267,8 +5275,8 @@ var EventsDefinitions = map[int32]EventDefinition{ SecurityFileMprotectEventID: { ID32Bit: sys32undefined, Name: "security_file_mprotect", - Probes: []probe{ - {event: "security_file_mprotect", attach: kprobe, fn: "trace_security_file_mprotect"}, + Probes: []probeDependency{ + {probes.SecurityFileMProtect, true}, }, Sets: []string{"lsm_hooks", "proc", "proc_mem", "fs", "fs_file_ops"}, Params: []trace.ArgMeta{ @@ -5280,7 +5288,6 @@ var EventsDefinitions = map[int32]EventDefinition{ InitNamespacesEventID: { ID32Bit: sys32undefined, Name: "init_namespaces", - Probes: []probe{}, Sets: []string{}, Params: []trace.ArgMeta{ {Type: "u32", Name: "cgroup"}, @@ -5298,7 +5305,6 @@ var EventsDefinitions = map[int32]EventDefinition{ SocketDupEventID: { ID32Bit: sys32undefined, Name: "socket_dup", - Probes: []probe{}, Dependencies: dependencies{ tailCalls: []tailCall{ {mapName: "sys_exit_tails", mapIdx: uint32(DupEventID), progName: "sys_dup_exit_tail"}, @@ -5316,8 +5322,8 @@ var EventsDefinitions = map[int32]EventDefinition{ HiddenInodesEventID: { ID32Bit: sys32undefined, Name: "hidden_inodes", - Probes: []probe{ - {event: "filldir64", attach: kprobe, fn: "trace_filldir64"}, + Probes: []probeDependency{ + {probes.Filldir64, true}, }, Sets: []string{}, Params: []trace.ArgMeta{ @@ -5327,9 +5333,9 @@ var EventsDefinitions = map[int32]EventDefinition{ __KernelWriteEventID: { ID32Bit: sys32undefined, Name: "__kernel_write", - Probes: []probe{ - {event: "__kernel_write", attach: kprobe, fn: "trace_kernel_write"}, - {event: "__kernel_write", attach: kretprobe, fn: "trace_ret_kernel_write"}, + Probes: []probeDependency{ + {probes.KernelWrite, true}, + {probes.KernelWriteRet, true}, }, Sets: []string{}, Params: []trace.ArgMeta{ @@ -5343,9 +5349,9 @@ var EventsDefinitions = map[int32]EventDefinition{ DirtyPipeSpliceEventID: { ID32Bit: sys32undefined, Name: "dirty_pipe_splice", - Probes: []probe{ - {event: "do_splice", attach: kprobe, fn: "trace_do_splice"}, - {event: "do_splice", attach: kretprobe, fn: "trace_ret_do_splice"}, + Probes: []probeDependency{ + {probes.DoSplice, true}, + {probes.DoSpliceRet, true}, }, Sets: []string{}, Dependencies: dependencies{ @@ -5364,7 +5370,6 @@ var EventsDefinitions = map[int32]EventDefinition{ ContainerCreateEventID: { ID32Bit: sys32undefined, Name: "container_create", - Probes: []probe{}, Dependencies: dependencies{ events: []eventDependency{{eventID: CgroupMkdirEventID}}, }, @@ -5383,7 +5388,6 @@ var EventsDefinitions = map[int32]EventDefinition{ ContainerRemoveEventID: { ID32Bit: sys32undefined, Name: "container_remove", - Probes: []probe{}, Dependencies: dependencies{ events: []eventDependency{{eventID: CgroupRmdirEventID}}, }, @@ -5396,7 +5400,6 @@ var EventsDefinitions = map[int32]EventDefinition{ ExistingContainerEventID: { ID32Bit: sys32undefined, Name: "existing_container", - Probes: []probe{}, Sets: []string{}, Params: []trace.ArgMeta{ {Type: "const char*", Name: "runtime"}, @@ -5407,7 +5410,6 @@ var EventsDefinitions = map[int32]EventDefinition{ NetPacket: { ID32Bit: sys32undefined, Name: "net_packet", - Probes: []probe{}, Dependencies: dependencies{}, Sets: []string{"network_events"}, Params: []trace.ArgMeta{ @@ -5417,7 +5419,6 @@ var EventsDefinitions = map[int32]EventDefinition{ DnsRequest: { ID32Bit: sys32undefined, Name: "dns_request", - Probes: []probe{}, Dependencies: dependencies{}, Sets: []string{"network_events"}, Params: []trace.ArgMeta{ @@ -5428,7 +5429,6 @@ var EventsDefinitions = map[int32]EventDefinition{ DnsResponse: { ID32Bit: sys32undefined, Name: "dns_response", - Probes: []probe{}, Dependencies: dependencies{}, Sets: []string{"network_events"}, Params: []trace.ArgMeta{ @@ -5439,8 +5439,8 @@ var EventsDefinitions = map[int32]EventDefinition{ ProcCreateEventID: { ID32Bit: sys32undefined, Name: "proc_create", - Probes: []probe{ - {event: "proc_create", attach: kprobe, fn: "trace_proc_create"}, + Probes: []probeDependency{ + {probes.ProcCreate, true}, }, Sets: []string{}, Params: []trace.ArgMeta{ @@ -5451,8 +5451,8 @@ var EventsDefinitions = map[int32]EventDefinition{ KprobeAttachEventID: { ID32Bit: sys32undefined, Name: "kprobe_attach", - Probes: []probe{ - {event: "arm_kprobe", attach: kprobe, fn: "trace_arm_kprobe"}, + Probes: []probeDependency{ + {probes.ARMKprobe, true}, }, Sets: []string{}, Params: []trace.ArgMeta{ @@ -5464,8 +5464,8 @@ var EventsDefinitions = map[int32]EventDefinition{ CallUsermodeHelperEventID: { ID32Bit: sys32undefined, Name: "call_usermodehelper", - Probes: []probe{ - {event: "call_usermodehelper", attach: kprobe, fn: "trace_call_usermodehelper"}, + Probes: []probeDependency{ + {probes.CallUsermodeHelper, true}, }, Sets: []string{}, Params: []trace.ArgMeta{ @@ -5478,8 +5478,8 @@ var EventsDefinitions = map[int32]EventDefinition{ DebugfsCreateFileEventID: { ID32Bit: sys32undefined, Name: "debugfs_create_file", - Probes: []probe{ - {event: "debugfs_create_file", attach: kprobe, fn: "trace_debugfs_create_file"}, + Probes: []probeDependency{ + {probes.DebugfsCreateFile, true}, }, Sets: []string{}, Params: []trace.ArgMeta{ @@ -5493,8 +5493,8 @@ var EventsDefinitions = map[int32]EventDefinition{ ID32Bit: sys32undefined, Name: "print_syscall_table", Internal: true, - Probes: []probe{ - {event: "security_file_ioctl", attach: kprobe, fn: "trace_tracee_trigger_event"}, + Probes: []probeDependency{ + {probes.SecurityFileIoctl, true}, }, Dependencies: dependencies{ksymbols: []string{"sys_call_table"}}, Sets: []string{}, @@ -5520,8 +5520,8 @@ var EventsDefinitions = map[int32]EventDefinition{ DebugfsCreateDirEventID: { ID32Bit: sys32undefined, Name: "debugfs_create_dir", - Probes: []probe{ - {event: "debugfs_create_dir", attach: kprobe, fn: "trace_debugfs_create_dir"}, + Probes: []probeDependency{ + {probes.DebugfsCreateDir, true}, }, Sets: []string{}, Params: []trace.ArgMeta{ @@ -5532,8 +5532,8 @@ var EventsDefinitions = map[int32]EventDefinition{ DeviceAddEventID: { ID32Bit: sys32undefined, Name: "device_add", - Probes: []probe{ - {event: "device_add", attach: kprobe, fn: "trace_device_add"}, + Probes: []probeDependency{ + {probes.DeviceAdd, true}, }, Sets: []string{}, Params: []trace.ArgMeta{ @@ -5544,9 +5544,9 @@ var EventsDefinitions = map[int32]EventDefinition{ RegisterChrdevEventID: { ID32Bit: sys32undefined, Name: "register_chrdev", - Probes: []probe{ - {event: "__register_chrdev", attach: kprobe, fn: "trace___register_chrdev"}, - {event: "__register_chrdev", attach: kretprobe, fn: "trace_ret__register_chrdev"}, + Probes: []probeDependency{ + {probes.RegisterChrdev, true}, + {probes.RegisterChrdevRet, true}, }, Sets: []string{}, Params: []trace.ArgMeta{ @@ -5559,7 +5559,6 @@ var EventsDefinitions = map[int32]EventDefinition{ SharedObjectLoadedEventID: { ID32Bit: sys32undefined, Name: "shared_object_loaded", - Probes: []probe{}, Dependencies: dependencies{ events: []eventDependency{{eventID: SecurityMmapFileEventID}}, }, @@ -5576,13 +5575,13 @@ var EventsDefinitions = map[int32]EventDefinition{ ID32Bit: sys32undefined, Name: "capture_file_write", Internal: true, - Probes: []probe{ - {event: "vfs_write", attach: kprobe, fn: "trace_vfs_write"}, - {event: "vfs_write", attach: kretprobe, fn: "trace_ret_vfs_write"}, - {event: "vfs_writev", attach: kprobe, fn: "trace_vfs_writev"}, - {event: "vfs_writev", attach: kretprobe, fn: "trace_ret_vfs_writev"}, - {event: "__kernel_write", attach: kprobe, fn: "trace_kernel_write"}, - {event: "__kernel_write", attach: kretprobe, fn: "trace_ret_kernel_write"}, + Probes: []probeDependency{ + {probes.VfsWrite, false}, + {probes.VfsWriteRet, false}, + {probes.VfsWriteV, false}, + {probes.VfsWriteVRet, false}, + {probes.KernelWrite, false}, + {probes.KernelWriteRet, false}, }, Dependencies: dependencies{ tailCalls: []tailCall{ @@ -5597,7 +5596,6 @@ var EventsDefinitions = map[int32]EventDefinition{ ID32Bit: sys32undefined, Name: "capture_exec", Internal: true, - Probes: []probe{}, Dependencies: dependencies{ events: []eventDependency{{eventID: SchedProcessExecEventID}}, }, @@ -5606,10 +5604,10 @@ var EventsDefinitions = map[int32]EventDefinition{ ID32Bit: sys32undefined, Name: "capture_module", Internal: true, - Probes: []probe{ - {event: "raw_syscalls:sys_enter", attach: rawTracepoint, fn: "tracepoint__raw_syscalls__sys_enter"}, - {event: "raw_syscalls:sys_exit", attach: rawTracepoint, fn: "tracepoint__raw_syscalls__sys_exit"}, - {event: "security_kernel_post_read_file", attach: kprobe, fn: "trace_security_kernel_post_read_file"}, + Probes: []probeDependency{ + {probes.SysEnter, true}, + {probes.SysExit, true}, + {probes.SecurityKernelPostReadFile, true}, }, Dependencies: dependencies{ events: []eventDependency{{eventID: SchedProcessExecEventID}}, @@ -5624,7 +5622,6 @@ var EventsDefinitions = map[int32]EventDefinition{ ID32Bit: sys32undefined, Name: "capture_mem", Internal: true, - Probes: []probe{}, Dependencies: dependencies{ tailCalls: []tailCall{ {mapName: "prog_array", mapIdx: tailSendBin, progName: "send_bin"}, @@ -5635,7 +5632,6 @@ var EventsDefinitions = map[int32]EventDefinition{ ID32Bit: sys32undefined, Name: "capture_profile", Internal: true, - Probes: []probe{}, Dependencies: dependencies{ events: []eventDependency{{eventID: SchedProcessExecEventID}}, }, @@ -5644,7 +5640,6 @@ var EventsDefinitions = map[int32]EventDefinition{ ID32Bit: sys32undefined, Name: "capture_pcap", Internal: true, - Probes: []probe{}, Dependencies: dependencies{ events: []eventDependency{{eventID: SecuritySocketBindEventID}}, }, @@ -5652,9 +5647,9 @@ var EventsDefinitions = map[int32]EventDefinition{ DoInitModuleEventID: { ID32Bit: sys32undefined, Name: "do_init_module", - Probes: []probe{ - {event: "do_init_module", attach: kprobe, fn: "trace_do_init_module"}, - {event: "do_init_module", attach: kretprobe, fn: "trace_ret_do_init_module"}, + Probes: []probeDependency{ + {probes.DoInitModule, true}, + {probes.DoInitModuleRet, true}, }, Dependencies: dependencies{}, Sets: []string{}, @@ -5672,9 +5667,9 @@ var EventsDefinitions = map[int32]EventDefinition{ ID32Bit: sys32undefined, Name: "socket_accept", Internal: false, - Probes: []probe{ - {event: "raw_syscalls:sys_enter", attach: rawTracepoint, fn: "tracepoint__raw_syscalls__sys_enter"}, - {event: "raw_syscalls:sys_exit", attach: rawTracepoint, fn: "tracepoint__raw_syscalls__sys_exit"}, + Probes: []probeDependency{ + {probes.SysEnter, true}, + {probes.SysExit, true}, }, Dependencies: dependencies{ events: []eventDependency{{eventID: SecuritySocketAcceptEventID}}, @@ -5692,8 +5687,8 @@ var EventsDefinitions = map[int32]EventDefinition{ LoadElfPhdrsEventID: { ID32Bit: sys32undefined, Name: "load_elf_phdrs", - Probes: []probe{ - {event: "load_elf_phdrs", attach: kprobe, fn: "trace_load_elf_phdrs"}, + Probes: []probeDependency{ + {probes.LoadElfPhdrs, true}, }, Sets: []string{"proc"}, Params: []trace.ArgMeta{ @@ -5705,8 +5700,8 @@ var EventsDefinitions = map[int32]EventDefinition{ HookedProcFopsEventID: { ID32Bit: sys32undefined, Name: "hooked_proc_fops", - Probes: []probe{ - {event: "security_file_permission", attach: kprobe, fn: "trace_security_file_permission"}, + Probes: []probeDependency{ + {probes.SecurityFilePermission, true}, }, Dependencies: dependencies{ ksymbols: []string{"_stext", "_etext"}, diff --git a/pkg/ebpf/probes.go b/pkg/ebpf/probes.go deleted file mode 100644 index b7533dd9b805..000000000000 --- a/pkg/ebpf/probes.go +++ /dev/null @@ -1,120 +0,0 @@ -package ebpf - -import ( - "fmt" - "strings" - - bpf "github.com/aquasecurity/libbpfgo" -) - -type probe struct { - event string - attach probeType - fn string - link *bpf.BPFLink -} - -// ProbeType is an enum that describes the mechanism used to attach the event -// Kprobes are explained here: https://github.com/iovisor/bcc/blob/master/docs/reference_guide.md#1-kprobes -// Tracepoints are explained here: https://github.com/iovisor/bcc/blob/master/docs/reference_guide.md#3-tracepoints -// Raw tracepoints are explained here: https://github.com/iovisor/bcc/blob/master/docs/reference_guide.md#7-raw-tracepoints -type probeType uint8 - -const ( - kprobe = iota - kretprobe - tracepoint - rawTracepoint -) - -func (p *probe) Attach(module *bpf.Module) error { - prog, err := module.GetProgram(p.event) - if err != nil { - return err - } - var link *bpf.BPFLink - switch p.attach { - case kprobe: - _, err = prog.AttachKprobe(p.event) - case kretprobe: - _, err = prog.AttachKretprobe(p.event) - case tracepoint: - tpEvent := strings.Split(p.event, ":") - if len(tpEvent) != 2 { - err = fmt.Errorf("tracepoint must be in 'category:name' format") - } else { - _, err = prog.AttachTracepoint(p.event, p.event) - } - case rawTracepoint: - tpEvent := strings.Split(p.event, ":")[1] - _, err = prog.AttachRawTracepoint(tpEvent) - } - if err != nil { - return fmt.Errorf("error attaching event %s: %v", p.event, err) - } - return nil -} - -func (p *probe) Detach(module *bpf.Module) error { - prog, err := module.GetProgram(p.event) - if err != nil { - return err - } - - prog. - - return nil -} - -const ( - SysEnterProbe = iota - SysExitProbe - SchedProcessForkProbe - SchedProcessExecProbe - SchedProcessExitProbe - SchedSwitchProbe - DoExitProbe - CapCapableProbe - VfsWriteProbe - VfsWriteRetProbe - VfsWriteVProbe - VfsWriteVRetProbe - SecurityMmapAddrProbe - SecurityMmapFileProbe - SecurityFileMProtectProbe - CommitCredsProbe - SwitchTaskNSProbe - __KernelWriteProbe - __KernelWriteRetProbe - CgroupAttachTaskProbe - CgroupMkdirProbe - CgroupRmdirProbe - SecurityBPRMCheckProbe - SecurityFileOpenProbe - SecurityInodeUnlinkProbe - SecurityInodeMknodProbe - SecurityInodeSymlinkProbe - SecuritySocketCreateProbe - SecuritySocketListenProbe - SecuritySocketConnectProbe - SecuritySocketAcceptProbe - SecuritySocketBindProbe - SecuritySbMountProbe - SecurityBPFProbe - SecurityBPFMapProbe - SecurityKernelReadFileProbe - SecurityKernelPostReadFileProbe - DoSpliceProbe - DoSpliceRetProbe - ProcCreateProbe - ARMKprobeProbe - CallUsermodeHelperProbe - DebugfsCreateFileProbe - DebugfsCreateDirProbe - SecurityFileIoctlProbe - DeviceAddProbe - RegisterChrdevProbe - RegisterChrdevRetProbe - DoInitModuleProbe - DoInitModuleRetProbe -) diff --git a/pkg/ebpf/tracee.go b/pkg/ebpf/tracee.go index b7eb2a3dfa0d..7cbe18a68b9e 100644 --- a/pkg/ebpf/tracee.go +++ b/pkg/ebpf/tracee.go @@ -27,6 +27,7 @@ import ( "github.com/aquasecurity/tracee/pkg/events/queue" "github.com/aquasecurity/tracee/pkg/events/sorting" "github.com/aquasecurity/tracee/pkg/metrics" + "github.com/aquasecurity/tracee/pkg/probes" "github.com/aquasecurity/tracee/pkg/procinfo" "github.com/aquasecurity/tracee/types/trace" lru "github.com/hashicorp/golang-lru" @@ -172,6 +173,7 @@ type eventConfig struct { // Tracee traces system calls and system events using eBPF type Tracee struct { config Config + probes probes.Probes events map[int32]eventConfig bpfModule *bpf.Module eventsPerfMap *bpf.PerfBuffer @@ -205,6 +207,43 @@ func (t *Tracee) Stats() *metrics.Stats { return &t.stats } +// Setup events which are essential by default +func (t *Tracee) initEssentialEvents() { + t.events = make(map[int32]eventConfig, len(t.config.Filter.EventsToTrace)) + + // Set essential events + t.events[SysEnterEventID] = eventConfig{} + t.events[SysExitEventID] = eventConfig{} + t.events[SchedProcessForkEventID] = eventConfig{} + t.events[SchedProcessExecEventID] = eventConfig{} + t.events[SchedProcessExitEventID] = eventConfig{} + t.events[CgroupMkdirEventID] = eventConfig{submit: true} + t.events[CgroupRmdirEventID] = eventConfig{submit: true} + + // Set events used to capture data + if t.config.Capture.Exec { + t.events[CaptureExecEventID] = eventConfig{} + } + if t.config.Capture.FileWrite { + t.events[CaptureFileWriteEventID] = eventConfig{} + } + if t.config.Capture.Module { + t.events[CaptureModuleEventID] = eventConfig{} + } + if t.config.Capture.Mem { + t.events[CaptureMemEventID] = eventConfig{} + } + if t.config.Capture.Profile { + t.events[CaptureProfileEventID] = eventConfig{} + } + if t.config.Capture.NetIfaces != nil { + t.events[CapturePcapEventID] = eventConfig{} + } + if len(t.config.Filter.NetFilter.InterfacesToTrace) > 0 || t.config.Debug { + t.events[SecuritySocketBindEventID] = eventConfig{} + } +} + func (t *Tracee) handleEventsDependencies(e int32, initReq *RequiredInitValues) { eDependencies := EventsDefinitions[e].Dependencies if len(eDependencies.ksymbols) > 0 { @@ -253,39 +292,8 @@ func New(cfg Config) (*Tracee, error) { return nil, fmt.Errorf("error creating process tree: %v", err) } - t.events = make(map[int32]eventConfig, len(cfg.Filter.EventsToTrace)) - - // Set essential events - t.events[SysEnterEventID] = eventConfig{} - t.events[SysExitEventID] = eventConfig{} - t.events[SchedProcessForkEventID] = eventConfig{} - t.events[SchedProcessExecEventID] = eventConfig{} - t.events[SchedProcessExitEventID] = eventConfig{} - t.events[CgroupMkdirEventID] = eventConfig{submit: true} - t.events[CgroupRmdirEventID] = eventConfig{submit: true} - - // Set events used to capture data - if t.config.Capture.Exec { - t.events[CaptureExecEventID] = eventConfig{} - } - if t.config.Capture.FileWrite { - t.events[CaptureFileWriteEventID] = eventConfig{} - } - if t.config.Capture.Module { - t.events[CaptureModuleEventID] = eventConfig{} - } - if t.config.Capture.Mem { - t.events[CaptureMemEventID] = eventConfig{} - } - if t.config.Capture.Profile { - t.events[CaptureProfileEventID] = eventConfig{} - } - if t.config.Capture.NetIfaces != nil { - t.events[CapturePcapEventID] = eventConfig{} - } - if len(t.config.Filter.NetFilter.InterfacesToTrace) > 0 || cfg.Debug { - t.events[SecuritySocketBindEventID] = eventConfig{} - } + // Setup events which are essential by default + t.initEssentialEvents() // Events chosen by the user for _, e := range t.config.Filter.EventsToTrace { @@ -959,6 +967,13 @@ func (t *Tracee) initBPF() error { return err } + // Initialize probes + t.probes, err = probes.InitProbes(t.bpfModule) + + if err != nil { + return fmt.Errorf("failed to initialize probes: %s", err.Error()) + } + if t.config.Capture.NetIfaces == nil && !t.config.Debug && len(t.config.Filter.NetFilter.InterfacesToTrace) == 0 { // SecuritySocketBindEventID is set as an essentialEvent if 'capture net' or 'debug' were chosen by the user. networkProbes := []string{"tc_ingress", "tc_egress", "trace_udp_sendmsg", "trace_udp_disconnect", "trace_udp_destroy_sock", "trace_udpv6_destroy_sock", "tracepoint__inet_sock_set_state", "trace_icmp_send", "trace_icmp_rcv", "trace_icmp6_send", "trace_icmpv6_rcv", "trace_ping_v4_sendmsg", "trace_ping_v6_sendmsg"} @@ -1014,40 +1029,19 @@ func (t *Tracee) initBPF() error { } } - seenProbes := make(map[probe]bool) - for e := range t.events { event, ok := EventsDefinitions[e] if !ok { continue } - for _, probe := range event.Probes { - if seenProbes[probe] { - continue - } - seenProbes[probe] = true - prog, err := t.bpfModule.GetProgram(probe.fn) + for _, dep := range event.Probes { + err := t.probes.Attach(dep.handle) if err != nil { - return fmt.Errorf("error getting program %s: %v", probe.fn, err) - } - switch probe.attach { - case kprobe: - _, err = prog.AttachKprobe(probe.event) - case kretprobe: - _, err = prog.AttachKretprobe(probe.event) - case tracepoint: - tpEvent := strings.Split(probe.event, ":") - if len(tpEvent) != 2 { - err = fmt.Errorf("tracepoint must be in 'category:name' format") + if dep.required { + return fmt.Errorf("failed to attach required probe: %v", err) } else { - _, err = prog.AttachTracepoint(probe.event, probe.event) + t.handleError(fmt.Errorf("failed to attach unrequired probe, tracee will continue to load, error was %v", err)) } - case rawTracepoint: - tpEvent := strings.Split(probe.event, ":")[1] - _, err = prog.AttachRawTracepoint(tpEvent) - } - if err != nil { - return fmt.Errorf("error attaching event %s: %v", probe.event, err) } } } diff --git a/pkg/probes/probes.go b/pkg/probes/probes.go new file mode 100644 index 000000000000..cb3222b68aad --- /dev/null +++ b/pkg/probes/probes.go @@ -0,0 +1,220 @@ +package probes + +import ( + "fmt" + "strings" + + bpf "github.com/aquasecurity/libbpfgo" +) + +type Probes interface { + Attach(probe Handle) error + Detach(probe Handle) error +} +type probes struct { + probes map[Handle]*probe + module *bpf.Module +} + +type probe struct { + event string + probeType probeType + fn string + link *bpf.BPFLink +} + +func InitProbes(module *bpf.Module) (Probes, error) { + return &probes{ + probes: map[Handle]*probe{ + SysEnter: {event: "raw_syscalls:sys_enter", probeType: rawTracepoint, fn: "tracepoint__raw_syscalls__sys_enter"}, + SysExit: {event: "raw_syscalls:sys_exit", probeType: rawTracepoint, fn: "tracepoint__raw_syscalls__sys_exit"}, + SchedProcessFork: {event: "sched:sched_process_fork", probeType: rawTracepoint, fn: "tracepoint__sched__sched_process_fork"}, + SchedProcessExec: {event: "sched:sched_process_exec", probeType: rawTracepoint, fn: "tracepoint__sched__sched_process_exec"}, + SchedProcessExit: {event: "sched:sched_process_exit", probeType: rawTracepoint, fn: "tracepoint__sched__sched_process_exit"}, + SchedSwitch: {event: "sched:sched_switch", probeType: rawTracepoint, fn: "tracepoint__sched__sched_switch"}, + DoExit: {event: "do_exit", probeType: kprobe, fn: "trace_do_exit"}, + CapCapable: {event: "cap_capable", probeType: kprobe, fn: "trace_cap_capable"}, + VfsWrite: {event: "vfs_write", probeType: kprobe, fn: "trace_vfs_write"}, + VfsWriteRet: {event: "vfs_write", probeType: kretprobe, fn: "trace_ret_vfs_write"}, + VfsWriteV: {event: "vfs_writev", probeType: kprobe, fn: "trace_vfs_writev"}, + VfsWriteVRet: {event: "vfs_writev", probeType: kretprobe, fn: "trace_ret_vfs_writev"}, + KernelWrite: {event: "__kernel_write", probeType: kprobe, fn: "trace_kernel_write"}, + KernelWriteRet: {event: "__kernel_write", probeType: kretprobe, fn: "trace_ret_kernel_write"}, + CgroupAttachTask: {event: "cgroup:cgroup_attach_task", probeType: rawTracepoint, fn: "tracepoint__cgroup__cgroup_attach_task"}, + CgroupMkdir: {event: "cgroup:cgroup_mkdir", probeType: rawTracepoint, fn: "tracepoint__cgroup__cgroup_mkdir"}, + CgroupRmdir: {event: "cgroup:cgroup_rmdir", probeType: rawTracepoint, fn: "tracepoint__cgroup__cgroup_rmdir"}, + SecurityBPRMCheck: {event: "security_bprm_check", probeType: kprobe, fn: "trace_security_bprm_check"}, + SecurityFileOpen: {event: "security_file_open", probeType: kprobe, fn: "trace_security_file_open"}, + SecurityFileIoctl: {event: "security_file_ioctl", probeType: kprobe, fn: "trace_tracee_trigger_event"}, + SecurityFilePermission: {event: "security_file_permission", probeType: kprobe, fn: "trace_security_file_permission"}, + SecuritySocketCreate: {event: "security_socket_create", probeType: kprobe, fn: "trace_security_socket_create"}, + SecuritySocketListen: {event: "security_socket_listen", probeType: kprobe, fn: "trace_security_socket_listen"}, + SecuritySocketConnect: {event: "security_socket_connect", probeType: kprobe, fn: "trace_security_socket_connect"}, + SecuritySocketAccept: {event: "security_socket_accept", probeType: kprobe, fn: "trace_security_socket_accept"}, + SecuritySocketBind: {event: "security_socket_bind", probeType: kprobe, fn: "trace_security_socket_bind"}, + SecuritySbMount: {event: "security_sb_mount", probeType: kprobe, fn: "trace_security_sb_mount"}, + SecurityBPF: {event: "security_bpf", probeType: kprobe, fn: "trace_security_bpf"}, + SecurityBPFMap: {event: "security_bpf_map", probeType: kprobe, fn: "trace_security_bpf_map"}, + SecurityKernelReadFile: {event: "security_kernel_read_file", probeType: kprobe, fn: "trace_security_kernel_read_file"}, + SecurityKernelPostReadFile: {event: "security_kernel_post_read_file", probeType: kprobe, fn: "trace_security_kernel_post_read_file"}, + SecurityInodeMknod: {event: "security_inode_mknod", probeType: kprobe, fn: "trace_security_inode_mknod"}, + SecurityInodeSymlink: {event: "security_inode_symlink", probeType: kprobe, fn: "trace_security_inode_symlink"}, + SecurityInodeUnlink: {event: "security_inode_unlink", probeType: kprobe, fn: "trace_security_inode_unlink"}, + SecurityMmapAddr: {event: "security_mmap_addr", probeType: kprobe, fn: "trace_mmap_alert"}, + SecurityMmapFile: {event: "security_mmap_file", probeType: kprobe, fn: "trace_security_mmap_file"}, + DoSplice: {event: "do_splice", probeType: kprobe, fn: "trace_do_splice"}, + DoSpliceRet: {event: "do_splice", probeType: kretprobe, fn: "trace_ret_do_splice"}, + ProcCreate: {event: "proc_create", probeType: kprobe, fn: "trace_proc_create"}, + SecurityFileMProtect: {event: "security_file_mprotect", probeType: kprobe, fn: "trace_security_file_mprotect"}, + CommitCreds: {event: "commit_creds", probeType: kprobe, fn: "trace_commit_creds"}, + SwitchTaskNS: {event: "switch_task_namespaces", probeType: kprobe, fn: "trace_switch_task_namespaces"}, + ARMKprobe: {event: "arm_kprobe", probeType: kprobe, fn: "trace_arm_kprobe"}, + CallUsermodeHelper: {event: "call_usermodehelper", probeType: kprobe, fn: "trace_call_usermodehelper"}, + DebugfsCreateFile: {event: "debugfs_create_file", probeType: kprobe, fn: "trace_debugfs_create_file"}, + DebugfsCreateDir: {event: "debugfs_create_dir", probeType: kprobe, fn: "trace_debugfs_create_dir"}, + DeviceAdd: {event: "device_add", probeType: kprobe, fn: "trace_device_add"}, + RegisterChrdev: {event: "__register_chrdev", probeType: kprobe, fn: "trace___register_chrdev"}, + RegisterChrdevRet: {event: "__register_chrdev", probeType: kretprobe, fn: "trace_ret__register_chrdev"}, + DoInitModule: {event: "do_init_module", probeType: kprobe, fn: "trace_do_init_module"}, + DoInitModuleRet: {event: "do_init_module", probeType: kretprobe, fn: "trace_ret_do_init_module"}, + LoadElfPhdrs: {event: "load_elf_phdrs", probeType: kprobe, fn: "trace_load_elf_phdrs"}, + Filldir64: {event: "filldir64", probeType: kprobe, fn: "trace_filldir64"}, + }, + module: module, + }, nil +} + +func (p *probes) Attach(probe Handle) error { + if p.probes[probe] == nil { + return fmt.Errorf("failed to attach probe: doesn't exist") + } + + return p.probes[probe].attach(p.module) +} + +func (p *probes) Detach(probe Handle) error { + if p.probes[probe] == nil { + return fmt.Errorf("failed to detach probe: doesn't exist") + } + + return p.probes[probe].detach() +} + +// ProbeType is an enum that describes the mechanism used to attach the event +// Kprobes are explained here: https://github.com/iovisor/bcc/blob/master/docs/reference_guide.md#1-kp +// Tracepoints are explained here: https://github.com/iovisor/bcc/blob/master/docs/reference_guide.md#3-tracep +// Raw tracepoints are explained here: https://github.com/iovisor/bcc/blob/master/docs/reference_guide.md#7-raw-tracep +type probeType uint8 + +const ( + kprobe = iota + kretprobe + tracepoint + rawTracepoint +) + +func (p *probe) attach(module *bpf.Module) error { + if p.link != nil { + return nil + } + prog, err := module.GetProgram(p.fn) + if err != nil { + return err + } + var link *bpf.BPFLink + switch p.probeType { + case kprobe: + link, err = prog.AttachKprobe(p.event) + case kretprobe: + link, err = prog.AttachKretprobe(p.event) + case tracepoint: + tpEvent := strings.Split(p.event, ":") + if len(tpEvent) != 2 { + err = fmt.Errorf("tracepoint must be in 'category:name' format") + } else { + link, err = prog.AttachTracepoint(p.event, p.event) + } + case rawTracepoint: + tpEvent := strings.Split(p.event, ":")[1] + link, err = prog.AttachRawTracepoint(tpEvent) + } + if err != nil { + return fmt.Errorf("error attaching probe %s: %v", p.event, err) + } + + p.link = link + return nil +} + +func (p *probe) detach() error { + if p.link == nil { + return fmt.Errorf("can't detach unattached probe %s", p.event) + } + + err := p.link.Destroy() + + if err != nil { + return err + } + + p.link = nil + return err +} + +type Handle int32 + +const ( + SysEnter Handle = iota + SysExit + SchedProcessFork + SchedProcessExec + SchedProcessExit + SchedSwitch + DoExit + CapCapable + VfsWrite + VfsWriteRet + VfsWriteV + VfsWriteVRet + SecurityMmapAddr + SecurityMmapFile + SecurityFileMProtect + CommitCreds + SwitchTaskNS + KernelWrite + KernelWriteRet + CgroupAttachTask + CgroupMkdir + CgroupRmdir + SecurityBPRMCheck + SecurityFileOpen + SecurityInodeUnlink + SecurityInodeMknod + SecurityInodeSymlink + SecuritySocketCreate + SecuritySocketListen + SecuritySocketConnect + SecuritySocketAccept + SecuritySocketBind + SecuritySbMount + SecurityBPF + SecurityBPFMap + SecurityKernelReadFile + SecurityKernelPostReadFile + DoSplice + DoSpliceRet + ProcCreate + ARMKprobe + CallUsermodeHelper + DebugfsCreateFile + DebugfsCreateDir + SecurityFileIoctl + DeviceAdd + RegisterChrdev + RegisterChrdevRet + DoInitModule + DoInitModuleRet + LoadElfPhdrs + Filldir64 + SecurityFilePermission +)