From c83ae9d39e3e6dbce6b7a90cbfe267c8fa9294f3 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 22 Jan 2025 10:35:44 +0000 Subject: [PATCH 01/11] tetragon: Move override action code in do_override_action Moving override action code in do_override_action so we can define it only for kprobe and lsm program (GENERIC_KPROBE and GENERIC_LSM) where it belongs. Now it's also part of kretprobe. Signed-off-by: Jiri Olsa --- bpf/process/generic_calls.h | 40 ++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/bpf/process/generic_calls.h b/bpf/process/generic_calls.h index 5f0c5042abd..2ce1d2c5615 100644 --- a/bpf/process/generic_calls.h +++ b/bpf/process/generic_calls.h @@ -216,20 +216,43 @@ generic_process_event_and_setup(struct pt_regs *ctx, struct bpf_map_def *tailcal return generic_process_event(ctx, tailcals); } +#if defined GENERIC_KPROBE || defined GENERIC_LSM +FUNC_INLINE void +do_override_action(__s32 error) +{ + __s32 *error_p; + __u64 id; + + id = get_current_pid_tgid(); + + /* + * TODO: this should not happen, it means that the override + * program was not executed for some reason, we should do + * warning in here + */ + error_p = map_lookup_elem(&override_tasks, &id); + if (error_p) + *error_p = error; + else + map_update_elem(&override_tasks, &id, &error, BPF_ANY); +} +#else +#define do_override_action(error) +#endif + FUNC_LOCAL __u32 do_action(void *ctx, __u32 i, struct selector_action *actions, bool *post) { int signal __maybe_unused = FGS_SIGKILL; int action = actions->act[i]; struct msg_generic_kprobe *e; - __s32 error, *error_p; + __s32 error __maybe_unused; int fdi, namei; int newfdi, oldfdi; int socki; int argi __maybe_unused; int err = 0; int zero = 0; - __u64 id; e = map_lookup_elem(&process_call_heap, &zero); if (!e) @@ -293,18 +316,7 @@ do_action(void *ctx, __u32 i, struct selector_action *actions, bool *post) break; case ACTION_OVERRIDE: error = actions->act[++i]; - id = get_current_pid_tgid(); - - /* - * TODO: this should not happen, it means that the override - * program was not executed for some reason, we should do - * warning in here - */ - error_p = map_lookup_elem(&override_tasks, &id); - if (error_p) - *error_p = error; - else - map_update_elem(&override_tasks, &id, &error, BPF_ANY); + do_override_action(error); break; case ACTION_GETURL: case ACTION_DNSLOOKUP: From aff4b059b40e87ba5c046804ee43a12ea0476f7c Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 13 Jan 2025 13:52:29 +0000 Subject: [PATCH 02/11] tetragon: Move SizeWithSuffix to strutils package Moving SizeWithSuffix to strutils package, so we can use it from other places. Signed-off-by: Jiri Olsa --- pkg/observer/observer.go | 19 ++++--------------- pkg/strutils/strutls.go | 13 +++++++++++++ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/pkg/observer/observer.go b/pkg/observer/observer.go index 1b5853f2582..4480424a078 100644 --- a/pkg/observer/observer.go +++ b/pkg/observer/observer.go @@ -26,6 +26,7 @@ import ( "github.com/cilium/tetragon/pkg/reader/notify" "github.com/cilium/tetragon/pkg/sensors" "github.com/cilium/tetragon/pkg/sensors/config/confmap" + "github.com/cilium/tetragon/pkg/strutils" "github.com/prometheus/client_golang/prometheus" dto "github.com/prometheus/client_model/go" @@ -158,18 +159,6 @@ func perfBufferSize(perCPUBuffer int) int { return nPages * pageSize } -func sizeWithSuffix(size int) string { - suffix := [4]string{"", "K", "M", "G"} - - i := 0 - for size > 1024 && i < 3 { - size = size / 1024 - i++ - } - - return fmt.Sprintf("%d%s", size, suffix[i]) -} - func (k *Observer) getRBSize(cpus int) int { var size int @@ -184,8 +173,8 @@ func (k *Observer) getRBSize(cpus int) int { cpuSize := perfBufferSize(size) totalSize := cpuSize * cpus - k.log.WithField("percpu", sizeWithSuffix(cpuSize)). - WithField("total", sizeWithSuffix(totalSize)). + k.log.WithField("percpu", strutils.SizeWithSuffix(cpuSize)). + WithField("total", strutils.SizeWithSuffix(totalSize)). Info("Perf ring buffer size (bytes)") return size } @@ -195,7 +184,7 @@ func (k *Observer) getRBQueueSize() int { if size == 0 { size = 65535 } - k.log.WithField("size", sizeWithSuffix(size)). + k.log.WithField("size", strutils.SizeWithSuffix(size)). Info("Perf ring buffer events queue size (events)") return size } diff --git a/pkg/strutils/strutls.go b/pkg/strutils/strutls.go index 6e2fd2f56ff..d5b9fd0d922 100644 --- a/pkg/strutils/strutls.go +++ b/pkg/strutils/strutls.go @@ -4,6 +4,7 @@ package strutils import ( + "fmt" "strconv" "strings" ) @@ -50,3 +51,15 @@ func ParseSize(str string) (int, error) { // never reached return 0, nil } + +func SizeWithSuffix(size int) string { + suffix := [4]string{"", "K", "M", "G"} + + i := 0 + for size > 1024 && i < 3 { + size = size / 1024 + i++ + } + + return fmt.Sprintf("%d%s", size, suffix[i]) +} From b03de3cf85345692f39de4d67941b90c69ce69f3 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 22 Jan 2025 11:04:43 +0000 Subject: [PATCH 03/11] tetragon: Make sure mapBuilder won't panic on empty lds array It's possible to omit programs when we create map in which case we explode. Adding check for that. Signed-off-by: Jiri Olsa --- pkg/sensors/program/map.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/sensors/program/map.go b/pkg/sensors/program/map.go index 82f34d0f61f..70278b3006f 100644 --- a/pkg/sensors/program/map.go +++ b/pkg/sensors/program/map.go @@ -159,7 +159,11 @@ func DeleteGlobMap(name string) { // ... // p.PinMap["mapX"] = &mapX func mapBuilder(name string, ty MapType, owner bool, lds ...*Program) *Map { - m := &Map{name, "", lds[0], Idle(), nil, MaxEntries{0, false}, MaxEntries{0, false}, ty, owner} + var prog *Program + if len(lds) != 0 { + prog = lds[0] + } + m := &Map{name, "", prog, Idle(), nil, MaxEntries{0, false}, MaxEntries{0, false}, ty, owner} for _, ld := range lds { ld.PinMap[name] = m } From f10f1c59bb2ad219af4ac68ded4616a44fe3ce57 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 10 Jan 2025 08:45:21 +0000 Subject: [PATCH 04/11] tetragon: Add TAIL_CALL_SETUP tail call index Adding TAIL_CALL_SETUP tail call index, which was missing in the TAIL_CALL_* enum values. Signed-off-by: Jiri Olsa --- bpf/process/bpf_generic_kprobe.c | 2 +- bpf/process/bpf_generic_lsm_core.c | 2 +- bpf/process/bpf_generic_uprobe.c | 2 +- bpf/process/types/basic.h | 1 + 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/bpf/process/bpf_generic_kprobe.c b/bpf/process/bpf_generic_kprobe.c index f5fe12f041d..59e247b5ba7 100644 --- a/bpf/process/bpf_generic_kprobe.c +++ b/bpf/process/bpf_generic_kprobe.c @@ -100,7 +100,7 @@ generic_kprobe_process_filter(void *ctx) if (ret == PFILTER_CONTINUE) tail_call(ctx, &kprobe_calls, TAIL_CALL_FILTER); else if (ret == PFILTER_ACCEPT) - tail_call(ctx, &kprobe_calls, 0); + tail_call(ctx, &kprobe_calls, TAIL_CALL_SETUP); /* If filter does not accept drop it. Ideally we would * log error codes for later review, TBD. */ diff --git a/bpf/process/bpf_generic_lsm_core.c b/bpf/process/bpf_generic_lsm_core.c index 04b99806d13..66dce4a1a8c 100644 --- a/bpf/process/bpf_generic_lsm_core.c +++ b/bpf/process/bpf_generic_lsm_core.c @@ -71,7 +71,7 @@ generic_lsm_process_filter(void *ctx) if (ret == PFILTER_CONTINUE) tail_call(ctx, &lsm_calls, TAIL_CALL_FILTER); else if (ret == PFILTER_ACCEPT) - tail_call(ctx, &lsm_calls, 0); + tail_call(ctx, &lsm_calls, TAIL_CALL_SETUP); return PFILTER_REJECT; } diff --git a/bpf/process/bpf_generic_uprobe.c b/bpf/process/bpf_generic_uprobe.c index 8f2b722b70b..2d225b20dd7 100644 --- a/bpf/process/bpf_generic_uprobe.c +++ b/bpf/process/bpf_generic_uprobe.c @@ -74,7 +74,7 @@ generic_uprobe_process_filter(void *ctx) if (ret == PFILTER_CONTINUE) tail_call(ctx, &uprobe_calls, TAIL_CALL_FILTER); else if (ret == PFILTER_ACCEPT) - tail_call(ctx, &uprobe_calls, 0); + tail_call(ctx, &uprobe_calls, TAIL_CALL_SETUP); /* If filter does not accept drop it. Ideally we would * log error codes for later review, TBD. */ diff --git a/bpf/process/types/basic.h b/bpf/process/types/basic.h index 7434734ea35..5cea0a7c505 100644 --- a/bpf/process/types/basic.h +++ b/bpf/process/types/basic.h @@ -117,6 +117,7 @@ enum { }; enum { + TAIL_CALL_SETUP = 0, TAIL_CALL_PROCESS = 1, TAIL_CALL_FILTER = 2, TAIL_CALL_ARGS = 3, From 53b23c241312ebc309d7b5621b58cc8ecdee9b07 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 10 Jan 2025 09:54:28 +0000 Subject: [PATCH 05/11] tetragon: Factor generic_process_filter function Switch 'enter' check to '!enter' and decrease indent of the following code, which makes the function more readable and will ease up following changes. There's no functional change. Signed-off-by: Jiri Olsa --- bpf/process/generic_calls.h | 70 ++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/bpf/process/generic_calls.h b/bpf/process/generic_calls.h index 2ce1d2c5615..d1f8aec37dc 100644 --- a/bpf/process/generic_calls.h +++ b/bpf/process/generic_calls.h @@ -570,59 +570,57 @@ FUNC_INLINE int generic_retkprobe(void *ctx, struct bpf_map_def *calls, unsigned // msg_generic_hdr structure. FUNC_INLINE int generic_process_filter(void) { + int selectors, pass, curr, zero = 0; struct execve_map_value *enter; struct msg_generic_kprobe *msg; struct msg_execve_key *current; struct msg_selector_data *sel; - int curr, zero = 0; bool walker = 0; - __u32 ppid; + __u32 ppid, *f; msg = map_lookup_elem(&process_call_heap, &zero); if (!msg) return 0; enter = event_find_curr(&ppid, &walker); - if (enter) { - int selectors, pass; - __u32 *f = map_lookup_elem(&filter_map, &msg->idx); + if (!enter) + return PFILTER_CURR_NOT_FOUND; - if (!f) - return PFILTER_ERROR; + f = map_lookup_elem(&filter_map, &msg->idx); + if (!f) + return PFILTER_ERROR; - sel = &msg->sel; - current = &msg->current; + sel = &msg->sel; + current = &msg->current; - curr = sel->curr; - if (curr > MAX_SELECTORS) - return process_filter_done(sel, enter, current); + curr = sel->curr; + if (curr > MAX_SELECTORS) + return process_filter_done(sel, enter, current); - selectors = f[0]; - /* If no selectors accept process */ - if (!selectors) { - sel->pass = true; - return process_filter_done(sel, enter, current); - } + selectors = f[0]; + /* If no selectors accept process */ + if (!selectors) { + sel->pass = true; + return process_filter_done(sel, enter, current); + } - /* If we get here with reference to uninitialized selector drop */ - if (selectors <= curr) - return process_filter_done(sel, enter, current); - - pass = selector_process_filter(f, curr, enter, msg); - if (pass) { - /* Verify lost that msg is not null here so recheck */ - asm volatile("%[curr] &= 0x1f;\n" - : [curr] "+r"(curr)); - sel->active[curr] = true; - sel->active[SELECTORS_ACTIVE] = true; - sel->pass |= true; - } - sel->curr++; - if (sel->curr > selectors) - return process_filter_done(sel, enter, current); - return PFILTER_CONTINUE; /* will iterate to the next selector */ + /* If we get here with reference to uninitialized selector drop */ + if (selectors <= curr) + return process_filter_done(sel, enter, current); + + pass = selector_process_filter(f, curr, enter, msg); + if (pass) { + /* Verify lost that msg is not null here so recheck */ + asm volatile("%[curr] &= 0x1f;\n" + : [curr] "+r"(curr)); + sel->active[curr] = true; + sel->active[SELECTORS_ACTIVE] = true; + sel->pass |= true; } - return PFILTER_CURR_NOT_FOUND; + sel->curr++; + if (sel->curr > selectors) + return process_filter_done(sel, enter, current); + return PFILTER_CONTINUE; /* will iterate to the next selector */ } FUNC_INLINE int filter_args(struct msg_generic_kprobe *e, int selidx, bool is_entry) From cd19fa1328e6198b83ca45934f67633b18d75668 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 10 Jan 2025 11:26:45 +0000 Subject: [PATCH 06/11] tetragon: Pass execve_map_value directly to match_binaries Passing execve_map_value directly to match_binaries to eliminate superfluous event_find_curr in it. Signed-off-by: Jiri Olsa --- bpf/process/pfilter.h | 2 +- bpf/process/types/basic.h | 12 ++---------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/bpf/process/pfilter.h b/bpf/process/pfilter.h index bdd90b7f930..bbdf7adbbbe 100644 --- a/bpf/process/pfilter.h +++ b/bpf/process/pfilter.h @@ -409,7 +409,7 @@ selector_process_filter(__u32 *f, __u32 index, struct execve_map_value *enter, __u64 i; /* Do binary filter first for selector index */ - if (!match_binaries(index)) + if (!match_binaries(index, enter)) return 0; /* Find selector offset byte index */ diff --git a/bpf/process/types/basic.h b/bpf/process/types/basic.h index 5cea0a7c505..84ef549480e 100644 --- a/bpf/process/types/basic.h +++ b/bpf/process/types/basic.h @@ -1543,11 +1543,9 @@ struct { }); } tg_mb_paths SEC(".maps"); -FUNC_INLINE int match_binaries(__u32 selidx) +FUNC_INLINE int match_binaries(__u32 selidx, struct execve_map_value *current) { - struct execve_map_value *current; - __u32 ppid; - bool walker, match = 0; + bool match = 0; void *path_map; __u8 *found_key; #ifdef __LARGE_BPF_PROG @@ -1567,12 +1565,6 @@ FUNC_INLINE int match_binaries(__u32 selidx) if (selector_options->op == op_filter_none) return 1; // matchBinaries selector is empty <=> match - current = event_find_curr(&ppid, &walker); - if (!current) { - // this should not happen, it means that the process was missed when - // scanning /proc for process that started before and after tetragon - return 0; - } if (current->bin.path_length < 0) { // something wrong happened when copying the filename to execve_map return 0; From b1f39f557d698406ce124322138a90d7924074be Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 22 Jan 2025 09:20:00 +0000 Subject: [PATCH 07/11] tetragon: Add Maps array to loader LoadOpts object Signed-off-by: Jiri Olsa --- pkg/sensors/program/loader.go | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/pkg/sensors/program/loader.go b/pkg/sensors/program/loader.go index 01958701095..ad93dd19b0d 100644 --- a/pkg/sensors/program/loader.go +++ b/pkg/sensors/program/loader.go @@ -28,6 +28,7 @@ type OpenFunc func(*ebpf.CollectionSpec) error type LoadOpts struct { Attach AttachFunc Open OpenFunc + Maps []*Map } func linkPinPath(bpfDir string, load *Program, extra ...string) string { @@ -799,8 +800,24 @@ func doLoadProgram( } } + maps := map[string]*Map{} + for _, pm := range loadOpts.Maps { + if !pm.IsOwner() { + maps[pm.Name] = pm + } + } + + getMap := func(name string) (*Map, bool) { + m, ok := load.PinMap[name] + if ok { + return m, true + } + m, ok = maps[name] + return m, ok + } + for _, ms := range spec.Maps { - m, ok := load.PinMap[ms.Name] + m, ok := getMap(ms.Name) if !ok { continue } @@ -842,7 +859,8 @@ func doLoadProgram( var m *ebpf.Map var err error var mapPath string - if pm, ok := load.PinMap[name]; ok { + + if pm, ok := getMap(name); ok { mapPath = filepath.Join(bpfDir, pm.PinPath) } else { mapPath = filepath.Join(bpfDir, name) @@ -945,6 +963,7 @@ func doLoadProgram( for _, mapLoad := range load.MapLoad { pinPath := "" + // We allow to load only maps that we own. if pm, ok := load.PinMap[mapLoad.Name]; ok { pinPath = pm.PinPath } From 6d98e6d8956cc392d1f9544ede5c9d717d7032f6 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 22 Jan 2025 10:04:05 +0000 Subject: [PATCH 08/11] tetragon: Pass maps from sensor to program loader Signed-off-by: Jiri Olsa --- pkg/sensors/exec/exec.go | 2 +- pkg/sensors/load.go | 19 +++++++------ pkg/sensors/program/cgroup/cgroup.go | 8 +++--- pkg/sensors/program/loader.go | 36 ++++++++++++++++-------- pkg/sensors/sensors.go | 3 +- pkg/sensors/tracing/enforcer.go | 14 ++++----- pkg/sensors/tracing/generickprobe.go | 16 +++++------ pkg/sensors/tracing/genericlsm.go | 2 +- pkg/sensors/tracing/generictracepoint.go | 6 ++-- pkg/sensors/tracing/genericuprobe.go | 4 +-- pkg/sensors/tracing/loader.go | 2 +- 11 files changed, 63 insertions(+), 49 deletions(-) diff --git a/pkg/sensors/exec/exec.go b/pkg/sensors/exec/exec.go index c9da56c8bb8..693da110106 100644 --- a/pkg/sensors/exec/exec.go +++ b/pkg/sensors/exec/exec.go @@ -261,7 +261,7 @@ func handleThrottleEvent(r *bytes.Reader) ([]observer.Event, error) { type execProbe struct{} func (e *execProbe) LoadProbe(args sensors.LoadProbeArgs) error { - return program.LoadTracepointProgram(args.BPFDir, args.Load, args.Verbose) + return program.LoadTracepointProgram(args.BPFDir, args.Load, args.Maps, args.Verbose) } func init() { diff --git a/pkg/sensors/load.go b/pkg/sensors/load.go index abf3a3b220a..6f796b3e12e 100644 --- a/pkg/sensors/load.go +++ b/pkg/sensors/load.go @@ -170,7 +170,7 @@ func (s *Sensor) Load(bpfDir string) (err error) { continue } - if err = observerLoadInstance(bpfDir, p); err != nil { + if err = observerLoadInstance(bpfDir, p, s.Maps); err != nil { return err } p.LoadState.RefInc() @@ -408,7 +408,7 @@ func mergeSensors(sensors []*Sensor) *Sensor { } } -func observerLoadInstance(bpfDir string, load *program.Program) error { +func observerLoadInstance(bpfDir string, load *program.Program, maps []*program.Map) error { version, _, err := kernels.GetKernelVersion(option.Config.KernelVersion, option.Config.ProcFS) if err != nil { return err @@ -420,33 +420,33 @@ func observerLoadInstance(bpfDir string, load *program.Program) error { "kern_version": version, }).Debugf("observerLoadInstance %s %d", load.Name, version) if load.Type == "tracepoint" { - err = loadInstance(bpfDir, load, version, option.Config.Verbosity) + err = loadInstance(bpfDir, load, maps, version, option.Config.Verbosity) if err != nil { l.WithField( "tracepoint", load.Name, ).Info("Failed to load, trying to remove and retrying") load.Unload(true) - err = loadInstance(bpfDir, load, version, option.Config.Verbosity) + err = loadInstance(bpfDir, load, maps, version, option.Config.Verbosity) } if err != nil { return fmt.Errorf("failed prog %s kern_version %d LoadTracingProgram: %w", load.Name, version, err) } } else if load.Type == "raw_tracepoint" || load.Type == "raw_tp" { - err = loadInstance(bpfDir, load, version, option.Config.Verbosity) + err = loadInstance(bpfDir, load, maps, version, option.Config.Verbosity) if err != nil { l.WithField( "raw_tracepoint", load.Name, ).Info("Failed to load, trying to remove and retrying") load.Unload(true) - err = loadInstance(bpfDir, load, version, option.Config.Verbosity) + err = loadInstance(bpfDir, load, maps, version, option.Config.Verbosity) } if err != nil { return fmt.Errorf("failed prog %s kern_version %d LoadRawTracepointProgram: %w", load.Name, version, err) } } else { - err = loadInstance(bpfDir, load, version, option.Config.Verbosity) + err = loadInstance(bpfDir, load, maps, version, option.Config.Verbosity) if err != nil && load.ErrorFatal { return fmt.Errorf("failed prog %s kern_version %d loadInstance: %w", load.Name, version, err) @@ -455,7 +455,7 @@ func observerLoadInstance(bpfDir string, load *program.Program) error { return nil } -func loadInstance(bpfDir string, load *program.Program, version, verbose int) error { +func loadInstance(bpfDir string, load *program.Program, maps []*program.Map, version, verbose int) error { // Check if the load.type is a standard program type. If so, use the standard loader. loadFn, ok := standardTypes[load.Type] if ok { @@ -463,7 +463,7 @@ func loadInstance(bpfDir string, load *program.Program, version, verbose int) er WithField("Type", load.Type). WithField("Attach", load.Attach). Debug("Loading BPF program") - return loadFn(bpfDir, load, verbose) + return loadFn(bpfDir, load, maps, verbose) } // Otherwise, check for a registered probe type. If one exists, use that. probe, ok := registeredProbeLoad[load.Type] @@ -479,6 +479,7 @@ func loadInstance(bpfDir string, load *program.Program, version, verbose int) er Load: load, Version: version, Verbose: verbose, + Maps: maps, }) } diff --git a/pkg/sensors/program/cgroup/cgroup.go b/pkg/sensors/program/cgroup/cgroup.go index a924155b874..2c5e6b81bf8 100644 --- a/pkg/sensors/program/cgroup/cgroup.go +++ b/pkg/sensors/program/cgroup/cgroup.go @@ -20,14 +20,14 @@ var ( func LoadSockOpt( bpfDir string, - load *program.Program, verbose int, + load *program.Program, maps []*program.Map, verbose int, ) error { - return LoadCgroupProgram(bpfDir, load, verbose) + return LoadCgroupProgram(bpfDir, load, maps, verbose) } func LoadCgroupProgram( bpfDir string, - load *program.Program, verbose int) error { + load *program.Program, maps []*program.Map, verbose int) error { if fgsCgroupFD < 0 { fd, err := unix.Open(fgsCgroupPath, unix.O_RDONLY, 0) if err != nil { @@ -35,5 +35,5 @@ func LoadCgroupProgram( } fgsCgroupFD = fd } - return program.LoadProgram(bpfDir, load, program.RawAttach(fgsCgroupFD), verbose) + return program.LoadProgram(bpfDir, load, maps, program.RawAttach(fgsCgroupFD), verbose) } diff --git a/pkg/sensors/program/loader.go b/pkg/sensors/program/loader.go index ad93dd19b0d..34b25809ebe 100644 --- a/pkg/sensors/program/loader.go +++ b/pkg/sensors/program/loader.go @@ -527,24 +527,27 @@ func MultiKprobeAttach(load *Program, bpfDir string) AttachFunc { } } -func LoadTracepointProgram(bpfDir string, load *Program, verbose int) error { +func LoadTracepointProgram(bpfDir string, load *Program, maps []*Map, verbose int) error { opts := &LoadOpts{ Attach: TracepointAttach(load, bpfDir), + Maps: maps, } return loadProgram(bpfDir, load, opts, verbose) } -func LoadRawTracepointProgram(bpfDir string, load *Program, verbose int) error { +func LoadRawTracepointProgram(bpfDir string, load *Program, maps []*Map, verbose int) error { opts := &LoadOpts{ Attach: RawTracepointAttach(load), + Maps: maps, } return loadProgram(bpfDir, load, opts, verbose) } -func LoadKprobeProgram(bpfDir string, load *Program, verbose int) error { +func LoadKprobeProgram(bpfDir string, load *Program, maps []*Map, verbose int) error { opts := &LoadOpts{ Attach: KprobeAttach(load, bpfDir), Open: KprobeOpen(load), + Maps: maps, } return loadProgram(bpfDir, load, opts, verbose) } @@ -571,29 +574,32 @@ func KprobeAttachMany(load *Program, syms []string, bpfDir string) AttachFunc { } } -func LoadKprobeProgramAttachMany(bpfDir string, load *Program, syms []string, verbose int) error { +func LoadKprobeProgramAttachMany(bpfDir string, load *Program, syms []string, maps []*Map, verbose int) error { opts := &LoadOpts{ Attach: KprobeAttachMany(load, syms, bpfDir), + Maps: maps, } return loadProgram(bpfDir, load, opts, verbose) } -func LoadUprobeProgram(bpfDir string, load *Program, verbose int) error { +func LoadUprobeProgram(bpfDir string, load *Program, maps []*Map, verbose int) error { opts := &LoadOpts{ Attach: UprobeAttach(load), + Maps: maps, } return loadProgram(bpfDir, load, opts, verbose) } -func LoadMultiKprobeProgram(bpfDir string, load *Program, verbose int) error { +func LoadMultiKprobeProgram(bpfDir string, load *Program, maps []*Map, verbose int) error { opts := &LoadOpts{ Attach: MultiKprobeAttach(load, bpfDir), Open: KprobeOpen(load), + Maps: maps, } return loadProgram(bpfDir, load, opts, verbose) } -func LoadFmodRetProgram(bpfDir string, load *Program, progName string, verbose int) error { +func LoadFmodRetProgram(bpfDir string, load *Program, maps []*Map, progName string, verbose int) error { opts := &LoadOpts{ Attach: func( _ *ebpf.Collection, @@ -625,35 +631,40 @@ func LoadFmodRetProgram(bpfDir string, load *Program, progName string, verbose i progSpec.AttachTo = load.Attach return nil }, + Maps: maps, } return loadProgram(bpfDir, load, opts, verbose) } -func LoadTracingProgram(bpfDir string, load *Program, verbose int) error { +func LoadTracingProgram(bpfDir string, load *Program, maps []*Map, verbose int) error { opts := &LoadOpts{ Attach: TracingAttach(), + Maps: maps, } return loadProgram(bpfDir, load, opts, verbose) } -func LoadLSMProgram(bpfDir string, load *Program, verbose int) error { +func LoadLSMProgram(bpfDir string, load *Program, maps []*Map, verbose int) error { opts := &LoadOpts{ Attach: LSMAttach(), Open: LSMOpen(load), + Maps: maps, } return loadProgram(bpfDir, load, opts, verbose) } -func LoadLSMProgramSimple(bpfDir string, load *Program, verbose int) error { +func LoadLSMProgramSimple(bpfDir string, load *Program, maps []*Map, verbose int) error { opts := &LoadOpts{ Attach: LSMAttach(), + Maps: maps, } return loadProgram(bpfDir, load, opts, verbose) } -func LoadMultiUprobeProgram(bpfDir string, load *Program, verbose int) error { +func LoadMultiUprobeProgram(bpfDir string, load *Program, maps []*Map, verbose int) error { opts := &LoadOpts{ Attach: MultiUprobeAttach(load), + Maps: maps, } return loadProgram(bpfDir, load, opts, verbose) } @@ -1072,10 +1083,11 @@ func loadProgram( func LoadProgram( bpfDir string, load *Program, + maps []*Map, attach AttachFunc, verbose int, ) error { - return loadProgram(bpfDir, load, &LoadOpts{Attach: attach}, verbose) + return loadProgram(bpfDir, load, &LoadOpts{Attach: attach, Maps: maps}, verbose) } func LoadProgramOpts( diff --git a/pkg/sensors/sensors.go b/pkg/sensors/sensors.go index 8cd741f94ad..e2a9cfa1f2d 100644 --- a/pkg/sensors/sensors.go +++ b/pkg/sensors/sensors.go @@ -223,7 +223,7 @@ var ( registeredPolicyHandlers = map[string]policyHandler{} // list of registers loaders, see registerProbeType() registeredProbeLoad = map[string]probeLoader{} - standardTypes = map[string]func(string, *program.Program, int) error{ + standardTypes = map[string]func(string, *program.Program, []*program.Map, int) error{ "tracepoint": program.LoadTracepointProgram, "raw_tracepoint": program.LoadRawTracepointProgram, "raw_tp": program.LoadRawTracepointProgram, @@ -257,6 +257,7 @@ func RegisterProbeType(probeType string, s probeLoader) { type LoadProbeArgs struct { BPFDir string Load *program.Program + Maps []*program.Map Version, Verbose int } diff --git a/pkg/sensors/tracing/enforcer.go b/pkg/sensors/tracing/enforcer.go index 7e154316622..7355dd14fff 100644 --- a/pkg/sensors/tracing/enforcer.go +++ b/pkg/sensors/tracing/enforcer.go @@ -122,9 +122,9 @@ func (kp *enforcerPolicy) PolicyHandler( func (kp *enforcerPolicy) loadSingleEnforcerSensor( kh *enforcerHandler, - bpfDir string, load *program.Program, verbose int, + bpfDir string, load *program.Program, maps []*program.Map, verbose int, ) error { - if err := program.LoadKprobeProgramAttachMany(bpfDir, load, kh.syscallsSyms, verbose); err == nil { + if err := program.LoadKprobeProgramAttachMany(bpfDir, load, kh.syscallsSyms, maps, verbose); err == nil { logger.GetLogger().Infof("Loaded enforcer sensor: %s", load.Attach) } else { return err @@ -134,7 +134,7 @@ func (kp *enforcerPolicy) loadSingleEnforcerSensor( func (kp *enforcerPolicy) loadMultiEnforcerSensor( kh *enforcerHandler, - bpfDir string, load *program.Program, verbose int, + bpfDir string, load *program.Program, maps []*program.Map, verbose int, ) error { data := &program.MultiKprobeAttachData{} @@ -142,7 +142,7 @@ func (kp *enforcerPolicy) loadMultiEnforcerSensor( load.SetAttachData(data) - if err := program.LoadMultiKprobeProgram(bpfDir, load, verbose); err != nil { + if err := program.LoadMultiKprobeProgram(bpfDir, load, maps, verbose); err != nil { return err } @@ -161,14 +161,14 @@ func (kp *enforcerPolicy) LoadProbe(args sensors.LoadProbeArgs) error { return fmt.Errorf("failed to get enforcer handler for '%s'", name) } if args.Load.Label == "kprobe.multi/enforcer" { - return kp.loadMultiEnforcerSensor(kh, args.BPFDir, args.Load, args.Verbose) + return kp.loadMultiEnforcerSensor(kh, args.BPFDir, args.Load, args.Maps, args.Verbose) } if args.Load.Label == "kprobe/enforcer" { - return kp.loadSingleEnforcerSensor(kh, args.BPFDir, args.Load, args.Verbose) + return kp.loadSingleEnforcerSensor(kh, args.BPFDir, args.Load, args.Maps, args.Verbose) } if strings.HasPrefix(args.Load.Label, "fmod_ret/") { - return program.LoadFmodRetProgram(args.BPFDir, args.Load, "fmodret_enforcer", args.Verbose) + return program.LoadFmodRetProgram(args.BPFDir, args.Load, args.Maps, "fmodret_enforcer", args.Verbose) } return fmt.Errorf("enforcer loader: unknown label: %s", args.Load.Label) diff --git a/pkg/sensors/tracing/generickprobe.go b/pkg/sensors/tracing/generickprobe.go index 0b7a7f97222..40a22551938 100644 --- a/pkg/sensors/tracing/generickprobe.go +++ b/pkg/sensors/tracing/generickprobe.go @@ -1088,7 +1088,7 @@ func getMapLoad(load *program.Program, kprobeEntry *genericKprobe, index uint32) return selectorsMaploads(state, index) } -func loadSingleKprobeSensor(id idtable.EntryID, bpfDir string, load *program.Program, verbose int) error { +func loadSingleKprobeSensor(id idtable.EntryID, bpfDir string, load *program.Program, maps []*program.Map, verbose int) error { gk, err := genericKprobeTableGet(id) if err != nil { return err @@ -1107,7 +1107,7 @@ func loadSingleKprobeSensor(id idtable.EntryID, bpfDir string, load *program.Pro } load.MapLoad = append(load.MapLoad, config) - if err := program.LoadKprobeProgram(bpfDir, load, verbose); err == nil { + if err := program.LoadKprobeProgram(bpfDir, load, maps, verbose); err == nil { logger.GetLogger().Infof("Loaded generic kprobe program: %s -> %s", load.Name, load.Attach) } else { return err @@ -1116,7 +1116,7 @@ func loadSingleKprobeSensor(id idtable.EntryID, bpfDir string, load *program.Pro return err } -func loadMultiKprobeSensor(ids []idtable.EntryID, bpfDir string, load *program.Program, verbose int) error { +func loadMultiKprobeSensor(ids []idtable.EntryID, bpfDir string, load *program.Program, maps []*program.Map, verbose int) error { bin_buf := make([]bytes.Buffer, len(ids)) data := &program.MultiKprobeAttachData{} @@ -1151,7 +1151,7 @@ func loadMultiKprobeSensor(ids []idtable.EntryID, bpfDir string, load *program.P load.OverrideFmodRet = false load.SetAttachData(data) - if err := program.LoadMultiKprobeProgram(bpfDir, load, verbose); err == nil { + if err := program.LoadMultiKprobeProgram(bpfDir, load, maps, verbose); err == nil { logger.GetLogger().Infof("Loaded generic kprobe sensor: %s -> %s", load.Name, load.Attach) } else { return err @@ -1160,12 +1160,12 @@ func loadMultiKprobeSensor(ids []idtable.EntryID, bpfDir string, load *program.P return nil } -func loadGenericKprobeSensor(bpfDir string, load *program.Program, verbose int) error { +func loadGenericKprobeSensor(bpfDir string, load *program.Program, maps []*program.Map, verbose int) error { if id, ok := load.LoaderData.(idtable.EntryID); ok { - return loadSingleKprobeSensor(id, bpfDir, load, verbose) + return loadSingleKprobeSensor(id, bpfDir, load, maps, verbose) } if ids, ok := load.LoaderData.([]idtable.EntryID); ok { - return loadMultiKprobeSensor(ids, bpfDir, load, verbose) + return loadMultiKprobeSensor(ids, bpfDir, load, maps, verbose) } return fmt.Errorf("invalid loadData type: expecting idtable.EntryID/[] and got: %T (%v)", load.LoaderData, load.LoaderData) @@ -1389,7 +1389,7 @@ func retprobeMerge(prev pendingEvent, curr pendingEvent) *tracing.MsgGenericKpro } func (k *observerKprobeSensor) LoadProbe(args sensors.LoadProbeArgs) error { - return loadGenericKprobeSensor(args.BPFDir, args.Load, args.Verbose) + return loadGenericKprobeSensor(args.BPFDir, args.Load, args.Maps, args.Verbose) } func selectorsHaveRateLimit(selectors []v1alpha1.KProbeSelector) bool { diff --git a/pkg/sensors/tracing/genericlsm.go b/pkg/sensors/tracing/genericlsm.go index 699ba08b2ea..1f2a59268fd 100644 --- a/pkg/sensors/tracing/genericlsm.go +++ b/pkg/sensors/tracing/genericlsm.go @@ -99,7 +99,7 @@ func (k *observerLsmSensor) LoadProbe(args sensors.LoadProbeArgs) error { } args.Load.MapLoad = append(args.Load.MapLoad, config) - if err := program.LoadLSMProgram(args.BPFDir, args.Load, args.Verbose); err == nil { + if err := program.LoadLSMProgram(args.BPFDir, args.Load, args.Maps, args.Verbose); err == nil { logger.GetLogger().Infof("Loaded generic LSM program: %s -> %s", args.Load.Name, args.Load.Attach) } else { return err diff --git a/pkg/sensors/tracing/generictracepoint.go b/pkg/sensors/tracing/generictracepoint.go index 2ddab7967ea..0c991a65e5d 100644 --- a/pkg/sensors/tracing/generictracepoint.go +++ b/pkg/sensors/tracing/generictracepoint.go @@ -672,7 +672,7 @@ func (tp *genericTracepoint) EventConfig() (api.EventConfig, error) { return config, nil } -func LoadGenericTracepointSensor(bpfDir string, load *program.Program, verbose int) error { +func LoadGenericTracepointSensor(bpfDir string, load *program.Program, maps []*program.Map, verbose int) error { tracepointLog = logger.GetLogger() @@ -703,7 +703,7 @@ func LoadGenericTracepointSensor(bpfDir string, load *program.Program, verbose i } load.MapLoad = append(load.MapLoad, cfg) - if err := program.LoadTracepointProgram(bpfDir, load, verbose); err == nil { + if err := program.LoadTracepointProgram(bpfDir, load, maps, verbose); err == nil { logger.GetLogger().Infof("Loaded generic tracepoint program: %s -> %s", load.Name, load.Attach) } else { return err @@ -924,5 +924,5 @@ func handleMsgGenericTracepoint( } func (t *observerTracepointSensor) LoadProbe(args sensors.LoadProbeArgs) error { - return LoadGenericTracepointSensor(args.BPFDir, args.Load, args.Verbose) + return LoadGenericTracepointSensor(args.BPFDir, args.Load, args.Maps, args.Verbose) } diff --git a/pkg/sensors/tracing/genericuprobe.go b/pkg/sensors/tracing/genericuprobe.go index 3406ff772e7..b830b6ef644 100644 --- a/pkg/sensors/tracing/genericuprobe.go +++ b/pkg/sensors/tracing/genericuprobe.go @@ -140,7 +140,7 @@ func loadSingleUprobeSensor(uprobeEntry *genericUprobe, args sensors.LoadProbeAr load.MapLoad = append(load.MapLoad, mapLoad...) - if err := program.LoadUprobeProgram(args.BPFDir, args.Load, args.Verbose); err != nil { + if err := program.LoadUprobeProgram(args.BPFDir, args.Load, args.Maps, args.Verbose); err != nil { return err } @@ -198,7 +198,7 @@ func loadMultiUprobeSensor(ids []idtable.EntryID, args sensors.LoadProbeArgs) er load.SetAttachData(data) - if err := program.LoadMultiUprobeProgram(args.BPFDir, args.Load, args.Verbose); err == nil { + if err := program.LoadMultiUprobeProgram(args.BPFDir, args.Load, args.Maps, args.Verbose); err == nil { logger.GetLogger().Infof("Loaded generic uprobe sensor: %s -> %s", load.Name, load.Attach) } else { return err diff --git a/pkg/sensors/tracing/loader.go b/pkg/sensors/tracing/loader.go index 43fe98d0df6..1e1e7b3e8af 100644 --- a/pkg/sensors/tracing/loader.go +++ b/pkg/sensors/tracing/loader.go @@ -180,7 +180,7 @@ func (k *loaderSensor) LoadProbe(args sensors.LoadProbeArgs) error { if err := createLoaderEvents(); err != nil { return err } - return program.LoadKprobeProgram(args.BPFDir, args.Load, args.Verbose) + return program.LoadKprobeProgram(args.BPFDir, args.Load, args.Maps, args.Verbose) } return nil } From bb8a251cb3ec45a5f26bfd18d5b0a7e447fb4d19 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 22 Jan 2025 22:49:31 +0000 Subject: [PATCH 09/11] tetragon: Factor user maps Signed-off-by: Jiri Olsa --- pkg/sensors/program/map.go | 24 ++++++++++++++++-------- pkg/sensors/tracing/enforcer.go | 16 ++++++++-------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/pkg/sensors/program/map.go b/pkg/sensors/program/map.go index 70278b3006f..d999e9a2680 100644 --- a/pkg/sensors/program/map.go +++ b/pkg/sensors/program/map.go @@ -194,20 +194,28 @@ func MapBuilderOpts(name string, opts MapOpts, lds ...*Program) *Map { return mapBuilder(name, opts.Type, opts.Owner, lds...) } -func MapUser(name string, lds ...*Program) *Map { - return mapBuilder(name, MapTypeGlobal, false, lds...) +func mapUser(name string, ty MapType, prog *Program) *Map { + return &Map{name, "", prog, Idle(), nil, MaxEntries{0, false}, MaxEntries{0, false}, ty, false} } -func MapUserProgram(name string, lds ...*Program) *Map { - return mapBuilder(name, MapTypeProgram, false, lds...) +func MapUser(name string, prog *Program) *Map { + return mapUser(name, MapTypeGlobal, prog) } -func MapUserSensor(name string, lds ...*Program) *Map { - return mapBuilder(name, MapTypeSensor, false, lds...) +func MapUserProgram(name string, prog *Program) *Map { + return mapUser(name, MapTypeProgram, prog) } -func MapUserPolicy(name string, lds ...*Program) *Map { - return mapBuilder(name, MapTypePolicy, false, lds...) +func MapUserSensor(name string, prog *Program) *Map { + return mapUser(name, MapTypeSensor, prog) +} + +func MapUserPolicy(name string, prog *Program) *Map { + return mapUser(name, MapTypePolicy, prog) +} + +func MapUserFrom(m *Map) *Map { + return mapUser(m.Name, m.Type, m.Prog) } func PolicyMapPath(mapDir, policy, name string) string { diff --git a/pkg/sensors/tracing/enforcer.go b/pkg/sensors/tracing/enforcer.go index 7355dd14fff..5644f6202c0 100644 --- a/pkg/sensors/tracing/enforcer.go +++ b/pkg/sensors/tracing/enforcer.go @@ -50,21 +50,21 @@ func init() { sensors.RegisterPolicyHandlerAtInit("enforcer", gEnforcerPolicy) } -func enforcerMapsUser(load ...*program.Program) []*program.Map { - edm := program.MapUserPolicy(enforcerDataMapName, load...) +func enforcerMapsUser(load *program.Program) []*program.Map { + edm := program.MapUserPolicy(enforcerDataMapName, load) edm.SetMaxEntries(enforcerMapMaxEntries) return []*program.Map{ edm, - program.MapUserPolicy(enforcermetrics.EnforcerMissedMapName, load...), + program.MapUserPolicy(enforcermetrics.EnforcerMissedMapName, load), } } -func enforcerMaps(load ...*program.Program) []*program.Map { - edm := program.MapBuilderPolicy(enforcerDataMapName, load...) +func enforcerMaps(load *program.Program) []*program.Map { + edm := program.MapBuilderPolicy(enforcerDataMapName, load) edm.SetMaxEntries(enforcerMapMaxEntries) return []*program.Map{ edm, - program.MapBuilderPolicy(enforcermetrics.EnforcerMissedMapName, load...), + program.MapBuilderPolicy(enforcermetrics.EnforcerMissedMapName, load), } } @@ -316,6 +316,7 @@ func (kp *enforcerPolicy) createEnforcerSensor( SetPolicy(policyName) progs = append(progs, load) + maps = append(maps, enforcerMaps(load)...) case OverrideMethodFmodRet: // for fmod_ret, we need one program per syscall logger.GetLogger().Infof("enforcer: using fmod_ret") @@ -329,13 +330,12 @@ func (kp *enforcerPolicy) createEnforcerSensor( SetLoaderData(policyName). SetPolicy(policyName) progs = append(progs, load) + maps = append(maps, enforcerMaps(load)...) } default: return nil, fmt.Errorf("unexpected override method: %d", overrideMethod) } - maps = append(maps, enforcerMaps(progs...)...) - if ok := kp.enforcerAdd(policyName, kh); !ok { return nil, fmt.Errorf("failed to add enforcer: '%s'", policyName) } From 831862a48961c06e20aadd709aa8461f7ececbcd Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 13 Jan 2025 13:58:18 +0000 Subject: [PATCH 10/11] tetragon: Allow to setup execve_map max entries Adding support to allow to setup execve_map max entries, so we can control the size of this map. Signed-off-by: Jiri Olsa --- bpf/lib/process.h | 2 +- pkg/sensors/base/base.go | 12 +++++++++--- pkg/sensors/test/cgroups.go | 2 ++ pkg/sensors/tracing/generickprobe.go | 3 +++ pkg/sensors/tracing/genericlsm.go | 3 +++ pkg/sensors/tracing/generictracepoint.go | 3 +++ pkg/sensors/tracing/genericuprobe.go | 3 +++ pkg/sensors/tracing/loader.go | 6 ++++-- 8 files changed, 28 insertions(+), 6 deletions(-) diff --git a/bpf/lib/process.h b/bpf/lib/process.h index d2876fb6fe6..21beb689847 100644 --- a/bpf/lib/process.h +++ b/bpf/lib/process.h @@ -366,7 +366,7 @@ struct { struct { __uint(type, BPF_MAP_TYPE_HASH); - __uint(max_entries, 32768); + __uint(max_entries, 1); __type(key, __u32); __type(value, struct execve_map_value); } execve_map SEC(".maps"); diff --git a/pkg/sensors/base/base.go b/pkg/sensors/base/base.go index dc8cf106fbb..f080fde22a5 100644 --- a/pkg/sensors/base/base.go +++ b/pkg/sensors/base/base.go @@ -17,6 +17,10 @@ import ( "github.com/cilium/tetragon/pkg/sensors/program" ) +const ( + execveMapMaxEntries = 32768 +) + var ( basePolicy = "__base__" @@ -55,7 +59,7 @@ var ( /* Event Ring map */ TCPMonMap = program.MapBuilder("tcpmon_map", Execve) /* Networking and Process Monitoring maps */ - ExecveMap = program.MapBuilder("execve_map", Execve) + ExecveMap = program.MapBuilder("execve_map", Execve, Exit, Fork, ExecveBprmCommit) ExecveTailCallsMap = program.MapBuilderProgram("execve_calls", Execve) ExecveJoinMap = program.MapBuilder("tg_execve_joined_info_map", ExecveBprmCommit) @@ -73,7 +77,7 @@ var ( ErrMetricsMap = program.MapBuilder(errmetrics.MapName, Execve) ) -func setupPrograms() { +func setupSensor() { // exit program function ks, err := ksyms.KernelSymbols() if err == nil { @@ -92,6 +96,8 @@ func setupPrograms() { } } logger.GetLogger().Infof("Exit probe on %s", Exit.Attach) + + ExecveMap.SetMaxEntries(execveMapMaxEntries) } func GetExecveMap() *program.Map { @@ -137,7 +143,7 @@ func initBaseSensor() *sensors.Sensor { sensor := sensors.Sensor{ Name: basePolicy, } - setupPrograms() + setupSensor() sensor.Progs = GetDefaultPrograms() sensor.Maps = GetDefaultMaps() return ApplyExtensions(&sensor) diff --git a/pkg/sensors/test/cgroups.go b/pkg/sensors/test/cgroups.go index 7c98bb2a40e..4eded504093 100644 --- a/pkg/sensors/test/cgroups.go +++ b/pkg/sensors/test/cgroups.go @@ -5,6 +5,7 @@ package test import ( "github.com/cilium/tetragon/pkg/sensors" + "github.com/cilium/tetragon/pkg/sensors/base" "github.com/cilium/tetragon/pkg/sensors/program" ) @@ -53,6 +54,7 @@ func getCgroupPrograms() []*program.Program { func getCgroupMaps() []*program.Map { maps := []*program.Map{ GetCgroupsTrackingMap(), + program.MapUserFrom(base.ExecveMap), } return maps } diff --git a/pkg/sensors/tracing/generickprobe.go b/pkg/sensors/tracing/generickprobe.go index 40a22551938..1465608565c 100644 --- a/pkg/sensors/tracing/generickprobe.go +++ b/pkg/sensors/tracing/generickprobe.go @@ -35,6 +35,7 @@ import ( "github.com/cilium/tetragon/pkg/policyfilter" "github.com/cilium/tetragon/pkg/selectors" "github.com/cilium/tetragon/pkg/sensors" + "github.com/cilium/tetragon/pkg/sensors/base" "github.com/cilium/tetragon/pkg/sensors/program" lru "github.com/hashicorp/golang-lru/v2" "github.com/sirupsen/logrus" @@ -665,6 +666,8 @@ func createGenericKprobeSensor( return nil, err } + maps = append(maps, program.MapUserFrom(base.ExecveMap)) + return &sensors.Sensor{ Name: name, Progs: progs, diff --git a/pkg/sensors/tracing/genericlsm.go b/pkg/sensors/tracing/genericlsm.go index 1f2a59268fd..a00da783f31 100644 --- a/pkg/sensors/tracing/genericlsm.go +++ b/pkg/sensors/tracing/genericlsm.go @@ -27,6 +27,7 @@ import ( "github.com/cilium/tetragon/pkg/policyfilter" "github.com/cilium/tetragon/pkg/selectors" "github.com/cilium/tetragon/pkg/sensors" + "github.com/cilium/tetragon/pkg/sensors/base" "github.com/cilium/tetragon/pkg/sensors/program" ) @@ -364,6 +365,8 @@ func createGenericLsmSensor( return nil, err } + maps = append(maps, program.MapUserFrom(base.ExecveMap)) + return &sensors.Sensor{ Name: name, Progs: progs, diff --git a/pkg/sensors/tracing/generictracepoint.go b/pkg/sensors/tracing/generictracepoint.go index 0c991a65e5d..a2ec9e431db 100644 --- a/pkg/sensors/tracing/generictracepoint.go +++ b/pkg/sensors/tracing/generictracepoint.go @@ -29,6 +29,7 @@ import ( "github.com/cilium/tetragon/pkg/reader/network" "github.com/cilium/tetragon/pkg/selectors" "github.com/cilium/tetragon/pkg/sensors" + "github.com/cilium/tetragon/pkg/sensors/base" "github.com/cilium/tetragon/pkg/sensors/program" "github.com/cilium/tetragon/pkg/syscallinfo" "github.com/cilium/tetragon/pkg/tracepoint" @@ -583,6 +584,8 @@ func createGenericTracepointSensor( maps = append(maps, selMatchBinariesMap) } + maps = append(maps, program.MapUserFrom(base.ExecveMap)) + ret.Progs = progs ret.Maps = maps return ret, nil diff --git a/pkg/sensors/tracing/genericuprobe.go b/pkg/sensors/tracing/genericuprobe.go index b830b6ef644..d924769ca65 100644 --- a/pkg/sensors/tracing/genericuprobe.go +++ b/pkg/sensors/tracing/genericuprobe.go @@ -24,6 +24,7 @@ import ( "github.com/cilium/tetragon/pkg/option" "github.com/cilium/tetragon/pkg/selectors" "github.com/cilium/tetragon/pkg/sensors" + "github.com/cilium/tetragon/pkg/sensors/base" "github.com/cilium/tetragon/pkg/sensors/program" ) @@ -284,6 +285,8 @@ func createGenericUprobeSensor( return nil, err } + maps = append(maps, program.MapUserFrom(base.ExecveMap)) + return &sensors.Sensor{ Name: name, Progs: progs, diff --git a/pkg/sensors/tracing/loader.go b/pkg/sensors/tracing/loader.go index 1e1e7b3e8af..5b39128be15 100644 --- a/pkg/sensors/tracing/loader.go +++ b/pkg/sensors/tracing/loader.go @@ -42,6 +42,7 @@ import ( "github.com/cilium/tetragon/pkg/observer" "github.com/cilium/tetragon/pkg/policyfilter" "github.com/cilium/tetragon/pkg/sensors" + "github.com/cilium/tetragon/pkg/sensors/base" "github.com/cilium/tetragon/pkg/sensors/program" "github.com/cilium/tetragon/pkg/strutils" "github.com/cilium/tetragon/pkg/tracingpolicy" @@ -67,7 +68,8 @@ var ( "loader", ) - idsMap = program.MapBuilder("ids_map", loader) + idsMap = program.MapBuilder("ids_map", loader) + execveMap = program.MapUserFrom(base.ExecveMap) loaderEnabled bool @@ -104,7 +106,7 @@ func GetLoaderSensor() *sensors.Sensor { return &sensors.Sensor{ Name: "__loader__", Progs: []*program.Program{loader}, - Maps: []*program.Map{idsMap}, + Maps: []*program.Map{idsMap, execveMap}, } } From 02d88da73d06c0012a4b81007dc65c8dd78f75bc Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 6 Jan 2025 22:59:19 +0000 Subject: [PATCH 11/11] tetragon: Add execve-map-entries option Adding execve-map-entries option to setup entries of execve_map map. Signed-off-by: Jiri Olsa --- docs/data/tetragon_flags.yaml | 3 ++ pkg/option/config.go | 2 + pkg/option/flags.go | 5 ++ pkg/sensors/base/base.go | 54 +++++++++++++++++++++- pkg/sensors/exec/procevents/proc_reader.go | 16 ++++++- 5 files changed, 77 insertions(+), 3 deletions(-) diff --git a/docs/data/tetragon_flags.yaml b/docs/data/tetragon_flags.yaml index 7a27fa4c60d..88af3e2d93a 100644 --- a/docs/data/tetragon_flags.yaml +++ b/docs/data/tetragon_flags.yaml @@ -95,6 +95,9 @@ options: - name: event-queue-size default_value: "10000" usage: Set the size of the internal event queue. + - name: execve-map-entries + default_value: "32768" + usage: Set entries for execve_map table (entries/size/max) - name: export-aggregation-buffer-size default_value: "10000" usage: Aggregator channel buffer size diff --git a/pkg/option/config.go b/pkg/option/config.go index 30871885afc..560692461c4 100644 --- a/pkg/option/config.go +++ b/pkg/option/config.go @@ -110,6 +110,8 @@ type config struct { EventCacheRetryDelay int CompatibilitySyscall64SizeType bool + + ExecveMapEntries string } var ( diff --git a/pkg/option/flags.go b/pkg/option/flags.go index 05a72d0e2a4..4ae0e040fc5 100644 --- a/pkg/option/flags.go +++ b/pkg/option/flags.go @@ -118,6 +118,8 @@ const ( KeyEventCacheRetryDelay = "event-cache-retry-delay" KeyCompatibilitySyscall64SizeType = "enable-compatibility-syscall64-size-type" + + KeyExecveMapEntries = "execve-map-entries" ) type UsernameMetadaCode int @@ -252,6 +254,7 @@ func ReadAndSetFlags() error { Config.CompatibilitySyscall64SizeType = viper.GetBool(KeyCompatibilitySyscall64SizeType) + Config.ExecveMapEntries = viper.GetString(KeyExecveMapEntries) return nil } @@ -419,4 +422,6 @@ func AddFlags(flags *pflag.FlagSet) { flags.Int(KeyEventCacheRetryDelay, defaults.DefaultEventCacheRetryDelay, "Delay in seconds between event cache retries") flags.Bool(KeyCompatibilitySyscall64SizeType, false, "syscall64 type will produce output of type size (compatibility flag, will be removed in v1.4)") + + flags.String(KeyExecveMapEntries, "32768", "Set entries for execve_map table (entries/size/max)") } diff --git a/pkg/sensors/base/base.go b/pkg/sensors/base/base.go index f080fde22a5..437bef3967d 100644 --- a/pkg/sensors/base/base.go +++ b/pkg/sensors/base/base.go @@ -5,20 +5,27 @@ package base import ( "log" + "os" + "strconv" + "strings" "sync" "testing" + "unsafe" "github.com/cilium/tetragon/pkg/errmetrics" "github.com/cilium/tetragon/pkg/ksyms" "github.com/cilium/tetragon/pkg/logger" "github.com/cilium/tetragon/pkg/mbset" + "github.com/cilium/tetragon/pkg/option" "github.com/cilium/tetragon/pkg/sensors" "github.com/cilium/tetragon/pkg/sensors/exec/config" + "github.com/cilium/tetragon/pkg/sensors/exec/execvemap" "github.com/cilium/tetragon/pkg/sensors/program" + "github.com/cilium/tetragon/pkg/strutils" ) const ( - execveMapMaxEntries = 32768 + ExecveMapMaxEntries = 32768 ) var ( @@ -77,6 +84,43 @@ var ( ErrMetricsMap = program.MapBuilder(errmetrics.MapName, Execve) ) +func readThreadsMax(path string) (int64, error) { + data, err := os.ReadFile(path) + if err != nil { + return 0, err + } + str := strings.TrimRight(string(data), "\n") + return strconv.ParseInt(str, 10, 32) +} + +func GetExecveMapEntries(str string) int { + entry := int(unsafe.Sizeof(execvemap.ExecveValue{})) + + if len(str) == 0 { + return ExecveMapMaxEntries + } + // pure number of entries + if val, err := strconv.Atoi(str); err == nil { + return val + } + // follow threads-max entries + if str == "max" { + if val, err := readThreadsMax("/proc/sys/kernel/threads-max"); err == nil { + return int(val) + } + logger.GetLogger().Warn("Failed to read /proc/sys/kernel/threads-max file, falling back to default") + return ExecveMapMaxEntries + } + // set entries based on size + size, err := strutils.ParseSize(str) + if err != nil { + logger.GetLogger().Warn("Failed to parse --execve-map-max value, falling back to default") + return ExecveMapMaxEntries + } + val := size / entry + return val +} + func setupSensor() { // exit program function ks, err := ksyms.KernelSymbols() @@ -97,7 +141,13 @@ func setupSensor() { } logger.GetLogger().Infof("Exit probe on %s", Exit.Attach) - ExecveMap.SetMaxEntries(execveMapMaxEntries) + entries := GetExecveMapEntries(option.Config.ExecveMapEntries) + ExecveMap.SetMaxEntries(entries) + + logger.GetLogger(). + WithField("size", strutils.SizeWithSuffix(entries*int(unsafe.Sizeof(execvemap.ExecveValue{})))). + WithField("config", option.Config.ExecveMapEntries). + Infof("Set execve_map entries %d", entries) } func GetExecveMap() *program.Map { diff --git a/pkg/sensors/exec/procevents/proc_reader.go b/pkg/sensors/exec/procevents/proc_reader.go index 6e3f0d3aba9..e0c8acbdfb4 100644 --- a/pkg/sensors/exec/procevents/proc_reader.go +++ b/pkg/sensors/exec/procevents/proc_reader.go @@ -335,6 +335,15 @@ func writeExecveMap(procs []procs) { panic(err) } } + + entries, ok := base.ExecveMap.GetMaxEntries() + if !ok { + logger.GetLogger().Warnf("Failed to get number of execve_map entries, using default.") + entries = base.ExecveMapMaxEntries + } + logger.GetLogger().Infof("Maximum execve_map entries %d, need to add %d.", entries, len(procs)) + i := uint32(0) + for _, p := range procs { k := &execvemap.ExecveKey{Pid: p.pid} v := &execvemap.ExecveValue{} @@ -365,6 +374,11 @@ func writeExecveMap(procs []procs) { if err != nil { logger.GetLogger().WithField("value", v).WithError(err).Warn("failed to put value in execve_map") } + + i++ + if i == entries { + break + } } // In order for kprobe events from kernel ctx to not abort we need the // execve lookup to map to a valid entry. So to simplify the kernel side @@ -381,7 +395,7 @@ func writeExecveMap(procs []procs) { }) m.Close() - updateExecveMapStats(int64(len(procs))) + updateExecveMapStats(int64(entries)) } func pushEvents(ps []procs) {