diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-20 15:06:02 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-20 15:06:02 +0300 |
| commit | 271af607921ceabc640271c475a66e45b9460d3f (patch) | |
| tree | 6ae443fd372dbeea947cba7bd5851f7936f354b5 | |
| parent | 63184df8d5e30f70011a97d862103fa38d797bb3 (diff) | |
feat: add mount/fs management syscall tracing for c7
| -rw-r--r-- | cmd/ioworkload/scenario_mountfs.go | 91 | ||||
| -rw-r--r-- | cmd/ioworkload/scenario_mountfs_test.go | 30 | ||||
| -rw-r--r-- | cmd/ioworkload/scenarios.go | 1 | ||||
| -rw-r--r-- | integrationtests/mountfs_test.go | 19 | ||||
| -rw-r--r-- | internal/c/generated_tracepoints.c | 97 | ||||
| -rw-r--r-- | internal/c/generated_tracepoints_result.txt | 22 | ||||
| -rw-r--r-- | internal/c/types.h | 13 | ||||
| -rw-r--r-- | internal/event/interface_assertions.go | 3 | ||||
| -rw-r--r-- | internal/eventloop_exit.go | 12 | ||||
| -rw-r--r-- | internal/eventloop_mountfs_test.go | 81 | ||||
| -rw-r--r-- | internal/eventloop_runtime.go | 11 | ||||
| -rw-r--r-- | internal/generate/bpfhandler.go | 18 | ||||
| -rw-r--r-- | internal/generate/classify.go | 53 | ||||
| -rw-r--r-- | internal/generate/classify_test.go | 123 | ||||
| -rw-r--r-- | internal/generate/codegen_test.go | 25 | ||||
| -rw-r--r-- | internal/generate/family.go | 8 | ||||
| -rw-r--r-- | internal/generate/kindregistry.go | 1 | ||||
| -rw-r--r-- | internal/generate/testdata.go | 333 | ||||
| -rw-r--r-- | internal/types/fastdecode.go | 20 | ||||
| -rw-r--r-- | internal/types/fastdecode_test.go | 43 | ||||
| -rw-r--r-- | internal/types/generated_types.go | 74 | ||||
| -rw-r--r-- | internal/types/types_test.go | 27 |
22 files changed, 1048 insertions, 57 deletions
diff --git a/cmd/ioworkload/scenario_mountfs.go b/cmd/ioworkload/scenario_mountfs.go new file mode 100644 index 0000000..4c48ded --- /dev/null +++ b/cmd/ioworkload/scenario_mountfs.go @@ -0,0 +1,91 @@ +package main + +import ( + "fmt" + "os" + "path/filepath" + "runtime" + "syscall" + "unsafe" + + "golang.org/x/sys/unix" +) + +type mountIDReq struct { + Size uint32 + Pad uint32 + MntID uint64 + Param uint64 +} + +func mountfsManagement() error { + dir, cleanup, err := makeTempDir("mountfs-management") + if err != nil { + return err + } + defer cleanup() + + mountPoint := filepath.Join(dir, "mnt") + if err := os.Mkdir(mountPoint, 0o755); err != nil { + return fmt.Errorf("mkdir mountpoint: %w", err) + } + + swapFile := filepath.Join(dir, "swapfile") + if err := os.WriteFile(swapFile, []byte("swap"), 0o600); err != nil { + return fmt.Errorf("write swap file: %w", err) + } + + mountPath := mustCStringPtr(mountPoint) + swapPath := mustCStringPtr(swapFile) + newRoot := mustCStringPtr(mountPoint) + putOld := mustCStringPtr(dir) + tmpfs := mustCStringPtr("tmpfs") + none := mustCStringPtr("none") + atFDCWDInt := int64(unix.AT_FDCWD) + atFDCWD := uintptr(atFDCWDInt) + + // Best-effort coverage: these calls are expected to fail on most hosts + // without CAP_SYS_ADMIN, but still exercise syscall tracing paths. + _, _, _ = syscall.RawSyscall6(unix.SYS_MOUNT, uintptr(unsafe.Pointer(none)), uintptr(unsafe.Pointer(mountPath)), uintptr(unsafe.Pointer(tmpfs)), 0, 0, 0) + _, _, _ = syscall.RawSyscall(unix.SYS_UMOUNT2, uintptr(unsafe.Pointer(mountPath)), 0, 0) + _, _, _ = syscall.RawSyscall(unix.SYS_UMOUNT2, uintptr(unsafe.Pointer(mountPath)), uintptr(unix.MNT_DETACH), 0) + _, _, _ = syscall.RawSyscall6(unix.SYS_MOVE_MOUNT, atFDCWD, uintptr(unsafe.Pointer(mountPath)), atFDCWD, uintptr(unsafe.Pointer(mountPath)), 0, 0) + _, _, _ = syscall.RawSyscall(unix.SYS_FSMOUNT, ^uintptr(0), 0, 0) + _, _, _ = syscall.RawSyscall(unix.SYS_PIVOT_ROOT, uintptr(unsafe.Pointer(newRoot)), uintptr(unsafe.Pointer(putOld)), 0) + _, _, _ = syscall.RawSyscall6(unix.SYS_QUOTACTL, 0, uintptr(unsafe.Pointer(mountPath)), 0, 0, 0, 0) + _, _, _ = syscall.RawSyscall(unix.SYS_SWAPON, uintptr(unsafe.Pointer(swapPath)), 0, 0) + _, _, _ = syscall.RawSyscall(unix.SYS_SWAPOFF, uintptr(unsafe.Pointer(swapPath)), 0, 0) + + req := mountIDReq{Size: uint32(unsafe.Sizeof(mountIDReq{}))} + var statBuf [256]byte + _, _, _ = syscall.RawSyscall6(unix.SYS_STATMOUNT, uintptr(unsafe.Pointer(&req)), uintptr(unsafe.Pointer(&statBuf[0])), uintptr(len(statBuf)), 0, 0, 0) + + var mountIDs [8]uint64 + _, _, _ = syscall.RawSyscall6(unix.SYS_LISTMOUNT, uintptr(unsafe.Pointer(&req)), uintptr(unsafe.Pointer(&mountIDs[0])), uintptr(len(mountIDs)), 0, 0, 0) + + if nr, err := listnsSyscallNr(); err == nil { + var nsIDs [8]uint64 + _, _, _ = syscall.RawSyscall6(nr, uintptr(unsafe.Pointer(&req)), uintptr(unsafe.Pointer(&nsIDs[0])), uintptr(len(nsIDs)), 0, 0, 0) + } + + return nil +} + +func listnsSyscallNr() (uintptr, error) { + return listnsSyscallNrForArch(runtime.GOARCH) +} + +func listnsSyscallNrForArch(arch string) (uintptr, error) { + // __NR_listns was introduced from asm-generic numbering where amd64/arm64 use 470. + switch arch { + case "amd64", "arm64": + return 470, nil + default: + return 0, fmt.Errorf("listns syscall number not defined for GOARCH=%s", arch) + } +} + +func mustCStringPtr(s string) *byte { + p, _ := unix.BytePtrFromString(s) + return p +} diff --git a/cmd/ioworkload/scenario_mountfs_test.go b/cmd/ioworkload/scenario_mountfs_test.go new file mode 100644 index 0000000..c1c317a --- /dev/null +++ b/cmd/ioworkload/scenario_mountfs_test.go @@ -0,0 +1,30 @@ +package main + +import "testing" + +func TestListnsSyscallNrForArch(t *testing.T) { + for _, tc := range []struct { + name string + arch string + want uintptr + wantErr bool + }{ + {name: "amd64", arch: "amd64", want: 470}, + {name: "arm64", arch: "arm64", want: 470}, + {name: "unsupported", arch: "riscv64", wantErr: true}, + } { + got, err := listnsSyscallNrForArch(tc.arch) + if tc.wantErr { + if err == nil { + t.Fatalf("%s: expected error", tc.name) + } + continue + } + if err != nil { + t.Fatalf("%s: unexpected error: %v", tc.name, err) + } + if got != tc.want { + t.Fatalf("%s: got %d, want %d", tc.name, got, tc.want) + } + } +} diff --git a/cmd/ioworkload/scenarios.go b/cmd/ioworkload/scenarios.go index e0827a5..79d4e6d 100644 --- a/cmd/ioworkload/scenarios.go +++ b/cmd/ioworkload/scenarios.go @@ -34,6 +34,7 @@ var scenarios = map[string]func() error{ "pipe2-basic": pipe2Basic, "eventfd-basic": eventfdBasic, "eventfd2-basic": eventfd2Basic, + "mountfs-management": mountfsManagement, "polling-epoll": pollingEpoll, "sleep-syscalls": sleepSyscalls, "family-mixed": familyMixed, diff --git a/integrationtests/mountfs_test.go b/integrationtests/mountfs_test.go new file mode 100644 index 0000000..77f0009 --- /dev/null +++ b/integrationtests/mountfs_test.go @@ -0,0 +1,19 @@ +package integrationtests + +import "testing" + +func TestMountFsManagementSyscalls(t *testing.T) { + runScenario(t, "mountfs-management", []ExpectedEvent{ + {Tracepoint: "enter_mount", MinCount: 1}, + {Tracepoint: "enter_umount", MinCount: 1}, + {Tracepoint: "enter_move_mount", MinCount: 1}, + {Tracepoint: "enter_fsmount", MinCount: 1}, + {Tracepoint: "enter_pivot_root", MinCount: 1}, + {Tracepoint: "enter_quotactl", MinCount: 1}, + {Tracepoint: "enter_statmount", MinCount: 1}, + {Tracepoint: "enter_listmount", MinCount: 1}, + {Tracepoint: "enter_listns", MinCount: 1}, + {Tracepoint: "enter_swapon", MinCount: 1}, + {Tracepoint: "enter_swapoff", MinCount: 1}, + }) +} diff --git a/internal/c/generated_tracepoints.c b/internal/c/generated_tracepoints.c index 55164d5..4db2e8d 100644 --- a/internal/c/generated_tracepoints.c +++ b/internal/c/generated_tracepoints.c @@ -3344,7 +3344,7 @@ int handle_sys_exit_msgrcv(struct syscall_trace_exit *ctx) { return 0; } -/// sys_enter_quotactl is a struct null_event +/// sys_enter_quotactl is a struct path_event SEC("tracepoint/syscalls/sys_enter_quotactl") int handle_sys_enter_quotactl(struct syscall_trace_enter *ctx) { __u32 pid, tid; @@ -3354,15 +3354,17 @@ int handle_sys_enter_quotactl(struct syscall_trace_enter *ctx) { if (!ior_on_syscall_enter(tid, SYS_ENTER_QUOTACTL)) return 0; - struct null_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct null_event), 0); + struct path_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct path_event), 0); if (!ev) return 0; - ev->event_type = ENTER_NULL_EVENT; + ev->event_type = ENTER_PATH_EVENT; ev->trace_id = SYS_ENTER_QUOTACTL; ev->pid = pid; ev->tid = tid; ev->time = bpf_ktime_get_boot_ns(); + __builtin_memset(&(ev->pathname), 0, sizeof(ev->pathname)); + bpf_probe_read_user_str(ev->pathname, sizeof(ev->pathname), (void*)ctx->args[1]); bpf_ringbuf_submit(ev, 0); return 0; @@ -5500,7 +5502,7 @@ int handle_sys_exit_futimesat(struct syscall_trace_exit *ctx) { return 0; } -/// sys_enter_utimes is a struct null_event +/// sys_enter_utimes is a struct path_event SEC("tracepoint/syscalls/sys_enter_utimes") int handle_sys_enter_utimes(struct syscall_trace_enter *ctx) { __u32 pid, tid; @@ -5510,15 +5512,17 @@ int handle_sys_enter_utimes(struct syscall_trace_enter *ctx) { if (!ior_on_syscall_enter(tid, SYS_ENTER_UTIMES)) return 0; - struct null_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct null_event), 0); + struct path_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct path_event), 0); if (!ev) return 0; - ev->event_type = ENTER_NULL_EVENT; + ev->event_type = ENTER_PATH_EVENT; ev->trace_id = SYS_ENTER_UTIMES; ev->pid = pid; ev->tid = tid; ev->time = bpf_ktime_get_boot_ns(); + __builtin_memset(&(ev->pathname), 0, sizeof(ev->pathname)); + bpf_probe_read_user_str(ev->pathname, sizeof(ev->pathname), (void*)ctx->args[0]); bpf_ringbuf_submit(ev, 0); return 0; @@ -5550,7 +5554,7 @@ int handle_sys_exit_utimes(struct syscall_trace_exit *ctx) { return 0; } -/// sys_enter_utime is a struct null_event +/// sys_enter_utime is a struct path_event SEC("tracepoint/syscalls/sys_enter_utime") int handle_sys_enter_utime(struct syscall_trace_enter *ctx) { __u32 pid, tid; @@ -5560,15 +5564,17 @@ int handle_sys_enter_utime(struct syscall_trace_enter *ctx) { if (!ior_on_syscall_enter(tid, SYS_ENTER_UTIME)) return 0; - struct null_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct null_event), 0); + struct path_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct path_event), 0); if (!ev) return 0; - ev->event_type = ENTER_NULL_EVENT; + ev->event_type = ENTER_PATH_EVENT; ev->trace_id = SYS_ENTER_UTIME; ev->pid = pid; ev->tid = tid; ev->time = bpf_ktime_get_boot_ns(); + __builtin_memset(&(ev->pathname), 0, sizeof(ev->pathname)); + bpf_probe_read_user_str(ev->pathname, sizeof(ev->pathname), (void*)ctx->args[0]); bpf_ringbuf_submit(ev, 0); return 0; @@ -6833,7 +6839,7 @@ int handle_sys_exit_fremovexattr(struct syscall_trace_exit *ctx) { return 0; } -/// sys_enter_umount is a struct null_event +/// sys_enter_umount is a struct path_event SEC("tracepoint/syscalls/sys_enter_umount") int handle_sys_enter_umount(struct syscall_trace_enter *ctx) { __u32 pid, tid; @@ -6843,15 +6849,17 @@ int handle_sys_enter_umount(struct syscall_trace_enter *ctx) { if (!ior_on_syscall_enter(tid, SYS_ENTER_UMOUNT)) return 0; - struct null_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct null_event), 0); + struct path_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct path_event), 0); if (!ev) return 0; - ev->event_type = ENTER_NULL_EVENT; + ev->event_type = ENTER_PATH_EVENT; ev->trace_id = SYS_ENTER_UMOUNT; ev->pid = pid; ev->tid = tid; ev->time = bpf_ktime_get_boot_ns(); + __builtin_memset(&(ev->pathname), 0, sizeof(ev->pathname)); + bpf_probe_read_user_str(ev->pathname, sizeof(ev->pathname), (void*)ctx->args[0]); bpf_ringbuf_submit(ev, 0); return 0; @@ -6937,7 +6945,7 @@ int handle_sys_exit_open_tree(struct syscall_trace_exit *ctx) { return 0; } -/// sys_enter_mount is a struct null_event +/// sys_enter_mount is a struct path_event SEC("tracepoint/syscalls/sys_enter_mount") int handle_sys_enter_mount(struct syscall_trace_enter *ctx) { __u32 pid, tid; @@ -6947,15 +6955,17 @@ int handle_sys_enter_mount(struct syscall_trace_enter *ctx) { if (!ior_on_syscall_enter(tid, SYS_ENTER_MOUNT)) return 0; - struct null_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct null_event), 0); + struct path_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct path_event), 0); if (!ev) return 0; - ev->event_type = ENTER_NULL_EVENT; + ev->event_type = ENTER_PATH_EVENT; ev->trace_id = SYS_ENTER_MOUNT; ev->pid = pid; ev->tid = tid; ev->time = bpf_ktime_get_boot_ns(); + __builtin_memset(&(ev->pathname), 0, sizeof(ev->pathname)); + bpf_probe_read_user_str(ev->pathname, sizeof(ev->pathname), (void*)ctx->args[1]); bpf_ringbuf_submit(ev, 0); return 0; @@ -6987,7 +6997,7 @@ int handle_sys_exit_mount(struct syscall_trace_exit *ctx) { return 0; } -/// sys_enter_fsmount is a struct null_event +/// sys_enter_fsmount is a struct eventfd_event SEC("tracepoint/syscalls/sys_enter_fsmount") int handle_sys_enter_fsmount(struct syscall_trace_enter *ctx) { __u32 pid, tid; @@ -6997,21 +7007,25 @@ int handle_sys_enter_fsmount(struct syscall_trace_enter *ctx) { if (!ior_on_syscall_enter(tid, SYS_ENTER_FSMOUNT)) return 0; - struct null_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct null_event), 0); + struct eventfd_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct eventfd_event), 0); if (!ev) return 0; - ev->event_type = ENTER_NULL_EVENT; + ev->event_type = ENTER_EVENTFD_EVENT; ev->trace_id = SYS_ENTER_FSMOUNT; ev->pid = pid; ev->tid = tid; ev->time = bpf_ktime_get_boot_ns(); + __s32 flags = (__s32)ctx->args[1]; + bpf_map_update_elem(&eventfd_flags_map, &tid, &flags, BPF_ANY); + ev->flags = flags; + ev->ret = -1; bpf_ringbuf_submit(ev, 0); return 0; } -/// sys_exit_fsmount is a struct ret_event (UNCLASSIFIED) +/// sys_exit_fsmount is a struct eventfd_event SEC("tracepoint/syscalls/sys_exit_fsmount") int handle_sys_exit_fsmount(struct syscall_trace_exit *ctx) { __u32 pid, tid; @@ -7021,23 +7035,29 @@ int handle_sys_exit_fsmount(struct syscall_trace_exit *ctx) { if (!ior_on_syscall_exit(tid, SYS_EXIT_FSMOUNT, ctx->ret)) return 0; - struct ret_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct ret_event), 0); + struct eventfd_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct eventfd_event), 0); if (!ev) return 0; - ev->event_type = EXIT_RET_EVENT; + ev->event_type = EXIT_EVENTFD_EVENT; ev->trace_id = SYS_EXIT_FSMOUNT; ev->pid = pid; ev->tid = tid; ev->time = bpf_ktime_get_boot_ns(); + __s32 flags = 0; + __s32 *pending = bpf_map_lookup_elem(&eventfd_flags_map, &tid); + if (pending) { + flags = *pending; + bpf_map_delete_elem(&eventfd_flags_map, &tid); + } + ev->flags = flags; ev->ret = ctx->ret; - ev->ret_type = UNCLASSIFIED; bpf_ringbuf_submit(ev, 0); return 0; } -/// sys_enter_move_mount is a struct null_event +/// sys_enter_move_mount is a struct two_fd_event SEC("tracepoint/syscalls/sys_enter_move_mount") int handle_sys_enter_move_mount(struct syscall_trace_enter *ctx) { __u32 pid, tid; @@ -7047,15 +7067,18 @@ int handle_sys_enter_move_mount(struct syscall_trace_enter *ctx) { if (!ior_on_syscall_enter(tid, SYS_ENTER_MOVE_MOUNT)) return 0; - struct null_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct null_event), 0); + struct two_fd_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct two_fd_event), 0); if (!ev) return 0; - ev->event_type = ENTER_NULL_EVENT; + ev->event_type = ENTER_TWO_FD_EVENT; ev->trace_id = SYS_ENTER_MOVE_MOUNT; ev->pid = pid; ev->tid = tid; ev->time = bpf_ktime_get_boot_ns(); + ev->fd_a = (__s32)ctx->args[0]; + ev->fd_b = (__s32)ctx->args[2]; + ev->extra = (__u64)ctx->args[4]; bpf_ringbuf_submit(ev, 0); return 0; @@ -7087,7 +7110,7 @@ int handle_sys_exit_move_mount(struct syscall_trace_exit *ctx) { return 0; } -/// sys_enter_pivot_root is a struct null_event +/// sys_enter_pivot_root is a struct path_event SEC("tracepoint/syscalls/sys_enter_pivot_root") int handle_sys_enter_pivot_root(struct syscall_trace_enter *ctx) { __u32 pid, tid; @@ -7097,15 +7120,17 @@ int handle_sys_enter_pivot_root(struct syscall_trace_enter *ctx) { if (!ior_on_syscall_enter(tid, SYS_ENTER_PIVOT_ROOT)) return 0; - struct null_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct null_event), 0); + struct path_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct path_event), 0); if (!ev) return 0; - ev->event_type = ENTER_NULL_EVENT; + ev->event_type = ENTER_PATH_EVENT; ev->trace_id = SYS_ENTER_PIVOT_ROOT; ev->pid = pid; ev->tid = tid; ev->time = bpf_ktime_get_boot_ns(); + __builtin_memset(&(ev->pathname), 0, sizeof(ev->pathname)); + bpf_probe_read_user_str(ev->pathname, sizeof(ev->pathname), (void*)ctx->args[0]); bpf_ringbuf_submit(ev, 0); return 0; @@ -11650,7 +11675,7 @@ int handle_sys_exit_get_mempolicy(struct syscall_trace_exit *ctx) { return 0; } -/// sys_enter_swapoff is a struct null_event +/// sys_enter_swapoff is a struct path_event SEC("tracepoint/syscalls/sys_enter_swapoff") int handle_sys_enter_swapoff(struct syscall_trace_enter *ctx) { __u32 pid, tid; @@ -11660,15 +11685,17 @@ int handle_sys_enter_swapoff(struct syscall_trace_enter *ctx) { if (!ior_on_syscall_enter(tid, SYS_ENTER_SWAPOFF)) return 0; - struct null_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct null_event), 0); + struct path_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct path_event), 0); if (!ev) return 0; - ev->event_type = ENTER_NULL_EVENT; + ev->event_type = ENTER_PATH_EVENT; ev->trace_id = SYS_ENTER_SWAPOFF; ev->pid = pid; ev->tid = tid; ev->time = bpf_ktime_get_boot_ns(); + __builtin_memset(&(ev->pathname), 0, sizeof(ev->pathname)); + bpf_probe_read_user_str(ev->pathname, sizeof(ev->pathname), (void*)ctx->args[0]); bpf_ringbuf_submit(ev, 0); return 0; @@ -11700,7 +11727,7 @@ int handle_sys_exit_swapoff(struct syscall_trace_exit *ctx) { return 0; } -/// sys_enter_swapon is a struct null_event +/// sys_enter_swapon is a struct path_event SEC("tracepoint/syscalls/sys_enter_swapon") int handle_sys_enter_swapon(struct syscall_trace_enter *ctx) { __u32 pid, tid; @@ -11710,15 +11737,17 @@ int handle_sys_enter_swapon(struct syscall_trace_enter *ctx) { if (!ior_on_syscall_enter(tid, SYS_ENTER_SWAPON)) return 0; - struct null_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct null_event), 0); + struct path_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct path_event), 0); if (!ev) return 0; - ev->event_type = ENTER_NULL_EVENT; + ev->event_type = ENTER_PATH_EVENT; ev->trace_id = SYS_ENTER_SWAPON; ev->pid = pid; ev->tid = tid; ev->time = bpf_ktime_get_boot_ns(); + __builtin_memset(&(ev->pathname), 0, sizeof(ev->pathname)); + bpf_probe_read_user_str(ev->pathname, sizeof(ev->pathname), (void*)ctx->args[0]); bpf_ringbuf_submit(ev, 0); return 0; diff --git a/internal/c/generated_tracepoints_result.txt b/internal/c/generated_tracepoints_result.txt index 6319861..3a5282e 100644 --- a/internal/c/generated_tracepoints_result.txt +++ b/internal/c/generated_tracepoints_result.txt @@ -68,7 +68,7 @@ sys_enter_fork is a struct null_event sys_enter_fremovexattr is a struct fd_event sys_enter_fsconfig is a struct fd_event sys_enter_fsetxattr is a struct fd_event -sys_enter_fsmount is a struct null_event +sys_enter_fsmount is a struct eventfd_event sys_enter_fsopen is a struct null_event sys_enter_fspick is a struct path_event sys_enter_fstatfs is a struct fd_event @@ -170,9 +170,9 @@ sys_enter_mlock2 is a struct null_event sys_enter_mlockall is a struct null_event sys_enter_mmap is a struct fd_event sys_enter_modify_ldt is a struct null_event -sys_enter_mount is a struct null_event +sys_enter_mount is a struct path_event sys_enter_mount_setattr is a struct path_event -sys_enter_move_mount is a struct null_event +sys_enter_move_mount is a struct two_fd_event sys_enter_move_pages is a struct null_event sys_enter_mprotect is a struct null_event sys_enter_mq_getsetattr is a struct null_event @@ -212,7 +212,7 @@ sys_enter_pidfd_open is a struct null_event sys_enter_pidfd_send_signal is a struct null_event sys_enter_pipe is a struct pipe_event sys_enter_pipe2 is a struct pipe_event -sys_enter_pivot_root is a struct null_event +sys_enter_pivot_root is a struct path_event sys_enter_pkey_alloc is a struct null_event sys_enter_pkey_free is a struct null_event sys_enter_pkey_mprotect is a struct null_event @@ -232,7 +232,7 @@ sys_enter_ptrace is a struct null_event sys_enter_pwrite64 is a struct fd_event sys_enter_pwritev is a struct fd_event sys_enter_pwritev2 is a struct fd_event -sys_enter_quotactl is a struct null_event +sys_enter_quotactl is a struct path_event sys_enter_quotactl_fd is a struct fd_event sys_enter_read is a struct fd_event sys_enter_readahead is a struct fd_event @@ -322,8 +322,8 @@ sys_enter_splice is a struct null_event sys_enter_statfs is a struct path_event sys_enter_statmount is a struct null_event sys_enter_statx is a struct path_event -sys_enter_swapoff is a struct null_event -sys_enter_swapon is a struct null_event +sys_enter_swapoff is a struct path_event +sys_enter_swapon is a struct path_event sys_enter_symlink is a struct name_event sys_enter_symlinkat is a struct name_event sys_enter_sync is a struct null_event @@ -347,7 +347,7 @@ sys_enter_times is a struct null_event sys_enter_tkill is a struct null_event sys_enter_truncate is a struct path_event sys_enter_umask is a struct null_event -sys_enter_umount is a struct null_event +sys_enter_umount is a struct path_event sys_enter_unlink is a struct path_event sys_enter_unlinkat is a struct path_event sys_enter_unshare is a struct null_event @@ -355,9 +355,9 @@ sys_enter_uprobe is a struct null_event sys_enter_uretprobe is a struct null_event sys_enter_userfaultfd is a struct null_event sys_enter_ustat is a struct null_event -sys_enter_utime is a struct null_event +sys_enter_utime is a struct path_event sys_enter_utimensat is a struct path_event -sys_enter_utimes is a struct null_event +sys_enter_utimes is a struct path_event sys_enter_vfork is a struct null_event sys_enter_vhangup is a struct null_event sys_enter_vmsplice is a struct fd_event @@ -435,7 +435,7 @@ sys_exit_fork is a struct ret_event (UNCLASSIFIED) sys_exit_fremovexattr is a struct ret_event (UNCLASSIFIED) sys_exit_fsconfig is a struct ret_event (UNCLASSIFIED) sys_exit_fsetxattr is a struct ret_event (UNCLASSIFIED) -sys_exit_fsmount is a struct ret_event (UNCLASSIFIED) +sys_exit_fsmount is a struct eventfd_event sys_exit_fsopen is a struct ret_event (UNCLASSIFIED) sys_exit_fspick is a struct ret_event (UNCLASSIFIED) sys_exit_fstatfs is a struct ret_event (UNCLASSIFIED) diff --git a/internal/c/types.h b/internal/c/types.h index 6c22b90..6b4785e 100644 --- a/internal/c/types.h +++ b/internal/c/types.h @@ -39,6 +39,8 @@ #define EXIT_MEM_EVENT 34 #define ENTER_SLEEP_EVENT 35 #define EXIT_SLEEP_EVENT 36 +#define ENTER_TWO_FD_EVENT 37 +#define EXIT_TWO_FD_EVENT 38 #define UNCLASSIFIED 0 #define READ_CLASSIFIED 1 @@ -232,3 +234,14 @@ struct sleep_event { __u32 tid; __s64 requested_ns; }; + +struct two_fd_event { + __u32 event_type; + __u32 trace_id; + __u64 time; + __u32 pid; + __u32 tid; + __s32 fd_a; + __s32 fd_b; + __u64 extra; +}; diff --git a/internal/event/interface_assertions.go b/internal/event/interface_assertions.go index ebe1d9f..2e1f958 100644 --- a/internal/event/interface_assertions.go +++ b/internal/event/interface_assertions.go @@ -68,4 +68,7 @@ var ( // *types.SleepEvent carries requested sleep duration metadata. _ Event = (*types.SleepEvent)(nil) + + // *types.TwoFdEvent carries operations that include two fd inputs. + _ Event = (*types.TwoFdEvent)(nil) ) diff --git a/internal/eventloop_exit.go b/internal/eventloop_exit.go index 7a69774..faaa9e1 100644 --- a/internal/eventloop_exit.go +++ b/internal/eventloop_exit.go @@ -40,6 +40,8 @@ func (e *eventLoop) handleTracepointExit(ep *event.Pair) bool { return e.handleEpollCtlExit(ep, ev) case *types.PollEvent: return e.handlePollExit(ep, ev) + case *types.TwoFdEvent: + return e.handleTwoFdExit(ep, ev) case *types.MemEvent: return e.handleMemExit(ep, ev) case *types.SleepEvent: @@ -410,6 +412,16 @@ func (e *eventLoop) handlePollExit(ep *event.Pair, pollEv *types.PollEvent) bool return true } +func (e *eventLoop) handleTwoFdExit(ep *event.Pair, twoFdEv *types.TwoFdEvent) bool { + ep.File = e.fdState().resolve(twoFdEv.FdA, twoFdEv.Pid) + ep.Comm = e.comm(twoFdEv.GetTid()) + if !e.Filter().MatchPair(ep) { + ep.Recycle() + return false + } + return true +} + func (e *eventLoop) handleMemExit(ep *event.Pair, memEv *types.MemEvent) bool { ep.Comm = e.comm(memEv.GetTid()) if !e.Filter().MatchPair(ep) { diff --git a/internal/eventloop_mountfs_test.go b/internal/eventloop_mountfs_test.go new file mode 100644 index 0000000..05c11d9 --- /dev/null +++ b/internal/eventloop_mountfs_test.go @@ -0,0 +1,81 @@ +package internal + +import ( + "testing" + + "ior/internal/event" + "ior/internal/file" + "ior/internal/globalfilter" + "ior/internal/types" +) + +func TestHandleTwoFdExitUsesFirstDescriptor(t *testing.T) { + el := mustNewEventLoop(t, eventLoopConfig{}) + el.fdState().set(81, file.NewFd(81, "/proc/self/fd/81", -1)) + + enter := &types.TwoFdEvent{ + EventType: types.ENTER_TWO_FD_EVENT, + TraceId: types.SYS_ENTER_MOVE_MOUNT, + Time: 100, + Pid: 70, + Tid: 71, + FdA: 81, + FdB: 82, + Extra: 0x2, + } + exit := &types.RetEvent{ + EventType: types.EXIT_RET_EVENT, + TraceId: types.SYS_EXIT_MOVE_MOUNT, + Time: 200, + Ret: 0, + Pid: 70, + Tid: 71, + } + ep := &event.Pair{EnterEv: enter, ExitEv: exit} + + if ok := el.handleTwoFdExit(ep, enter); !ok { + t.Fatal("handleTwoFdExit returned false") + } + if ep.File == nil || ep.File.FD() != 81 { + t.Fatalf("expected resolved descriptor 81, got file=%v", ep.File) + } +} + +func TestHandleTwoFdExitAppliesPairFilter(t *testing.T) { + el := mustNewEventLoop(t, eventLoopConfig{ + filter: globalfilter.Filter{ + Syscall: &globalfilter.StringFilter{Pattern: "openat"}, + }, + }) + + enter := &types.TwoFdEvent{ + EventType: types.ENTER_TWO_FD_EVENT, + TraceId: types.SYS_ENTER_MOVE_MOUNT, + Time: 100, + Pid: 72, + Tid: 73, + FdA: 91, + FdB: 92, + Extra: 0, + } + exit := &types.RetEvent{ + EventType: types.EXIT_RET_EVENT, + TraceId: types.SYS_EXIT_MOVE_MOUNT, + Time: 200, + Ret: 0, + Pid: 72, + Tid: 73, + } + ep := &event.Pair{EnterEv: enter, ExitEv: exit} + + if ok := el.handleTwoFdExit(ep, enter); ok { + t.Fatal("handleTwoFdExit should reject pair due to filter mismatch") + } +} + +func TestInitRawHandlersRegistersTwoFdEvent(t *testing.T) { + el := mustNewEventLoop(t, eventLoopConfig{}) + if _, ok := el.rawHandlers[types.ENTER_TWO_FD_EVENT]; !ok { + t.Fatal("ENTER_TWO_FD_EVENT handler is not registered") + } +} diff --git a/internal/eventloop_runtime.go b/internal/eventloop_runtime.go index 8ef3abf..9a818e3 100644 --- a/internal/eventloop_runtime.go +++ b/internal/eventloop_runtime.go @@ -247,6 +247,7 @@ func (e *eventLoop) initRawHandlers() { e.registerSocketHandlers() e.registerIPCHandlers() e.registerPollingHandlers() + e.registerTwoFdHandlers() e.registerMemoryHandlers() e.registerSleepHandlers() } @@ -451,6 +452,16 @@ func (e *eventLoop) registerPollingHandlers() { } } +func (e *eventLoop) registerTwoFdHandlers() { + e.rawHandlers[types.ENTER_TWO_FD_EVENT] = func(raw []byte, _ chan<- *event.Pair) { + twoFdEv, ok := decodeRawEvent(e, types.ENTER_TWO_FD_EVENT, raw, types.NewTwoFdEventFast) + if !ok { + return + } + e.tracepointEntered(twoFdEv) + } +} + func (e *eventLoop) registerMemoryHandlers() { e.rawHandlers[types.ENTER_MEM_EVENT] = func(raw []byte, _ chan<- *event.Pair) { memEv, ok := decodeRawEvent(e, types.ENTER_MEM_EVENT, raw, types.NewMemEventFast) diff --git a/internal/generate/bpfhandler.go b/internal/generate/bpfhandler.go index 5c42464..afdb83e 100644 --- a/internal/generate/bpfhandler.go +++ b/internal/generate/bpfhandler.go @@ -93,6 +93,8 @@ func generateExtra(tp GeneratedTracepoint, isEnter bool) string { return generateExtraEventfd(f, isEnter) case KindEpollCtl: return generateExtraEpollCtl() + case KindTwoFd: + return generateExtraTwoFd(f.Name) case KindPoll: return generateExtraPoll(f.Name) case KindMem: @@ -207,7 +209,12 @@ func generateExtraPipe(f *Format, isEnter bool) string { func generateExtraEventfd(f *Format, isEnter bool) string { if isEnter { flagsExpr := "0" - if f.Name == "sys_enter_eventfd2" { + switch f.Name { + case "sys_enter_eventfd2": + flagsExpr = "(__s32)ctx->args[1]" + case "sys_enter_fsmount": + flagsExpr = "(__s32)ctx->args[1]" + case "sys_enter_fsopen": flagsExpr = "(__s32)ctx->args[1]" } return " __s32 flags = " + flagsExpr + ";\n bpf_map_update_elem(&eventfd_flags_map, &tid, &flags, BPF_ANY);\n ev->flags = flags;\n ev->ret = -1;\n" @@ -219,6 +226,15 @@ func generateExtraEpollCtl() string { return " ev->epfd = (__s32)ctx->args[0];\n ev->op = (__s32)ctx->args[1];\n ev->fd = (__s32)ctx->args[2];\n ev->events = 0;\n if (ctx->args[3] != 0) {\n __u32 user_events = 0;\n if (bpf_probe_read_user(&user_events, sizeof(user_events), (void *)ctx->args[3]) == 0) {\n ev->events = user_events;\n }\n }\n" } +func generateExtraTwoFd(name string) string { + switch name { + case "sys_enter_move_mount": + return " ev->fd_a = (__s32)ctx->args[0];\n ev->fd_b = (__s32)ctx->args[2];\n ev->extra = (__u64)ctx->args[4];\n" + default: + return " ev->fd_a = (__s32)ctx->args[0];\n ev->fd_b = (__s32)ctx->args[1];\n ev->extra = (__u64)ctx->args[2];\n" + } +} + func generateExtraPoll(name string) string { switch name { case "sys_enter_poll": diff --git a/internal/generate/classify.go b/internal/generate/classify.go index 2bb2b81..2b750cf 100644 --- a/internal/generate/classify.go +++ b/internal/generate/classify.go @@ -21,6 +21,7 @@ const ( KindPipe KindEventfd KindEpollCtl + KindTwoFd KindPoll KindMem KindSleep @@ -142,6 +143,18 @@ func classifyNameOnly(name string) (ClassificationResult, bool) { return ClassificationResult{Kind: KindFd}, true case "sys_enter_epoll_ctl": return ClassificationResult{Kind: KindEpollCtl}, true + case "sys_enter_move_mount": + return ClassificationResult{Kind: KindTwoFd}, true + case "sys_enter_fsmount": + return ClassificationResult{Kind: KindEventfd}, true + case "sys_exit_fsmount": + return ClassificationResult{Kind: KindEventfd}, true + case "sys_enter_statmount": + return ClassificationResult{Kind: KindNull}, true + case "sys_enter_listmount": + return ClassificationResult{Kind: KindNull}, true + case "sys_enter_listns": + return ClassificationResult{Kind: KindNull}, true case "sys_enter_poll": return ClassificationResult{Kind: KindPoll}, true case "sys_enter_ppoll": @@ -182,18 +195,42 @@ func classifyNameAndField(name, fieldType, fieldName string) (ClassificationResu return ClassificationResult{Kind: KindDup3}, true } case "sys_enter_name_to_handle_at": - if fieldType == "const char *" && fieldName == "name" { + if isCStringPtrType(fieldType) && fieldName == "name" { return ClassificationResult{Kind: KindPathname, PathnameField: "name"}, true } case "sys_enter_copy_file_range": if isFdType(fieldType) && fieldName == "fd_in" { return ClassificationResult{Kind: KindFd}, true } + case "sys_enter_mount": + if isCStringPtrType(fieldType) && fieldName == "dir_name" { + return ClassificationResult{Kind: KindPathname, PathnameField: "dir_name"}, true + } + case "sys_enter_umount": + if isCStringPtrType(fieldType) && fieldName == "name" { + return ClassificationResult{Kind: KindPathname, PathnameField: "name"}, true + } + case "sys_enter_pivot_root": + if isCStringPtrType(fieldType) && fieldName == "new_root" { + return ClassificationResult{Kind: KindPathname, PathnameField: "new_root"}, true + } + case "sys_enter_quotactl": + if isCStringPtrType(fieldType) && fieldName == "special" { + return ClassificationResult{Kind: KindPathname, PathnameField: "special"}, true + } + case "sys_enter_swapon": + if isCStringPtrType(fieldType) && fieldName == "specialfile" { + return ClassificationResult{Kind: KindPathname, PathnameField: "specialfile"}, true + } + case "sys_enter_swapoff": + if isCStringPtrType(fieldType) && fieldName == "specialfile" { + return ClassificationResult{Kind: KindPathname, PathnameField: "specialfile"}, true + } } if strings.HasPrefix(name, "sys_enter") && strings.Contains(name, "open") && - fieldType == "const char *" && fieldName == "filename" { + isCStringPtrType(fieldType) && fieldName == "filename" { return ClassificationResult{Kind: KindOpen}, true } @@ -204,13 +241,13 @@ func classifyByField(fieldType, fieldName string) (ClassificationResult, bool) { switch { case fieldName == "fd" && isFdType(fieldType): return ClassificationResult{Kind: KindFd}, true - case fieldType == "const char *" && fieldName == "newname": + case isCStringPtrType(fieldType) && fieldName == "newname": return ClassificationResult{Kind: KindName}, true - case fieldType == "const char *" && fieldName == "pathname": + case isCStringPtrType(fieldType) && fieldName == "pathname": return ClassificationResult{Kind: KindPathname, PathnameField: "pathname"}, true - case fieldType == "const char *" && fieldName == "path": + case isCStringPtrType(fieldType) && fieldName == "path": return ClassificationResult{Kind: KindPathname, PathnameField: "path"}, true - case fieldType == "const char *" && fieldName == "filename": + case isCStringPtrType(fieldType) && fieldName == "filename": return ClassificationResult{Kind: KindPathname, PathnameField: "filename"}, true case fieldType == "long" && fieldName == "ret": return ClassificationResult{Kind: KindRet}, true @@ -222,6 +259,10 @@ func isFdType(t string) bool { return t == "unsigned int" || t == "unsigned long" || t == "int" } +func isCStringPtrType(t string) bool { + return t == "const char *" || t == "char *" +} + // ClassifyRet returns the RetClassification for a syscall exit name. func ClassifyRet(name string) RetClassification { syscall := strings.ToLower(strings.TrimPrefix(name, "sys_exit_")) diff --git a/internal/generate/classify_test.go b/internal/generate/classify_test.go index daf008a..b853994 100644 --- a/internal/generate/classify_test.go +++ b/internal/generate/classify_test.go @@ -453,6 +453,108 @@ func TestClassifyClockNanosleep(t *testing.T) { } } +func TestClassifyMount(t *testing.T) { + r := classifyFromData(t, FormatMount) + if r.Kind != KindPathname { + t.Errorf("mount: got kind %d, want KindPathname", r.Kind) + } + if r.PathnameField != "dir_name" { + t.Errorf("mount: PathnameField = %q, want dir_name", r.PathnameField) + } +} + +func TestClassifyUmount(t *testing.T) { + r := classifyFromData(t, FormatUmount) + if r.Kind != KindPathname { + t.Errorf("umount: got kind %d, want KindPathname", r.Kind) + } + if r.PathnameField != "name" { + t.Errorf("umount: PathnameField = %q, want name", r.PathnameField) + } +} + +func TestClassifyMoveMount(t *testing.T) { + r := classifyFromData(t, FormatMoveMount) + if r.Kind != KindTwoFd { + t.Errorf("move_mount: got kind %d, want KindTwoFd", r.Kind) + } +} + +func TestClassifyFsmount(t *testing.T) { + r := classifyFromData(t, FormatFsmount) + if r.Kind != KindEventfd { + t.Errorf("fsmount: got kind %d, want KindEventfd", r.Kind) + } +} + +func TestClassifyExitFsmount(t *testing.T) { + r := classifyFromData(t, FormatExitFsmount) + if r.Kind != KindEventfd { + t.Errorf("exit_fsmount: got kind %d, want KindEventfd", r.Kind) + } +} + +func TestClassifyPivotRoot(t *testing.T) { + r := classifyFromData(t, FormatPivotRoot) + if r.Kind != KindPathname { + t.Errorf("pivot_root: got kind %d, want KindPathname", r.Kind) + } + if r.PathnameField != "new_root" { + t.Errorf("pivot_root: PathnameField = %q, want new_root", r.PathnameField) + } +} + +func TestClassifyQuotactl(t *testing.T) { + r := classifyFromData(t, FormatQuotactl) + if r.Kind != KindPathname { + t.Errorf("quotactl: got kind %d, want KindPathname", r.Kind) + } + if r.PathnameField != "special" { + t.Errorf("quotactl: PathnameField = %q, want special", r.PathnameField) + } +} + +func TestClassifyStatmount(t *testing.T) { + r := classifyFromData(t, FormatStatmount) + if r.Kind != KindNull { + t.Errorf("statmount: got kind %d, want KindNull", r.Kind) + } +} + +func TestClassifyListmount(t *testing.T) { + r := classifyFromData(t, FormatListmount) + if r.Kind != KindNull { + t.Errorf("listmount: got kind %d, want KindNull", r.Kind) + } +} + +func TestClassifyListns(t *testing.T) { + r := classifyFromData(t, FormatListns) + if r.Kind != KindNull { + t.Errorf("listns: got kind %d, want KindNull", r.Kind) + } +} + +func TestClassifySwapon(t *testing.T) { + r := classifyFromData(t, FormatSwapon) + if r.Kind != KindPathname { + t.Errorf("swapon: got kind %d, want KindPathname", r.Kind) + } + if r.PathnameField != "specialfile" { + t.Errorf("swapon: PathnameField = %q, want specialfile", r.PathnameField) + } +} + +func TestClassifySwapoff(t *testing.T) { + r := classifyFromData(t, FormatSwapoff) + if r.Kind != KindPathname { + t.Errorf("swapoff: got kind %d, want KindPathname", r.Kind) + } + if r.PathnameField != "specialfile" { + t.Errorf("swapoff: PathnameField = %q, want specialfile", r.PathnameField) + } +} + func TestClassifyKillRequiresGenerationFallback(t *testing.T) { r := classifyFromData(t, FormatKill) if r.Kind != KindNone { @@ -509,6 +611,17 @@ func TestClassifySyscallPairAccepted(t *testing.T) { {"mremap", FormatMremap, FormatExitMremap, KindMem}, {"nanosleep", FormatNanosleep, FormatExitNanosleep, KindSleep}, {"clock_nanosleep", FormatClockNanosleep, FormatExitClockNanosleep, KindSleep}, + {"mount", FormatMount, FormatExitMount, KindPathname}, + {"umount", FormatUmount, FormatExitUmount, KindPathname}, + {"move_mount", FormatMoveMount, FormatExitMoveMount, KindTwoFd}, + {"fsmount", FormatFsmount, FormatExitFsmount, KindEventfd}, + {"pivot_root", FormatPivotRoot, FormatExitPivotRoot, KindPathname}, + {"quotactl", FormatQuotactl, FormatExitQuotactl, KindPathname}, + {"statmount", FormatStatmount, FormatExitStatmount, KindNull}, + {"listmount", FormatListmount, FormatExitListmount, KindNull}, + {"listns", FormatListns, FormatExitListns, KindNull}, + {"swapon", FormatSwapon, FormatExitSwapon, KindPathname}, + {"swapoff", FormatSwapoff, FormatExitSwapoff, KindPathname}, {"kill", FormatKill, FormatExitKill, KindNull}, } @@ -550,6 +663,16 @@ func TestClassifySyscallPairEmitsAllFamilies(t *testing.T) { {"mremap", FormatMremap, FormatExitMremap, FamilyMemory}, {"nanosleep", FormatNanosleep, FormatExitNanosleep, FamilyTime}, {"clock_nanosleep", FormatClockNanosleep, FormatExitClockNanosleep, FamilyTime}, + {"mount", FormatMount, FormatExitMount, FamilyFS}, + {"umount", FormatUmount, FormatExitUmount, FamilyFS}, + {"move_mount", FormatMoveMount, FormatExitMoveMount, FamilyFS}, + {"fsmount", FormatFsmount, FormatExitFsmount, FamilyFS}, + {"quotactl", FormatQuotactl, FormatExitQuotactl, FamilyFS}, + {"statmount", FormatStatmount, FormatExitStatmount, FamilyFS}, + {"listmount", FormatListmount, FormatExitListmount, FamilyFS}, + {"listns", FormatListns, FormatExitListns, FamilyFS}, + {"swapon", FormatSwapon, FormatExitSwapon, FamilyFS}, + {"swapoff", FormatSwapoff, FormatExitSwapoff, FamilyFS}, {"kill", FormatKill, FormatExitKill, FamilySignals}, } diff --git a/internal/generate/codegen_test.go b/internal/generate/codegen_test.go index bc4ec3a..ac04eba 100644 --- a/internal/generate/codegen_test.go +++ b/internal/generate/codegen_test.go @@ -281,6 +281,27 @@ func TestGenerateEpollCtlHandler(t *testing.T) { requireContains(t, output, "ev->event_type = EXIT_RET_EVENT;") } +func TestGenerateMoveMountHandler(t *testing.T) { + output := generateFromPair(t, FormatMoveMount, FormatExitMoveMount) + + requireContains(t, output, "struct two_fd_event *ev") + requireContains(t, output, "ev->event_type = ENTER_TWO_FD_EVENT;") + requireContains(t, output, "ev->fd_a = (__s32)ctx->args[0];") + requireContains(t, output, "ev->fd_b = (__s32)ctx->args[2];") + requireContains(t, output, "ev->extra = (__u64)ctx->args[4];") + requireContains(t, output, "ev->event_type = EXIT_RET_EVENT;") +} + +func TestGenerateFsmountHandler(t *testing.T) { + output := generateFromPair(t, FormatFsmount, FormatExitFsmount) + + requireContains(t, output, "struct eventfd_event *ev") + requireContains(t, output, "ev->event_type = ENTER_EVENTFD_EVENT;") + requireContains(t, output, "flags = (__s32)ctx->args[1];") + requireContains(t, output, "ev->event_type = EXIT_EVENTFD_EVENT;") + requireContains(t, output, "ev->ret = ctx->ret;") +} + func TestGenerateEpollWaitHandlerUsesEpollFd(t *testing.T) { output := generateFromPair(t, FormatEpollWait, FormatExitEpollWait) @@ -442,6 +463,7 @@ func TestGenerateAllEventTypes(t *testing.T) { {KindPipe, "ENTER_PIPE_EVENT", "EXIT_PIPE_EVENT"}, {KindEventfd, "ENTER_EVENTFD_EVENT", "EXIT_EVENTFD_EVENT"}, {KindEpollCtl, "ENTER_EPOLL_CTL_EVENT", "EXIT_EPOLL_CTL_EVENT"}, + {KindTwoFd, "ENTER_TWO_FD_EVENT", "EXIT_TWO_FD_EVENT"}, {KindPoll, "ENTER_POLL_EVENT", "EXIT_POLL_EVENT"}, {KindMem, "ENTER_MEM_EVENT", "EXIT_MEM_EVENT"}, {KindSleep, "ENTER_SLEEP_EVENT", "EXIT_SLEEP_EVENT"}, @@ -477,6 +499,7 @@ func TestEventStructNames(t *testing.T) { {KindPipe, "pipe_event"}, {KindEventfd, "eventfd_event"}, {KindEpollCtl, "epoll_ctl_event"}, + {KindTwoFd, "two_fd_event"}, {KindPoll, "poll_event"}, {KindMem, "mem_event"}, {KindSleep, "sleep_event"}, @@ -498,7 +521,7 @@ func TestEnterReject(t *testing.T) { t.Error("KindNone should be enter-rejected") } - accepted := []TracepointKind{KindFd, KindOpen, KindPathname, KindName, KindFcntl, KindNull, KindDup3, KindOpenByHandleAt, KindSocket, KindSocketpair, KindAccept, KindPipe, KindEventfd, KindEpollCtl, KindPoll, KindMem, KindSleep} + accepted := []TracepointKind{KindFd, KindOpen, KindPathname, KindName, KindFcntl, KindNull, KindDup3, KindOpenByHandleAt, KindSocket, KindSocketpair, KindAccept, KindPipe, KindEventfd, KindEpollCtl, KindTwoFd, KindPoll, KindMem, KindSleep} for _, k := range accepted { if isEnterRejected(k) { t.Errorf("kind %d should NOT be enter-rejected", k) diff --git a/internal/generate/family.go b/internal/generate/family.go index f39b13f..ff75b5a 100644 --- a/internal/generate/family.go +++ b/internal/generate/family.go @@ -152,15 +152,17 @@ var fsSyscalls = map[string]struct{}{ "fsmount": {}, "fsopen": {}, "fspick": {}, "fsync": {}, "ftruncate": {}, "futimesat": {}, "getcwd": {}, "getdents": {}, "getdents64": {}, "ioctl": {}, "link": {}, "linkat": {}, "lseek": {}, "mkdir": {}, "mkdirat": {}, - "mknod": {}, "mknodat": {}, "mount": {}, "mount_setattr": {}, "move_mount": {}, + "listmount": {}, "listns": {}, "mknod": {}, "mknodat": {}, "mount": {}, + "mount_setattr": {}, "move_mount": {}, "msync": {}, "name_to_handle_at": {}, "newfstat": {}, "newfstatat": {}, "newlstat": {}, "newstat": {}, "open": {}, "open_by_handle_at": {}, "open_tree": {}, "open_tree_attr": {}, "openat": {}, "openat2": {}, "quotactl": {}, "quotactl_fd": {}, "read": {}, "readahead": {}, "readlink": {}, "readlinkat": {}, "readv": {}, "rename": {}, "renameat": {}, "renameat2": {}, "rmdir": {}, - "statfs": {}, "sync": {}, "sync_file_range": {}, "syncfs": {}, "symlink": {}, - "symlinkat": {}, "truncate": {}, "umount2": {}, "unlink": {}, "unlinkat": {}, + "statfs": {}, "statmount": {}, "swapoff": {}, "swapon": {}, "sync": {}, + "sync_file_range": {}, "syncfs": {}, "symlink": {}, "symlinkat": {}, + "truncate": {}, "umount": {}, "umount2": {}, "unlink": {}, "unlinkat": {}, "utimensat": {}, "write": {}, "writev": {}, "pread64": {}, "preadv": {}, "preadv2": {}, "pwrite64": {}, "pwritev": {}, "pwritev2": {}, } diff --git a/internal/generate/kindregistry.go b/internal/generate/kindregistry.go index 96d98d8..2775f38 100644 --- a/internal/generate/kindregistry.go +++ b/internal/generate/kindregistry.go @@ -31,6 +31,7 @@ var kindRegistry = map[TracepointKind]kindMeta{ KindPipe: {structName: "pipe_event", enterAccepted: true}, KindEventfd: {structName: "eventfd_event", enterAccepted: true}, KindEpollCtl: {structName: "epoll_ctl_event", enterAccepted: true}, + KindTwoFd: {structName: "two_fd_event", enterAccepted: true}, KindPoll: {structName: "poll_event", enterAccepted: true}, KindMem: {structName: "mem_event", enterAccepted: true}, KindSleep: {structName: "sleep_event", enterAccepted: true}, diff --git a/internal/generate/testdata.go b/internal/generate/testdata.go index d88a1b9..2bc041e 100644 --- a/internal/generate/testdata.go +++ b/internal/generate/testdata.go @@ -733,6 +733,339 @@ format: print fmt: "pathname: 0x%08lx, mode: 0x%08lx", ((unsigned long)(REC->pathname)), ((unsigned long)(REC->mode)) ` +const FormatMount = `name: sys_enter_mount +ID: 949 +format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:int __syscall_nr; offset:8; size:4; signed:1; + field:const char * dev_name; offset:16; size:8; signed:0; + field:const char * dir_name; offset:24; size:8; signed:0; + field:const char * type; offset:32; size:8; signed:0; + field:unsigned long flags; offset:40; size:8; signed:0; + field:void * data; offset:48; size:8; signed:0; + +print fmt: "dev_name: 0x%08lx, dir_name: 0x%08lx, type: 0x%08lx, flags: 0x%08lx, data: 0x%08lx", ((unsigned long)(REC->dev_name)), ((unsigned long)(REC->dir_name)), ((unsigned long)(REC->type)), ((unsigned long)(REC->flags)), ((unsigned long)(REC->data)) +` + +const FormatExitMount = `name: sys_exit_mount +ID: 948 +format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:int __syscall_nr; offset:8; size:4; signed:1; + field:long ret; offset:16; size:8; signed:1; + +print fmt: "0x%lx", REC->ret +` + +const FormatUmount = `name: sys_enter_umount +ID: 953 +format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:int __syscall_nr; offset:8; size:4; signed:1; + field:const char * name; offset:16; size:8; signed:0; + field:int flags; offset:24; size:8; signed:0; + +print fmt: "name: 0x%08lx, flags: 0x%08lx", ((unsigned long)(REC->name)), ((unsigned long)(REC->flags)) +` + +const FormatExitUmount = `name: sys_exit_umount +ID: 952 +format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:int __syscall_nr; offset:8; size:4; signed:1; + field:long ret; offset:16; size:8; signed:1; + +print fmt: "0x%lx", REC->ret +` + +const FormatMoveMount = `name: sys_enter_move_mount +ID: 945 +format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:int __syscall_nr; offset:8; size:4; signed:1; + field:int from_dfd; offset:16; size:8; signed:0; + field:const char * from_pathname; offset:24; size:8; signed:0; + field:int to_dfd; offset:32; size:8; signed:0; + field:const char * to_pathname; offset:40; size:8; signed:0; + field:unsigned int flags; offset:48; size:8; signed:0; + +print fmt: "from_dfd: 0x%08lx, from_pathname: 0x%08lx, to_dfd: 0x%08lx, to_pathname: 0x%08lx, flags: 0x%08lx", ((unsigned long)(REC->from_dfd)), ((unsigned long)(REC->from_pathname)), ((unsigned long)(REC->to_dfd)), ((unsigned long)(REC->to_pathname)), ((unsigned long)(REC->flags)) +` + +const FormatExitMoveMount = `name: sys_exit_move_mount +ID: 944 +format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:int __syscall_nr; offset:8; size:4; signed:1; + field:long ret; offset:16; size:8; signed:1; + +print fmt: "0x%lx", REC->ret +` + +const FormatFsmount = `name: sys_enter_fsmount +ID: 947 +format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:int __syscall_nr; offset:8; size:4; signed:1; + field:int fs_fd; offset:16; size:8; signed:0; + field:unsigned int flags; offset:24; size:8; signed:0; + field:unsigned int attr_flags; offset:32; size:8; signed:0; + +print fmt: "fs_fd: 0x%08lx, flags: 0x%08lx, attr_flags: 0x%08lx", ((unsigned long)(REC->fs_fd)), ((unsigned long)(REC->flags)), ((unsigned long)(REC->attr_flags)) +` + +const FormatExitFsmount = `name: sys_exit_fsmount +ID: 946 +format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:int __syscall_nr; offset:8; size:4; signed:1; + field:long ret; offset:16; size:8; signed:1; + +print fmt: "0x%lx", REC->ret +` + +const FormatPivotRoot = `name: sys_enter_pivot_root +ID: 943 +format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:int __syscall_nr; offset:8; size:4; signed:1; + field:const char * new_root; offset:16; size:8; signed:0; + field:const char * put_old; offset:24; size:8; signed:0; + +print fmt: "new_root: 0x%08lx, put_old: 0x%08lx", ((unsigned long)(REC->new_root)), ((unsigned long)(REC->put_old)) +` + +const FormatExitPivotRoot = `name: sys_exit_pivot_root +ID: 942 +format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:int __syscall_nr; offset:8; size:4; signed:1; + field:long ret; offset:16; size:8; signed:1; + +print fmt: "0x%lx", REC->ret +` + +const FormatQuotactl = `name: sys_enter_quotactl +ID: 1164 +format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:int __syscall_nr; offset:8; size:4; signed:1; + field:unsigned int cmd; offset:16; size:8; signed:0; + field:const char * special; offset:24; size:8; signed:0; + field:qid_t id; offset:32; size:8; signed:0; + field:void * addr; offset:40; size:8; signed:0; + +print fmt: "cmd: 0x%08lx, special: 0x%08lx, id: 0x%08lx, addr: 0x%08lx", ((unsigned long)(REC->cmd)), ((unsigned long)(REC->special)), ((unsigned long)(REC->id)), ((unsigned long)(REC->addr)) +` + +const FormatExitQuotactl = `name: sys_exit_quotactl +ID: 1163 +format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:int __syscall_nr; offset:8; size:4; signed:1; + field:long ret; offset:16; size:8; signed:1; + +print fmt: "0x%lx", REC->ret +` + +const FormatStatmount = `name: sys_enter_statmount +ID: 937 +format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:int __syscall_nr; offset:8; size:4; signed:1; + field:struct mnt_id_req * req; offset:16; size:8; signed:0; + field:struct statmount * smbuf; offset:24; size:8; signed:0; + field:size_t bufsize; offset:32; size:8; signed:0; + field:unsigned long flags; offset:40; size:8; signed:0; + +print fmt: "req: 0x%08lx, smbuf: 0x%08lx, bufsize: 0x%08lx, flags: 0x%08lx", ((unsigned long)(REC->req)), ((unsigned long)(REC->smbuf)), ((unsigned long)(REC->bufsize)), ((unsigned long)(REC->flags)) +` + +const FormatExitStatmount = `name: sys_exit_statmount +ID: 936 +format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:int __syscall_nr; offset:8; size:4; signed:1; + field:long ret; offset:16; size:8; signed:1; + +print fmt: "0x%lx", REC->ret +` + +const FormatListmount = `name: sys_enter_listmount +ID: 935 +format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:int __syscall_nr; offset:8; size:4; signed:1; + field:struct mnt_id_req * req; offset:16; size:8; signed:0; + field:u64 * mnt_ids; offset:24; size:8; signed:0; + field:size_t nr_mnt_ids; offset:32; size:8; signed:0; + field:unsigned long flags; offset:40; size:8; signed:0; + +print fmt: "req: 0x%08lx, mnt_ids: 0x%08lx, nr_mnt_ids: 0x%08lx, flags: 0x%08lx", ((unsigned long)(REC->req)), ((unsigned long)(REC->mnt_ids)), ((unsigned long)(REC->nr_mnt_ids)), ((unsigned long)(REC->flags)) +` + +const FormatExitListmount = `name: sys_exit_listmount +ID: 934 +format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:int __syscall_nr; offset:8; size:4; signed:1; + field:long ret; offset:16; size:8; signed:1; + +print fmt: "0x%lx", REC->ret +` + +const FormatListns = `name: sys_enter_listns +ID: 277 +format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:int __syscall_nr; offset:8; size:4; signed:1; + field:const struct ns_id_req * req; offset:16; size:8; signed:0; + field:u64 * ns_ids; offset:24; size:8; signed:0; + field:size_t nr_ns_ids; offset:32; size:8; signed:0; + field:unsigned long flags; offset:40; size:8; signed:0; + +print fmt: "req: 0x%08lx, ns_ids: 0x%08lx, nr_ns_ids: 0x%08lx, flags: 0x%08lx", ((unsigned long)(REC->req)), ((unsigned long)(REC->ns_ids)), ((unsigned long)(REC->nr_ns_ids)), ((unsigned long)(REC->flags)) +` + +const FormatExitListns = `name: sys_exit_listns +ID: 276 +format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:int __syscall_nr; offset:8; size:4; signed:1; + field:long ret; offset:16; size:8; signed:1; + +print fmt: "0x%lx", REC->ret +` + +const FormatSwapon = `name: sys_enter_swapon +ID: 731 +format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:int __syscall_nr; offset:8; size:4; signed:1; + field:const char * specialfile; offset:16; size:8; signed:0; + field:int swap_flags; offset:24; size:8; signed:0; + +print fmt: "specialfile: 0x%08lx, swap_flags: 0x%08lx", ((unsigned long)(REC->specialfile)), ((unsigned long)(REC->swap_flags)) +` + +const FormatExitSwapon = `name: sys_exit_swapon +ID: 730 +format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:int __syscall_nr; offset:8; size:4; signed:1; + field:long ret; offset:16; size:8; signed:1; + +print fmt: "0x%lx", REC->ret +` + +const FormatSwapoff = `name: sys_enter_swapoff +ID: 733 +format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:int __syscall_nr; offset:8; size:4; signed:1; + field:const char * specialfile; offset:16; size:8; signed:0; + +print fmt: "specialfile: 0x%08lx", ((unsigned long)(REC->specialfile)) +` + +const FormatExitSwapoff = `name: sys_exit_swapoff +ID: 732 +format: + field:unsigned short common_type; offset:0; size:2; signed:0; + field:unsigned char common_flags; offset:2; size:1; signed:0; + field:unsigned char common_preempt_count; offset:3; size:1; signed:0; + field:int common_pid; offset:4; size:4; signed:1; + + field:int __syscall_nr; offset:8; size:4; signed:1; + field:long ret; offset:16; size:8; signed:1; + +print fmt: "0x%lx", REC->ret +` + // Ignored tracepoints const FormatExecve = `name: sys_enter_execve diff --git a/internal/types/fastdecode.go b/internal/types/fastdecode.go index 6e35093..fcaee45 100644 --- a/internal/types/fastdecode.go +++ b/internal/types/fastdecode.go @@ -22,6 +22,7 @@ const ( eventfdEventSize = 40 eventfdEventSizeV1 = 36 epollCtlEventSize = 40 + twoFdEventSize = 40 pollEventSize = 40 pollEventSizeV1 = 36 memEventSize = 56 @@ -320,6 +321,25 @@ func NewEpollCtlEventFast(raw []byte) *EpollCtlEvent { return e } +func NewTwoFdEventFast(raw []byte) *TwoFdEvent { + if len(raw) < twoFdEventSize { + return nil + } + if len(raw) != twoFdEventSize { + return NewTwoFdEvent(raw) + } + t := poolOfTwoFdEvents.Get().(*TwoFdEvent) + t.EventType = EventType(binary.LittleEndian.Uint32(raw[0:4])) + t.TraceId = TraceId(binary.LittleEndian.Uint32(raw[4:8])) + t.Time = binary.LittleEndian.Uint64(raw[8:16]) + t.Pid = binary.LittleEndian.Uint32(raw[16:20]) + t.Tid = binary.LittleEndian.Uint32(raw[20:24]) + t.FdA = int32(binary.LittleEndian.Uint32(raw[24:28])) + t.FdB = int32(binary.LittleEndian.Uint32(raw[28:32])) + t.Extra = binary.LittleEndian.Uint64(raw[32:40]) + return t +} + func NewPollEventFast(raw []byte) *PollEvent { if len(raw) < pollEventSizeV1 { return nil diff --git a/internal/types/fastdecode_test.go b/internal/types/fastdecode_test.go index f17c7a9..41ba7e1 100644 --- a/internal/types/fastdecode_test.go +++ b/internal/types/fastdecode_test.go @@ -206,6 +206,19 @@ func TestFastDecodersMatchGeneratedDecoders(t *testing.T) { } }) + t.Run("TwoFdEvent", func(t *testing.T) { + ev := &TwoFdEvent{EventType: ENTER_TWO_FD_EVENT, TraceId: SYS_ENTER_MOVE_MOUNT, Time: 1, Pid: 2, Tid: 3, FdA: 10, FdB: 11, Extra: 0x2} + raw, _ := ev.Bytes() + + slow := NewTwoFdEvent(raw) + fast := NewTwoFdEventFast(raw) + defer slow.Recycle() + defer fast.Recycle() + if !slow.Equals(fast) { + t.Fatalf("two_fd decode mismatch") + } + }) + t.Run("PollEvent", func(t *testing.T) { ev := &PollEvent{EventType: ENTER_POLL_EVENT, TraceId: SYS_ENTER_POLL, Time: 1, Pid: 2, Tid: 3, Nfds: 4, TimeoutNs: 5_000_000} raw, _ := ev.Bytes() @@ -410,6 +423,35 @@ func TestNewPollEventFastKernelLayout(t *testing.T) { } } +func TestNewTwoFdEventFastKernelLayout(t *testing.T) { + raw := make([]byte, twoFdEventSize) + binary.LittleEndian.PutUint32(raw[0:4], uint32(ENTER_TWO_FD_EVENT)) + binary.LittleEndian.PutUint32(raw[4:8], uint32(SYS_ENTER_MOVE_MOUNT)) + binary.LittleEndian.PutUint64(raw[8:16], 1) + binary.LittleEndian.PutUint32(raw[16:20], 2) + binary.LittleEndian.PutUint32(raw[20:24], 3) + binary.LittleEndian.PutUint32(raw[24:28], uint32(10)) + binary.LittleEndian.PutUint32(raw[28:32], uint32(11)) + binary.LittleEndian.PutUint64(raw[32:40], uint64(0x80)) + + fast := NewTwoFdEventFast(raw) + if fast == nil { + t.Fatalf("expected decoded two_fd event for kernel layout payload") + } + defer fast.Recycle() + + if fast.EventType != ENTER_TWO_FD_EVENT || + fast.TraceId != SYS_ENTER_MOVE_MOUNT || + fast.Time != 1 || + fast.Pid != 2 || + fast.Tid != 3 || + fast.FdA != 10 || + fast.FdB != 11 || + fast.Extra != 0x80 { + t.Fatalf("unexpected two_fd decode: %#v", fast) + } +} + func TestNewSleepEventFastKernelLayout(t *testing.T) { raw := make([]byte, sleepEventSize) binary.LittleEndian.PutUint32(raw[0:4], uint32(ENTER_SLEEP_EVENT)) @@ -455,6 +497,7 @@ func TestFastDecodersReturnNilOnShortPayload(t *testing.T) { {name: "PipeEvent", decode: func(raw []byte) bool { return NewPipeEventFast(raw) == nil }}, {name: "EventfdEvent", decode: func(raw []byte) bool { return NewEventfdEventFast(raw) == nil }}, {name: "EpollCtlEvent", decode: func(raw []byte) bool { return NewEpollCtlEventFast(raw) == nil }}, + {name: "TwoFdEvent", decode: func(raw []byte) bool { return NewTwoFdEventFast(raw) == nil }}, {name: "PollEvent", decode: func(raw []byte) bool { return NewPollEventFast(raw) == nil }}, {name: "SleepEvent", decode: func(raw []byte) bool { return NewSleepEventFast(raw) == nil }}, } diff --git a/internal/types/generated_types.go b/internal/types/generated_types.go index bd5518a..d731d30 100644 --- a/internal/types/generated_types.go +++ b/internal/types/generated_types.go @@ -38,7 +38,7 @@ var traceId2Name = map[TraceId]string{ } var traceId2Family = map[TraceId]SyscallFamily{ - 1847: FamilyNetwork, 1846: FamilyNetwork, 1845: FamilyNetwork, 1844: FamilyNetwork, 1843: FamilyNetwork, 1842: FamilyNetwork, 1841: FamilyNetwork, 1840: FamilyNetwork, 1839: FamilyNetwork, 1838: FamilyNetwork, 1837: FamilyNetwork, 1836: FamilyNetwork, 1835: FamilyNetwork, 1834: FamilyNetwork, 1833: FamilyNetwork, 1832: FamilyNetwork, 1831: FamilyNetwork, 1830: FamilyNetwork, 1829: FamilyNetwork, 1828: FamilyNetwork, 1827: FamilyNetwork, 1826: FamilyNetwork, 1825: FamilyNetwork, 1824: FamilyNetwork, 1823: FamilyNetwork, 1822: FamilyNetwork, 1821: FamilyNetwork, 1820: FamilyNetwork, 1819: FamilyNetwork, 1818: FamilyNetwork, 1817: FamilyNetwork, 1816: FamilyNetwork, 1815: FamilyNetwork, 1814: FamilyNetwork, 1813: FamilyNetwork, 1812: FamilyNetwork, 1575: FamilySecurity, 1574: FamilySecurity, 1528: FamilyAIO, 1527: FamilyAIO, 1509: FamilyAIO, 1508: FamilyAIO, 1507: FamilyAIO, 1506: FamilyAIO, 1491: FamilyMisc, 1490: FamilyMisc, 1489: FamilyMisc, 1488: FamilyMisc, 1463: FamilySecurity, 1462: FamilySecurity, 1461: FamilySecurity, 1460: FamilySecurity, 1459: FamilySecurity, 1458: FamilySecurity, 1456: FamilyMisc, 1455: FamilyMisc, 1454: FamilyMisc, 1453: FamilyMisc, 1452: FamilyMisc, 1451: FamilyMisc, 1449: FamilySecurity, 1448: FamilySecurity, 1447: FamilySecurity, 1446: FamilySecurity, 1445: FamilySecurity, 1444: FamilySecurity, 1443: FamilyIPC, 1442: FamilyIPC, 1441: FamilyIPC, 1440: FamilyIPC, 1439: FamilyIPC, 1438: FamilyIPC, 1437: FamilyIPC, 1436: FamilyIPC, 1435: FamilyIPC, 1434: FamilyIPC, 1433: FamilyIPC, 1432: FamilyIPC, 1431: FamilyIPC, 1430: FamilyIPC, 1429: FamilyIPC, 1428: FamilyIPC, 1427: FamilyIPC, 1426: FamilyIPC, 1425: FamilyIPC, 1424: FamilyIPC, 1423: FamilyIPC, 1422: FamilyIPC, 1421: FamilyIPC, 1420: FamilyIPC, 1419: FamilyIPC, 1418: FamilyIPC, 1417: FamilyIPC, 1416: FamilyIPC, 1415: FamilyIPC, 1414: FamilyIPC, 1413: FamilyIPC, 1412: FamilyIPC, 1411: FamilyIPC, 1410: FamilyIPC, 1409: FamilyIPC, 1408: FamilyIPC, 1164: FamilyFS, 1163: FamilyFS, 1162: FamilyFS, 1161: FamilyFS, 1146: FamilyFS, 1145: FamilyFS, 1144: FamilyFS, 1143: FamilyFS, 1130: FamilyFS, 1129: FamilyFS, 1111: FamilyAIO, 1110: FamilyAIO, 1109: FamilyAIO, 1108: FamilyAIO, 1107: FamilyAIO, 1106: FamilyAIO, 1105: FamilyAIO, 1104: FamilyAIO, 1103: FamilyAIO, 1102: FamilyAIO, 1101: FamilyAIO, 1100: FamilyAIO, 1099: FamilyIPC, 1098: FamilyIPC, 1097: FamilyIPC, 1096: FamilyIPC, 1095: FamilyIPC, 1094: FamilyIPC, 1093: FamilyIPC, 1092: FamilyIPC, 1091: FamilyIPC, 1090: FamilyIPC, 1089: FamilyIPC, 1088: FamilyIPC, 1087: FamilyIPC, 1086: FamilyIPC, 1085: FamilyIPC, 1084: FamilyIPC, 1083: FamilyPolling, 1082: FamilyPolling, 1081: FamilyPolling, 1080: FamilyPolling, 1079: FamilyPolling, 1078: FamilyPolling, 1077: FamilyPolling, 1076: FamilyPolling, 1075: FamilyPolling, 1074: FamilyPolling, 1073: FamilyPolling, 1072: FamilyPolling, 1071: FamilyMisc, 1070: FamilyMisc, 1069: FamilyMisc, 1068: FamilyMisc, 1067: FamilyIPC, 1066: FamilyIPC, 1065: FamilyIPC, 1064: FamilyIPC, 1063: FamilyIPC, 1062: FamilyIPC, 1061: FamilyIPC, 1060: FamilyIPC, 1059: FamilyMisc, 1058: FamilyMisc, 1057: FamilyMisc, 1056: FamilyMisc, 1055: FamilyFS, 1054: FamilyFS, 1053: FamilyFS, 1052: FamilyFS, 1051: FamilyFS, 1050: FamilyFS, 1049: FamilyFS, 1048: FamilyFS, 1047: FamilyFS, 1046: FamilyFS, 1045: FamilyFS, 1044: FamilyFS, 1043: FamilyFS, 1042: FamilyFS, 1041: FamilyFS, 1040: FamilyFS, 1039: FamilyFS, 1038: FamilyFS, 1037: FamilyMisc, 1036: FamilyMisc, 1035: FamilyMisc, 1034: FamilyMisc, 1033: FamilyFS, 1032: FamilyFS, 1031: FamilyFS, 1030: FamilyFS, 1029: FamilyFS, 1028: FamilyFS, 1027: FamilyFS, 1026: FamilyFS, 1025: FamilyFS, 1024: FamilyFS, 1023: FamilyMisc, 1022: FamilyMisc, 1021: FamilyNetwork, 1020: FamilyNetwork, 1019: FamilyNetwork, 1018: FamilyNetwork, 985: FamilyFS, 984: FamilyFS, 983: FamilyFS, 982: FamilyFS, 981: FamilyFS, 980: FamilyFS, 979: FamilyFS, 978: FamilyFS, 977: FamilyFS, 976: FamilyFS, 975: FamilyFS, 974: FamilyFS, 973: FamilyFS, 972: FamilyFS, 971: FamilyFS, 970: FamilyFS, 969: FamilyFS, 968: FamilyFS, 967: FamilyFS, 966: FamilyFS, 965: FamilyFS, 964: FamilyFS, 963: FamilyFS, 962: FamilyFS, 961: FamilyFS, 960: FamilyFS, 959: FamilyFS, 958: FamilyFS, 957: FamilyFS, 956: FamilyFS, 955: FamilyFS, 954: FamilyFS, 953: FamilyMisc, 952: FamilyMisc, 951: FamilyFS, 950: FamilyFS, 949: FamilyFS, 948: FamilyFS, 947: FamilyFS, 946: FamilyFS, 945: FamilyFS, 944: FamilyFS, 943: FamilyProcess, 942: FamilyProcess, 941: FamilyFS, 940: FamilyFS, 939: FamilyFS, 938: FamilyFS, 937: FamilyFS, 936: FamilyFS, 935: FamilyMisc, 934: FamilyMisc, 933: FamilyMisc, 932: FamilyMisc, 931: FamilyFS, 930: FamilyFS, 929: FamilyFS, 928: FamilyFS, 927: FamilyFS, 926: FamilyFS, 925: FamilyFS, 924: FamilyFS, 919: FamilyPolling, 918: FamilyPolling, 917: FamilyPolling, 916: FamilyPolling, 915: FamilyPolling, 914: FamilyPolling, 913: FamilyPolling, 912: FamilyPolling, 911: FamilyFS, 910: FamilyFS, 909: FamilyFS, 908: FamilyFS, 907: FamilyFS, 906: FamilyFS, 905: FamilyFS, 904: FamilyFS, 903: FamilyFS, 902: FamilyFS, 901: FamilyFS, 900: FamilyFS, 899: FamilyFS, 898: FamilyFS, 897: FamilyFS, 896: FamilyFS, 895: FamilyFS, 894: FamilyFS, 893: FamilyFS, 892: FamilyFS, 891: FamilyFS, 890: FamilyFS, 889: FamilyFS, 888: FamilyFS, 887: FamilyFS, 886: FamilyFS, 885: FamilyFS, 884: FamilyFS, 883: FamilyFS, 882: FamilyFS, 881: FamilyFS, 880: FamilyFS, 879: FamilyFS, 878: FamilyFS, 877: FamilyFS, 876: FamilyFS, 875: FamilyIPC, 874: FamilyIPC, 873: FamilyIPC, 872: FamilyIPC, 871: FamilyProcess, 870: FamilyProcess, 869: FamilyProcess, 868: FamilyProcess, 867: FamilyFS, 866: FamilyFS, 865: FamilyFS, 864: FamilyFS, 863: FamilyFS, 862: FamilyFS, 861: FamilyFS, 860: FamilyFS, 859: FamilyFS, 858: FamilyFS, 857: FamilyFS, 856: FamilyFS, 855: FamilyFS, 854: FamilyFS, 853: FamilyFS, 852: FamilyFS, 851: FamilyFS, 850: FamilyFS, 849: FamilyFS, 848: FamilyFS, 847: FamilyFS, 846: FamilyFS, 845: FamilyFS, 844: FamilyFS, 843: FamilyFS, 842: FamilyFS, 841: FamilyFS, 840: FamilyFS, 839: FamilyFS, 838: FamilyFS, 837: FamilyFS, 836: FamilyFS, 835: FamilyFS, 834: FamilyFS, 833: FamilyFS, 832: FamilyFS, 831: FamilyNetwork, 830: FamilyNetwork, 829: FamilyFS, 828: FamilyFS, 827: FamilyFS, 826: FamilyFS, 825: FamilyFS, 824: FamilyFS, 823: FamilyFS, 822: FamilyFS, 821: FamilyFS, 820: FamilyFS, 819: FamilyFS, 818: FamilyFS, 817: FamilyFS, 816: FamilyFS, 815: FamilyFS, 814: FamilyFS, 813: FamilyFS, 812: FamilyFS, 811: FamilyFS, 810: FamilyFS, 809: FamilyFS, 808: FamilyFS, 807: FamilyFS, 806: FamilyFS, 805: FamilyFS, 804: FamilyFS, 803: FamilyFS, 802: FamilyFS, 801: FamilyFS, 800: FamilyFS, 799: FamilyFS, 798: FamilyFS, 797: FamilyFS, 796: FamilyFS, 795: FamilyFS, 794: FamilyFS, 793: FamilyFS, 792: FamilyFS, 791: FamilyFS, 790: FamilyFS, 789: FamilyFS, 788: FamilyFS, 787: FamilyFS, 786: FamilyFS, 785: FamilyFS, 784: FamilyFS, 783: FamilyProcess, 782: FamilyProcess, 781: FamilyIPC, 780: FamilyIPC, 774: FamilyIPC, 773: FamilyIPC, 754: FamilyMemory, 753: FamilyMemory, 743: FamilyMemory, 742: FamilyMemory, 741: FamilyMemory, 740: FamilyMemory, 739: FamilyMemory, 738: FamilyMemory, 737: FamilyMemory, 736: FamilyMemory, 735: FamilySecurity, 734: FamilySecurity, 733: FamilyMisc, 732: FamilyMisc, 731: FamilyMisc, 730: FamilyMisc, 729: FamilyMemory, 728: FamilyMemory, 727: FamilyMemory, 726: FamilyMemory, 725: FamilyMemory, 724: FamilyMemory, 723: FamilyMemory, 722: FamilyMemory, 721: FamilyMemory, 720: FamilyMemory, 712: FamilyFS, 711: FamilyFS, 710: FamilyMemory, 709: FamilyMemory, 708: FamilyMemory, 707: FamilyMemory, 706: FamilyMemory, 705: FamilyMemory, 704: FamilyMemory, 703: FamilyMemory, 702: FamilyMemory, 701: FamilyMemory, 698: FamilyMemory, 697: FamilyMemory, 696: FamilyMemory, 695: FamilyMemory, 694: FamilyMemory, 693: FamilyMemory, 692: FamilyMemory, 691: FamilyMemory, 690: FamilyMemory, 689: FamilyMemory, 688: FamilyMemory, 687: FamilyMemory, 686: FamilyMemory, 685: FamilyMemory, 684: FamilyMemory, 683: FamilyMemory, 682: FamilyMemory, 681: FamilyMemory, 616: FamilyFS, 615: FamilyFS, 614: FamilyFS, 613: FamilyFS, 604: FamilyMemory, 603: FamilyMemory, 595: FamilyFS, 594: FamilyFS, 591: FamilyMisc, 590: FamilyMisc, 587: FamilySecurity, 586: FamilySecurity, 585: FamilySecurity, 584: FamilySecurity, 526: FamilySecurity, 525: FamilySecurity, 508: FamilySecurity, 507: FamilySecurity, 506: FamilyMisc, 505: FamilyMisc, 504: FamilyMisc, 503: FamilyMisc, 499: FamilyMisc, 498: FamilyMisc, 497: FamilyMisc, 496: FamilyMisc, 495: FamilyMisc, 494: FamilyMisc, 493: FamilyMisc, 492: FamilyMisc, 491: FamilyMisc, 490: FamilyMisc, 489: FamilyMisc, 488: FamilyMisc, 487: FamilyMisc, 486: FamilyMisc, 471: FamilyTime, 470: FamilyTime, 469: FamilyMisc, 468: FamilyMisc, 467: FamilyTime, 466: FamilyTime, 465: FamilyTime, 464: FamilyTime, 463: FamilyTime, 462: FamilyTime, 461: FamilyTime, 460: FamilyTime, 459: FamilyTime, 458: FamilyTime, 457: FamilyTime, 456: FamilyTime, 455: FamilyTime, 454: FamilyTime, 453: FamilyTime, 452: FamilyTime, 451: FamilyTime, 450: FamilyTime, 449: FamilyTime, 448: FamilyTime, 447: FamilyTime, 446: FamilyTime, 441: FamilyTime, 440: FamilyTime, 425: FamilyTime, 424: FamilyTime, 423: FamilyTime, 422: FamilyTime, 421: FamilyTime, 420: FamilyTime, 419: FamilyMisc, 418: FamilyMisc, 417: FamilyProcess, 416: FamilyProcess, 410: FamilySecurity, 409: FamilySecurity, 408: FamilySecurity, 407: FamilySecurity, 406: FamilySecurity, 405: FamilySecurity, 350: FamilyMisc, 349: FamilyMisc, 346: FamilyMemory, 345: FamilyMemory, 341: FamilySched, 340: FamilySched, 339: FamilySched, 338: FamilySched, 337: FamilySched, 336: FamilySched, 335: FamilySched, 334: FamilySched, 333: FamilySched, 332: FamilySched, 331: FamilySched, 330: FamilySched, 329: FamilySched, 328: FamilySched, 327: FamilySched, 326: FamilySched, 325: FamilySched, 324: FamilySched, 323: FamilySched, 322: FamilySched, 321: FamilySched, 320: FamilySched, 319: FamilySched, 318: FamilySched, 286: FamilyProcess, 285: FamilyProcess, 284: FamilyProcess, 283: FamilyProcess, 282: FamilyProcess, 281: FamilyProcess, 277: FamilyMisc, 276: FamilyMisc, 275: FamilyProcess, 274: FamilyProcess, 273: FamilyIPC, 272: FamilyIPC, 271: FamilyIPC, 270: FamilyIPC, 265: FamilyProcess, 264: FamilyProcess, 263: FamilyProcess, 262: FamilyProcess, 261: FamilyProcess, 260: FamilyProcess, 259: FamilyProcess, 258: FamilyProcess, 257: FamilyProcess, 256: FamilyProcess, 255: FamilyProcess, 254: FamilyProcess, 253: FamilyProcess, 252: FamilyProcess, 251: FamilyProcess, 250: FamilyProcess, 249: FamilyProcess, 248: FamilyProcess, 247: FamilyProcess, 246: FamilyProcess, 245: FamilyProcess, 244: FamilyProcess, 243: FamilyProcess, 242: FamilyProcess, 241: FamilyProcess, 240: FamilyProcess, 239: FamilyProcess, 238: FamilyProcess, 237: FamilyProcess, 236: FamilyProcess, 235: FamilyProcess, 234: FamilyProcess, 233: FamilyProcess, 232: FamilyProcess, 231: FamilyProcess, 230: FamilyProcess, 229: FamilyProcess, 228: FamilyProcess, 227: FamilyTime, 226: FamilyTime, 225: FamilyProcess, 224: FamilyProcess, 223: FamilyProcess, 222: FamilyProcess, 221: FamilyProcess, 220: FamilyProcess, 219: FamilyProcess, 218: FamilyProcess, 217: FamilyProcess, 216: FamilyProcess, 215: FamilyMisc, 214: FamilyMisc, 213: FamilyMisc, 212: FamilyMisc, 211: FamilyMisc, 210: FamilyMisc, 209: FamilyProcess, 208: FamilyProcess, 207: FamilyProcess, 206: FamilyProcess, 205: FamilyProcess, 204: FamilyProcess, 203: FamilyProcess, 202: FamilyProcess, 201: FamilyProcess, 200: FamilyProcess, 199: FamilyProcess, 198: FamilyProcess, 197: FamilyMisc, 196: FamilyMisc, 195: FamilyMisc, 194: FamilyMisc, 191: FamilyProcess, 190: FamilyProcess, 189: FamilySignals, 188: FamilySignals, 187: FamilySignals, 186: FamilySignals, 185: FamilySignals, 184: FamilySignals, 183: FamilySignals, 182: FamilySignals, 181: FamilyIPC, 180: FamilyIPC, 179: FamilySignals, 178: FamilySignals, 177: FamilySignals, 176: FamilySignals, 175: FamilySignals, 174: FamilySignals, 173: FamilySignals, 172: FamilySignals, 171: FamilySignals, 170: FamilySignals, 169: FamilySignals, 168: FamilySignals, 167: FamilySignals, 166: FamilySignals, 165: FamilySignals, 164: FamilySignals, 163: FamilySecurity, 162: FamilySecurity, 161: FamilySecurity, 160: FamilySecurity, 159: FamilySecurity, 158: FamilySecurity, 150: FamilyProcess, 149: FamilyProcess, 148: FamilyProcess, 147: FamilyProcess, 146: FamilyProcess, 145: FamilyProcess, 144: FamilyProcess, 143: FamilyProcess, 139: FamilyProcess, 138: FamilyProcess, 134: FamilyProcess, 133: FamilyProcess, 132: FamilyProcess, 131: FamilyProcess, 130: FamilyProcess, 129: FamilyProcess, 128: FamilyProcess, 127: FamilyProcess, 126: FamilyProcess, 125: FamilyProcess, 124: FamilyProcess, 123: FamilyProcess, 119: FamilyMemory, 118: FamilyMemory, 117: FamilyMisc, 116: FamilyMisc, 115: FamilyMisc, 114: FamilyMisc, 102: FamilyProcess, 101: FamilyProcess, 100: FamilyMemory, 99: FamilyMemory, 98: FamilyMisc, 97: FamilyMisc, 95: FamilyMisc, 94: FamilyMisc, 93: FamilyMisc, 92: FamilyMisc, 57: FamilySignals, 56: FamilySignals, + 1847: FamilyNetwork, 1846: FamilyNetwork, 1845: FamilyNetwork, 1844: FamilyNetwork, 1843: FamilyNetwork, 1842: FamilyNetwork, 1841: FamilyNetwork, 1840: FamilyNetwork, 1839: FamilyNetwork, 1838: FamilyNetwork, 1837: FamilyNetwork, 1836: FamilyNetwork, 1835: FamilyNetwork, 1834: FamilyNetwork, 1833: FamilyNetwork, 1832: FamilyNetwork, 1831: FamilyNetwork, 1830: FamilyNetwork, 1829: FamilyNetwork, 1828: FamilyNetwork, 1827: FamilyNetwork, 1826: FamilyNetwork, 1825: FamilyNetwork, 1824: FamilyNetwork, 1823: FamilyNetwork, 1822: FamilyNetwork, 1821: FamilyNetwork, 1820: FamilyNetwork, 1819: FamilyNetwork, 1818: FamilyNetwork, 1817: FamilyNetwork, 1816: FamilyNetwork, 1815: FamilyNetwork, 1814: FamilyNetwork, 1813: FamilyNetwork, 1812: FamilyNetwork, 1575: FamilySecurity, 1574: FamilySecurity, 1528: FamilyAIO, 1527: FamilyAIO, 1509: FamilyAIO, 1508: FamilyAIO, 1507: FamilyAIO, 1506: FamilyAIO, 1491: FamilyMisc, 1490: FamilyMisc, 1489: FamilyMisc, 1488: FamilyMisc, 1463: FamilySecurity, 1462: FamilySecurity, 1461: FamilySecurity, 1460: FamilySecurity, 1459: FamilySecurity, 1458: FamilySecurity, 1456: FamilyMisc, 1455: FamilyMisc, 1454: FamilyMisc, 1453: FamilyMisc, 1452: FamilyMisc, 1451: FamilyMisc, 1449: FamilySecurity, 1448: FamilySecurity, 1447: FamilySecurity, 1446: FamilySecurity, 1445: FamilySecurity, 1444: FamilySecurity, 1443: FamilyIPC, 1442: FamilyIPC, 1441: FamilyIPC, 1440: FamilyIPC, 1439: FamilyIPC, 1438: FamilyIPC, 1437: FamilyIPC, 1436: FamilyIPC, 1435: FamilyIPC, 1434: FamilyIPC, 1433: FamilyIPC, 1432: FamilyIPC, 1431: FamilyIPC, 1430: FamilyIPC, 1429: FamilyIPC, 1428: FamilyIPC, 1427: FamilyIPC, 1426: FamilyIPC, 1425: FamilyIPC, 1424: FamilyIPC, 1423: FamilyIPC, 1422: FamilyIPC, 1421: FamilyIPC, 1420: FamilyIPC, 1419: FamilyIPC, 1418: FamilyIPC, 1417: FamilyIPC, 1416: FamilyIPC, 1415: FamilyIPC, 1414: FamilyIPC, 1413: FamilyIPC, 1412: FamilyIPC, 1411: FamilyIPC, 1410: FamilyIPC, 1409: FamilyIPC, 1408: FamilyIPC, 1164: FamilyFS, 1163: FamilyFS, 1162: FamilyFS, 1161: FamilyFS, 1146: FamilyFS, 1145: FamilyFS, 1144: FamilyFS, 1143: FamilyFS, 1130: FamilyFS, 1129: FamilyFS, 1111: FamilyAIO, 1110: FamilyAIO, 1109: FamilyAIO, 1108: FamilyAIO, 1107: FamilyAIO, 1106: FamilyAIO, 1105: FamilyAIO, 1104: FamilyAIO, 1103: FamilyAIO, 1102: FamilyAIO, 1101: FamilyAIO, 1100: FamilyAIO, 1099: FamilyIPC, 1098: FamilyIPC, 1097: FamilyIPC, 1096: FamilyIPC, 1095: FamilyIPC, 1094: FamilyIPC, 1093: FamilyIPC, 1092: FamilyIPC, 1091: FamilyIPC, 1090: FamilyIPC, 1089: FamilyIPC, 1088: FamilyIPC, 1087: FamilyIPC, 1086: FamilyIPC, 1085: FamilyIPC, 1084: FamilyIPC, 1083: FamilyPolling, 1082: FamilyPolling, 1081: FamilyPolling, 1080: FamilyPolling, 1079: FamilyPolling, 1078: FamilyPolling, 1077: FamilyPolling, 1076: FamilyPolling, 1075: FamilyPolling, 1074: FamilyPolling, 1073: FamilyPolling, 1072: FamilyPolling, 1071: FamilyMisc, 1070: FamilyMisc, 1069: FamilyMisc, 1068: FamilyMisc, 1067: FamilyIPC, 1066: FamilyIPC, 1065: FamilyIPC, 1064: FamilyIPC, 1063: FamilyIPC, 1062: FamilyIPC, 1061: FamilyIPC, 1060: FamilyIPC, 1059: FamilyMisc, 1058: FamilyMisc, 1057: FamilyMisc, 1056: FamilyMisc, 1055: FamilyFS, 1054: FamilyFS, 1053: FamilyFS, 1052: FamilyFS, 1051: FamilyFS, 1050: FamilyFS, 1049: FamilyFS, 1048: FamilyFS, 1047: FamilyFS, 1046: FamilyFS, 1045: FamilyFS, 1044: FamilyFS, 1043: FamilyFS, 1042: FamilyFS, 1041: FamilyFS, 1040: FamilyFS, 1039: FamilyFS, 1038: FamilyFS, 1037: FamilyMisc, 1036: FamilyMisc, 1035: FamilyMisc, 1034: FamilyMisc, 1033: FamilyFS, 1032: FamilyFS, 1031: FamilyFS, 1030: FamilyFS, 1029: FamilyFS, 1028: FamilyFS, 1027: FamilyFS, 1026: FamilyFS, 1025: FamilyFS, 1024: FamilyFS, 1023: FamilyMisc, 1022: FamilyMisc, 1021: FamilyNetwork, 1020: FamilyNetwork, 1019: FamilyNetwork, 1018: FamilyNetwork, 985: FamilyFS, 984: FamilyFS, 983: FamilyFS, 982: FamilyFS, 981: FamilyFS, 980: FamilyFS, 979: FamilyFS, 978: FamilyFS, 977: FamilyFS, 976: FamilyFS, 975: FamilyFS, 974: FamilyFS, 973: FamilyFS, 972: FamilyFS, 971: FamilyFS, 970: FamilyFS, 969: FamilyFS, 968: FamilyFS, 967: FamilyFS, 966: FamilyFS, 965: FamilyFS, 964: FamilyFS, 963: FamilyFS, 962: FamilyFS, 961: FamilyFS, 960: FamilyFS, 959: FamilyFS, 958: FamilyFS, 957: FamilyFS, 956: FamilyFS, 955: FamilyFS, 954: FamilyFS, 953: FamilyFS, 952: FamilyFS, 951: FamilyFS, 950: FamilyFS, 949: FamilyFS, 948: FamilyFS, 947: FamilyFS, 946: FamilyFS, 945: FamilyFS, 944: FamilyFS, 943: FamilyProcess, 942: FamilyProcess, 941: FamilyFS, 940: FamilyFS, 939: FamilyFS, 938: FamilyFS, 937: FamilyFS, 936: FamilyFS, 935: FamilyFS, 934: FamilyFS, 933: FamilyMisc, 932: FamilyMisc, 931: FamilyFS, 930: FamilyFS, 929: FamilyFS, 928: FamilyFS, 927: FamilyFS, 926: FamilyFS, 925: FamilyFS, 924: FamilyFS, 919: FamilyPolling, 918: FamilyPolling, 917: FamilyPolling, 916: FamilyPolling, 915: FamilyPolling, 914: FamilyPolling, 913: FamilyPolling, 912: FamilyPolling, 911: FamilyFS, 910: FamilyFS, 909: FamilyFS, 908: FamilyFS, 907: FamilyFS, 906: FamilyFS, 905: FamilyFS, 904: FamilyFS, 903: FamilyFS, 902: FamilyFS, 901: FamilyFS, 900: FamilyFS, 899: FamilyFS, 898: FamilyFS, 897: FamilyFS, 896: FamilyFS, 895: FamilyFS, 894: FamilyFS, 893: FamilyFS, 892: FamilyFS, 891: FamilyFS, 890: FamilyFS, 889: FamilyFS, 888: FamilyFS, 887: FamilyFS, 886: FamilyFS, 885: FamilyFS, 884: FamilyFS, 883: FamilyFS, 882: FamilyFS, 881: FamilyFS, 880: FamilyFS, 879: FamilyFS, 878: FamilyFS, 877: FamilyFS, 876: FamilyFS, 875: FamilyIPC, 874: FamilyIPC, 873: FamilyIPC, 872: FamilyIPC, 871: FamilyProcess, 870: FamilyProcess, 869: FamilyProcess, 868: FamilyProcess, 867: FamilyFS, 866: FamilyFS, 865: FamilyFS, 864: FamilyFS, 863: FamilyFS, 862: FamilyFS, 861: FamilyFS, 860: FamilyFS, 859: FamilyFS, 858: FamilyFS, 857: FamilyFS, 856: FamilyFS, 855: FamilyFS, 854: FamilyFS, 853: FamilyFS, 852: FamilyFS, 851: FamilyFS, 850: FamilyFS, 849: FamilyFS, 848: FamilyFS, 847: FamilyFS, 846: FamilyFS, 845: FamilyFS, 844: FamilyFS, 843: FamilyFS, 842: FamilyFS, 841: FamilyFS, 840: FamilyFS, 839: FamilyFS, 838: FamilyFS, 837: FamilyFS, 836: FamilyFS, 835: FamilyFS, 834: FamilyFS, 833: FamilyFS, 832: FamilyFS, 831: FamilyNetwork, 830: FamilyNetwork, 829: FamilyFS, 828: FamilyFS, 827: FamilyFS, 826: FamilyFS, 825: FamilyFS, 824: FamilyFS, 823: FamilyFS, 822: FamilyFS, 821: FamilyFS, 820: FamilyFS, 819: FamilyFS, 818: FamilyFS, 817: FamilyFS, 816: FamilyFS, 815: FamilyFS, 814: FamilyFS, 813: FamilyFS, 812: FamilyFS, 811: FamilyFS, 810: FamilyFS, 809: FamilyFS, 808: FamilyFS, 807: FamilyFS, 806: FamilyFS, 805: FamilyFS, 804: FamilyFS, 803: FamilyFS, 802: FamilyFS, 801: FamilyFS, 800: FamilyFS, 799: FamilyFS, 798: FamilyFS, 797: FamilyFS, 796: FamilyFS, 795: FamilyFS, 794: FamilyFS, 793: FamilyFS, 792: FamilyFS, 791: FamilyFS, 790: FamilyFS, 789: FamilyFS, 788: FamilyFS, 787: FamilyFS, 786: FamilyFS, 785: FamilyFS, 784: FamilyFS, 783: FamilyProcess, 782: FamilyProcess, 781: FamilyIPC, 780: FamilyIPC, 774: FamilyIPC, 773: FamilyIPC, 754: FamilyMemory, 753: FamilyMemory, 743: FamilyMemory, 742: FamilyMemory, 741: FamilyMemory, 740: FamilyMemory, 739: FamilyMemory, 738: FamilyMemory, 737: FamilyMemory, 736: FamilyMemory, 735: FamilySecurity, 734: FamilySecurity, 733: FamilyFS, 732: FamilyFS, 731: FamilyFS, 730: FamilyFS, 729: FamilyMemory, 728: FamilyMemory, 727: FamilyMemory, 726: FamilyMemory, 725: FamilyMemory, 724: FamilyMemory, 723: FamilyMemory, 722: FamilyMemory, 721: FamilyMemory, 720: FamilyMemory, 712: FamilyFS, 711: FamilyFS, 710: FamilyMemory, 709: FamilyMemory, 708: FamilyMemory, 707: FamilyMemory, 706: FamilyMemory, 705: FamilyMemory, 704: FamilyMemory, 703: FamilyMemory, 702: FamilyMemory, 701: FamilyMemory, 698: FamilyMemory, 697: FamilyMemory, 696: FamilyMemory, 695: FamilyMemory, 694: FamilyMemory, 693: FamilyMemory, 692: FamilyMemory, 691: FamilyMemory, 690: FamilyMemory, 689: FamilyMemory, 688: FamilyMemory, 687: FamilyMemory, 686: FamilyMemory, 685: FamilyMemory, 684: FamilyMemory, 683: FamilyMemory, 682: FamilyMemory, 681: FamilyMemory, 616: FamilyFS, 615: FamilyFS, 614: FamilyFS, 613: FamilyFS, 604: FamilyMemory, 603: FamilyMemory, 595: FamilyFS, 594: FamilyFS, 591: FamilyMisc, 590: FamilyMisc, 587: FamilySecurity, 586: FamilySecurity, 585: FamilySecurity, 584: FamilySecurity, 526: FamilySecurity, 525: FamilySecurity, 508: FamilySecurity, 507: FamilySecurity, 506: FamilyMisc, 505: FamilyMisc, 504: FamilyMisc, 503: FamilyMisc, 499: FamilyMisc, 498: FamilyMisc, 497: FamilyMisc, 496: FamilyMisc, 495: FamilyMisc, 494: FamilyMisc, 493: FamilyMisc, 492: FamilyMisc, 491: FamilyMisc, 490: FamilyMisc, 489: FamilyMisc, 488: FamilyMisc, 487: FamilyMisc, 486: FamilyMisc, 471: FamilyTime, 470: FamilyTime, 469: FamilyMisc, 468: FamilyMisc, 467: FamilyTime, 466: FamilyTime, 465: FamilyTime, 464: FamilyTime, 463: FamilyTime, 462: FamilyTime, 461: FamilyTime, 460: FamilyTime, 459: FamilyTime, 458: FamilyTime, 457: FamilyTime, 456: FamilyTime, 455: FamilyTime, 454: FamilyTime, 453: FamilyTime, 452: FamilyTime, 451: FamilyTime, 450: FamilyTime, 449: FamilyTime, 448: FamilyTime, 447: FamilyTime, 446: FamilyTime, 441: FamilyTime, 440: FamilyTime, 425: FamilyTime, 424: FamilyTime, 423: FamilyTime, 422: FamilyTime, 421: FamilyTime, 420: FamilyTime, 419: FamilyMisc, 418: FamilyMisc, 417: FamilyProcess, 416: FamilyProcess, 410: FamilySecurity, 409: FamilySecurity, 408: FamilySecurity, 407: FamilySecurity, 406: FamilySecurity, 405: FamilySecurity, 350: FamilyMisc, 349: FamilyMisc, 346: FamilyMemory, 345: FamilyMemory, 341: FamilySched, 340: FamilySched, 339: FamilySched, 338: FamilySched, 337: FamilySched, 336: FamilySched, 335: FamilySched, 334: FamilySched, 333: FamilySched, 332: FamilySched, 331: FamilySched, 330: FamilySched, 329: FamilySched, 328: FamilySched, 327: FamilySched, 326: FamilySched, 325: FamilySched, 324: FamilySched, 323: FamilySched, 322: FamilySched, 321: FamilySched, 320: FamilySched, 319: FamilySched, 318: FamilySched, 286: FamilyProcess, 285: FamilyProcess, 284: FamilyProcess, 283: FamilyProcess, 282: FamilyProcess, 281: FamilyProcess, 277: FamilyFS, 276: FamilyFS, 275: FamilyProcess, 274: FamilyProcess, 273: FamilyIPC, 272: FamilyIPC, 271: FamilyIPC, 270: FamilyIPC, 265: FamilyProcess, 264: FamilyProcess, 263: FamilyProcess, 262: FamilyProcess, 261: FamilyProcess, 260: FamilyProcess, 259: FamilyProcess, 258: FamilyProcess, 257: FamilyProcess, 256: FamilyProcess, 255: FamilyProcess, 254: FamilyProcess, 253: FamilyProcess, 252: FamilyProcess, 251: FamilyProcess, 250: FamilyProcess, 249: FamilyProcess, 248: FamilyProcess, 247: FamilyProcess, 246: FamilyProcess, 245: FamilyProcess, 244: FamilyProcess, 243: FamilyProcess, 242: FamilyProcess, 241: FamilyProcess, 240: FamilyProcess, 239: FamilyProcess, 238: FamilyProcess, 237: FamilyProcess, 236: FamilyProcess, 235: FamilyProcess, 234: FamilyProcess, 233: FamilyProcess, 232: FamilyProcess, 231: FamilyProcess, 230: FamilyProcess, 229: FamilyProcess, 228: FamilyProcess, 227: FamilyTime, 226: FamilyTime, 225: FamilyProcess, 224: FamilyProcess, 223: FamilyProcess, 222: FamilyProcess, 221: FamilyProcess, 220: FamilyProcess, 219: FamilyProcess, 218: FamilyProcess, 217: FamilyProcess, 216: FamilyProcess, 215: FamilyMisc, 214: FamilyMisc, 213: FamilyMisc, 212: FamilyMisc, 211: FamilyMisc, 210: FamilyMisc, 209: FamilyProcess, 208: FamilyProcess, 207: FamilyProcess, 206: FamilyProcess, 205: FamilyProcess, 204: FamilyProcess, 203: FamilyProcess, 202: FamilyProcess, 201: FamilyProcess, 200: FamilyProcess, 199: FamilyProcess, 198: FamilyProcess, 197: FamilyMisc, 196: FamilyMisc, 195: FamilyMisc, 194: FamilyMisc, 191: FamilyProcess, 190: FamilyProcess, 189: FamilySignals, 188: FamilySignals, 187: FamilySignals, 186: FamilySignals, 185: FamilySignals, 184: FamilySignals, 183: FamilySignals, 182: FamilySignals, 181: FamilyIPC, 180: FamilyIPC, 179: FamilySignals, 178: FamilySignals, 177: FamilySignals, 176: FamilySignals, 175: FamilySignals, 174: FamilySignals, 173: FamilySignals, 172: FamilySignals, 171: FamilySignals, 170: FamilySignals, 169: FamilySignals, 168: FamilySignals, 167: FamilySignals, 166: FamilySignals, 165: FamilySignals, 164: FamilySignals, 163: FamilySecurity, 162: FamilySecurity, 161: FamilySecurity, 160: FamilySecurity, 159: FamilySecurity, 158: FamilySecurity, 150: FamilyProcess, 149: FamilyProcess, 148: FamilyProcess, 147: FamilyProcess, 146: FamilyProcess, 145: FamilyProcess, 144: FamilyProcess, 143: FamilyProcess, 139: FamilyProcess, 138: FamilyProcess, 134: FamilyProcess, 133: FamilyProcess, 132: FamilyProcess, 131: FamilyProcess, 130: FamilyProcess, 129: FamilyProcess, 128: FamilyProcess, 127: FamilyProcess, 126: FamilyProcess, 125: FamilyProcess, 124: FamilyProcess, 123: FamilyProcess, 119: FamilyMemory, 118: FamilyMemory, 117: FamilyMisc, 116: FamilyMisc, 115: FamilyMisc, 114: FamilyMisc, 102: FamilyProcess, 101: FamilyProcess, 100: FamilyMemory, 99: FamilyMemory, 98: FamilyMisc, 97: FamilyMisc, 95: FamilyMisc, 94: FamilyMisc, 93: FamilyMisc, 92: FamilyMisc, 57: FamilySignals, 56: FamilySignals, } func (s TraceId) String() string { @@ -104,6 +104,8 @@ const ENTER_MEM_EVENT = 33 const EXIT_MEM_EVENT = 34 const ENTER_SLEEP_EVENT = 35 const EXIT_SLEEP_EVENT = 36 +const ENTER_TWO_FD_EVENT = 37 +const EXIT_TWO_FD_EVENT = 38 const UNCLASSIFIED = 0 const READ_CLASSIFIED = 1 const WRITE_CLASSIFIED = 2 @@ -2091,3 +2093,73 @@ func (s *SleepEvent) Bytes() ([]byte, error) { func (s *SleepEvent) Recycle() { poolOfSleepEvents.Put(s) } + +type TwoFdEvent struct { + EventType EventType + TraceId TraceId + Time uint64 + Pid uint32 + Tid uint32 + FdA int32 + FdB int32 + Extra uint64 +} + +func (t TwoFdEvent) String() string { + return fmt.Sprintf("EventType:%v TraceId:%v Time:%v Pid:%v Tid:%v FdA:%v FdB:%v Extra:%v", t.EventType, t.TraceId, t.Time, t.Pid, t.Tid, t.FdA, t.FdB, t.Extra) +} + +func (t TwoFdEvent) Equals(other any) bool { + otherConcrete, ok := other.(*TwoFdEvent) + if !ok { + return false + } + return t.EventType == otherConcrete.EventType && t.TraceId == otherConcrete.TraceId && t.Time == otherConcrete.Time && t.Pid == otherConcrete.Pid && t.Tid == otherConcrete.Tid && t.FdA == otherConcrete.FdA && t.FdB == otherConcrete.FdB && t.Extra == otherConcrete.Extra +} + +func (t *TwoFdEvent) GetEventType() EventType { + return t.EventType +} + +func (t *TwoFdEvent) GetTraceId() TraceId { + return t.TraceId +} + +func (t *TwoFdEvent) GetPid() uint32 { + return t.Pid +} + +func (t *TwoFdEvent) GetTid() uint32 { + return t.Tid +} + +func (t *TwoFdEvent) GetTime() uint64 { + return t.Time +} + +var poolOfTwoFdEvents = sync.Pool{ + New: func() any { return &TwoFdEvent{} }, +} + +func NewTwoFdEvent(raw []byte) *TwoFdEvent { + t := poolOfTwoFdEvents.Get().(*TwoFdEvent) + if err := binary.Read(bytes.NewReader(raw), binary.LittleEndian, t); err != nil { + *t = TwoFdEvent{} + poolOfTwoFdEvents.Put(t) + return nil + } + return t +} + +func (t *TwoFdEvent) Bytes() ([]byte, error) { + buf := new(bytes.Buffer) + err := binary.Write(buf, binary.LittleEndian, t) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +func (t *TwoFdEvent) Recycle() { + poolOfTwoFdEvents.Put(t) +} diff --git a/internal/types/types_test.go b/internal/types/types_test.go index df321ac..2bc78fe 100644 --- a/internal/types/types_test.go +++ b/internal/types/types_test.go @@ -298,6 +298,33 @@ func TestEpollCtlEventSerialization(t *testing.T) { assertEquals(t, epollCtlEv1.Events, epollCtlEv2.Events) } +func TestTwoFdEventSerialization(t *testing.T) { + twoFdEv1 := TwoFdEvent{ + EventType: ENTER_TWO_FD_EVENT, + TraceId: SYS_ENTER_MOVE_MOUNT, + Time: 6790, + Pid: 40, + Tid: 41, + FdA: 12, + FdB: 34, + Extra: 0x20, + } + bytes, err := twoFdEv1.Bytes() + if err != nil { + t.Error(err) + } + twoFdEv2 := NewTwoFdEvent(bytes) + + assertEquals(t, twoFdEv1.EventType, twoFdEv2.EventType) + assertEquals(t, twoFdEv1.TraceId, twoFdEv2.TraceId) + assertEquals(t, twoFdEv1.Time, twoFdEv2.Time) + assertEquals(t, twoFdEv1.Pid, twoFdEv2.Pid) + assertEquals(t, twoFdEv1.Tid, twoFdEv2.Tid) + assertEquals(t, twoFdEv1.FdA, twoFdEv2.FdA) + assertEquals(t, twoFdEv1.FdB, twoFdEv2.FdB) + assertEquals(t, twoFdEv1.Extra, twoFdEv2.Extra) +} + func TestPollEventSerialization(t *testing.T) { pollEv1 := PollEvent{ EventType: ENTER_POLL_EVENT, |
