diff options
| author | Paul Buetow <paul@buetow.org> | 2024-02-15 10:40:15 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2024-02-16 00:23:24 +0200 |
| commit | cb70df2d4b17dd3d54d89a46e3aee22f3c131854 (patch) | |
| tree | 3c7210a4090139e9045a85bf73322b5002d1f573 | |
| parent | 6d2ae77ccb31844c6c366911ee1b4bc43bd691f6 (diff) | |
switch from perf maps to ring buffer
| -rw-r--r-- | internal/flags/flags.go | 19 | ||||
| -rw-r--r-- | internal/ioriotng.go | 57 | ||||
| -rw-r--r-- | ioriotng.bpf.c | 98 | ||||
| -rw-r--r-- | maps.bpf.h | 53 |
4 files changed, 107 insertions, 120 deletions
diff --git a/internal/flags/flags.go b/internal/flags/flags.go index 1ba9d60..ac7abd4 100644 --- a/internal/flags/flags.go +++ b/internal/flags/flags.go @@ -9,15 +9,13 @@ import ( ) type Flags struct { - UidFilter int - FdEventMapSize int - OpenEventMapSize int + UidFilter int + EventMapSize int } func New() (flags Flags) { flag.IntVar(&flags.UidFilter, "uid", 0, "Filter for processes with UID") - flag.IntVar(&flags.FdEventMapSize, "fdMapSize", 4096, "BPF FD event map size") - flag.IntVar(&flags.OpenEventMapSize, "openMapSize", 1024, "BPF open event map size") + flag.IntVar(&flags.EventMapSize, "mapSize", 4096, "BPF FD event ring buffer map size") flag.Parse() return flags } @@ -39,17 +37,14 @@ func (flags Flags) SetBPF(bpfModule *bpf.Module) error { } func (flags Flags) ResizeBPFMaps(bpfModule *bpf.Module) error { - if err := resizeBPFMap(bpfModule, "open_event_map", uint32(flags.OpenEventMapSize)); err != nil { - return err - } - if err := resizeBPFMap(bpfModule, "fd_event_map", uint32(flags.FdEventMapSize)); err != nil { - return err + if err := resizeBPFMap(bpfModule, "event_map", uint32(flags.EventMapSize)); err != nil { + return fmt.Errorf("event_map: %w", err) } return nil } func resizeBPFMap(module *bpf.Module, name string, size uint32) error { - m, err := module.GetMap("open_event_map") + m, err := module.GetMap(name) if err != nil { return err } @@ -59,7 +54,7 @@ func resizeBPFMap(module *bpf.Module, name string, size uint32) error { } if actual := m.MaxEntries(); actual != size { - return fmt.Errorf("map resize failed, expected %v, actual %v", size, actual) + return fmt.Errorf("map resize to %d failed, expected %v, actual %v", size, size, actual) } return nil diff --git a/internal/ioriotng.go b/internal/ioriotng.go index d840ea5..f368c09 100644 --- a/internal/ioriotng.go +++ b/internal/ioriotng.go @@ -6,15 +6,12 @@ import ( "bytes" "context" "encoding/binary" - "fmt" "log" "runtime" - "sync" "ioriotng/internal/debugfs" "ioriotng/internal/flags" "ioriotng/internal/tracepoints" - "ioriotng/internal/types" bpf "github.com/aquasecurity/libbpfgo" ) @@ -50,25 +47,43 @@ func Run(flags flags.Flags) { log.Fatal(err) } - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - var wg sync.WaitGroup - wg.Add(2) + ch := make(chan []byte) + rb, err := bpfModule.InitRingBuf("event_map", ch) + if err != nil { + log.Fatal(err) + } + rb.Poll(300) - go func() { - defer wg.Done() - for ev := range listenToEvents[types.FdEvent](ctx, bpfModule, "fd_event_map") { - fmt.Println(ev) - } - }() - go func() { - defer wg.Done() - for ev := range listenToEvents[types.OpenEvent](ctx, bpfModule, "open_event_map") { - fmt.Println(ev) - } - }() + for b := range ch { + /* + if binary.LittleEndian.Uint32(b) != 2021 { + log.Fatal("invalid data retrieved", len(b), b) + } + */ + log.Println("Ringbuf data received", len(b), b) + } + + /* + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + var wg sync.WaitGroup + wg.Add(2) + + go func() { + defer wg.Done() + for ev := range listenToEvents[types.FdEvent](ctx, bpfModule, "fd_event_map") { + fmt.Println(ev) + } + }() + go func() { + defer wg.Done() + for ev := range listenToEvents[types.OpenEvent](ctx, bpfModule, "open_event_map") { + fmt.Println(ev) + } + }() - wg.Wait() + wg.Wait() + */ log.Println("Good bye") } @@ -77,7 +92,7 @@ func listenToEvents[T BpfMapper](ctx context.Context, bpfModule *bpf.Module, map rawLostCh := make(chan uint64) // TODO: Of any use this channel? eventsCh := make(chan T) - pb, err := bpfModule.InitPerfBuf(mapName, rawEventsCh, rawLostCh, 4096) + pb, err := bpfModule.InitPerfBuf(mapName, rawEventsCh, rawLostCh, 1024) if err != nil { log.Fatal(err) } diff --git a/ioriotng.bpf.c b/ioriotng.bpf.c index e4286c2..3eaf160 100644 --- a/ioriotng.bpf.c +++ b/ioriotng.bpf.c @@ -4,6 +4,7 @@ #include "opids.h" #include <bpf/bpf_helpers.h> #include "maps.bpf.h" +#include "ringbufs.bpf.h" static inline int filter() { u32 key = 1; @@ -11,63 +12,53 @@ static inline int filter() { return flagsp == NULL || (bpf_get_current_uid_gid() & 0xFFFFFFFF) != flagsp->uid_filter; } -SEC("tracepoint/syscalls/sys_enter_open") -int handle_enter_open(struct trace_event_raw_sys_enter *ctx) { +SEC("tracepoint/syscalls/sys_enter_openat") +int handle_enter_openat(struct trace_event_raw_sys_enter *ctx) { if (filter()) return 0; - u32 tid = bpf_get_current_pid_tgid(); + struct openat_enter_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct openat_enter_event), 0); + if (!ev) + return 0; - struct open_event open_event = {}; - bpf_probe_read_user_str(open_event.filename, sizeof(open_event.filename), (void *)ctx->args[0]); - bpf_get_current_comm(&open_event.comm, sizeof(open_event.comm)); - open_event.tid = tid; - open_event.enter_time = bpf_ktime_get_ns(); + ev->op_id = OPENAT_ENTER_OP_ID; + ev->tid = bpf_get_current_pid_tgid(); + ev->time = bpf_ktime_get_ns(); - bpf_map_update_elem(&open_event_temp_map, &tid, &open_event, BPF_ANY); + bpf_probe_read_user_str(ev->filename, sizeof(ev->filename), (void *)ctx->args[1]); + bpf_get_current_comm(&ev->comm, sizeof(ev->comm)); + bpf_ringbuf_submit(ev, 0); return 0; } -SEC("tracepoint/syscalls/sys_exit_open") -int handle_exit_open(struct trace_event_raw_sys_exit *ctx) { +SEC("tracepoint/syscalls/sys_exit_openat") +int handle_exit_openat(struct trace_event_raw_sys_exit *ctx) { if (filter()) return 0; - u32 tid = bpf_get_current_pid_tgid(); - struct open_event *open_eventp = bpf_map_lookup_elem(&open_event_temp_map, &tid); - if (!open_eventp) { - return 0; - } - open_eventp->exit_time = bpf_ktime_get_ns(); - open_eventp->fd = ctx->ret; - bpf_perf_event_output(ctx, &open_event_map, BPF_F_CURRENT_CPU, open_eventp, sizeof(struct open_event)); - bpf_map_delete_elem(&open_event_temp_map, &tid); - - return 0; -} - -SEC("tracepoint/syscalls/sys_enter_openat") -int handle_enter_openat(struct trace_event_raw_sys_enter *ctx) { - if (filter()) + struct fd_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct fd_event), 0); + if (!ev) return 0; - u32 tid = bpf_get_current_pid_tgid(); + ev->op_id = OPENAT_EXIT_OP_ID; + ev->tid = bpf_get_current_pid_tgid(); + ev->time = bpf_ktime_get_ns(); + ev->fd = ctx->ret; - struct open_event open_event = {}; - - bpf_probe_read_user_str(open_event.filename, sizeof(open_event.filename), (void *)ctx->args[1]); - bpf_get_current_comm(&open_event.comm, sizeof(open_event.comm)); - open_event.tid = tid; - open_event.enter_time = bpf_ktime_get_ns(); - bpf_map_update_elem(&open_event_temp_map, &tid, &open_event, BPF_ANY); + bpf_ringbuf_submit(ev, 0); return 0; } -SEC("tracepoint/syscalls/sys_exit_openat") -int handle_exit_openat(struct trace_event_raw_sys_exit *ctx) { - return handle_exit_open(ctx); +SEC("tracepoint/syscalls/sys_enter_open") +int handle_enter_open(struct trace_event_raw_sys_enter *ctx) { + return handle_enter_openat(ctx); +} + +SEC("tracepoint/syscalls/sys_exit_open") +int handle_exit_open(struct trace_event_raw_sys_exit *ctx) { + return handle_exit_openat(ctx); } SEC("tracepoint/syscalls/sys_enter_close") @@ -75,16 +66,16 @@ int handle_enter_close(struct trace_event_raw_sys_enter *ctx) { if (filter()) return 0; - u32 tid = bpf_get_current_pid_tgid(); - - struct fd_event event = {}; - event.fd = (int)ctx->args[0]; - event.op_id = CLOSE; - event.tid = tid; - event.enter_time = bpf_ktime_get_ns(); + struct fd_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct fd_event), 0); + if (!ev) + return 0; - bpf_map_update_elem(&fd_event_temp_map, &tid, &event, BPF_ANY); + ev->op_id = CLOSE_ENTER_OP_ID; + ev->tid = bpf_get_current_pid_tgid(); + ev->time = bpf_ktime_get_ns(); + ev->fd = (int)ctx->args[0]; + bpf_ringbuf_submit(ev, 0); return 0; } @@ -93,16 +84,15 @@ int handle_exit_close(struct trace_event_raw_sys_enter *ctx) { if (filter()) return 0; - u32 tid = bpf_get_current_pid_tgid(); - - struct open_event *open_eventp = bpf_map_lookup_elem(&fd_event_temp_map, &tid); - if (!open_eventp) { + struct null_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct null_event), 0); + if (!ev) return 0; - } - open_eventp->exit_time = bpf_ktime_get_ns(); - bpf_perf_event_output(ctx, &fd_event_map, BPF_F_CURRENT_CPU, open_eventp, sizeof(struct fd_event)); - bpf_map_delete_elem(&fd_event_temp_map, &tid); + ev->op_id = CLOSE_EXIT_OP_ID; + ev->tid = bpf_get_current_pid_tgid(); + ev->time = bpf_ktime_get_ns(); + + bpf_ringbuf_submit(ev, 0); return 0; } @@ -8,6 +8,7 @@ struct flags { __u32 uid_filter; }; +// To pass command line flags from userspace to BPF kernel space. struct { __uint(type, BPF_MAP_TYPE_HASH); __type(key, u32); @@ -15,47 +16,33 @@ struct { __uint(max_entries, 1 << 24); } flags_map SEC(".maps"); -struct open_event { - __s32 fd; +#define OPENAT_ENTER_OP_ID 1 +#define OPENAT_EXIT_OP_ID 2 +#define CLOSE_ENTER_OP_ID 1 +#define CLOSE_EXIT_OP_ID 2 + +struct openat_enter_event { + __u32 op_id; __u32 tid; - __u64 enter_time; - __u64 exit_time; + __u64 time; char filename[MAX_FILENAME_LENGTH]; char comm[MAX_PROGNAME_LENGTH]; }; -struct { - __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); - __uint(key_size, sizeof(u32)); - __uint(value_size, sizeof(u32)); -} open_event_map SEC(".maps"); - -// Map to temporarily store the filename from sys_enter_openat -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __uint(key_size, sizeof(u32)); - __uint(value_size, sizeof(struct open_event)); - __uint(max_entries, TEMP_MAP_SIZES); -} open_event_temp_map SEC(".maps"); - struct fd_event { - __s32 fd; - __s32 op_id; + __u32 op_id; __u32 tid; - __u64 enter_time; - __u64 exit_time; + __u64 time; + __s32 fd; }; -struct { - __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); - __uint(key_size, sizeof(u32)); - __uint(value_size, sizeof(u32)); -} fd_event_map SEC(".maps"); +struct null_event { + __u32 op_id; + __u32 tid; + __u64 time; +}; -// Map to temporarily store info from the enter tracepoinut for the exit one struct { - __uint(type, BPF_MAP_TYPE_HASH); - __uint(key_size, sizeof(u32)); - __uint(value_size, sizeof(struct fd_event)); - __uint(max_entries, TEMP_MAP_SIZES); -} fd_event_temp_map SEC(".maps"); + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, 1 << 24); +} event_map SEC(".maps"); |
