From 9afe05526556eaca5ba5a5ffe5e4e85139eabb88 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 22 Sep 2024 18:48:21 +0000 Subject: [PATCH] tetragon: Add tests for other (not owner) maps Adding tests for 'other' maps to cover following scenarios: - other map gets properly created from pinned map - other map fails to be loaded if the pinned map is missing - other map fails to be loaded if the pinned map has different max entries setup - other map fails to be loaded if the pinned map is not compatible Signed-off-by: Jiri Olsa --- bpf/Makefile | 2 +- bpf/process/bpf_map_test_p3.c | 22 +++++ pkg/sensors/test/sensors_test.go | 148 +++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 bpf/process/bpf_map_test_p3.c diff --git a/bpf/Makefile b/bpf/Makefile index 1a6fb86c093..1ea659cbdc3 100644 --- a/bpf/Makefile +++ b/bpf/Makefile @@ -31,7 +31,7 @@ PROCESS = bpf_execve_event.o bpf_execve_event_v53.o bpf_fork.o bpf_exit.o bpf_ge bpf_loader.o \ bpf_cgroup.o \ bpf_enforcer.o bpf_multi_enforcer.o bpf_fmodret_enforcer.o \ - bpf_map_test_p1.o bpf_map_test_p2.o + bpf_map_test_p1.o bpf_map_test_p2.o bpf_map_test_p3.o CGROUP = bpf_cgroup_mkdir.o bpf_cgroup_rmdir.o bpf_cgroup_release.o BPFTEST = bpf_lseek.o diff --git a/bpf/process/bpf_map_test_p3.c b/bpf/process/bpf_map_test_p3.c new file mode 100644 index 00000000000..1ae0a899e63 --- /dev/null +++ b/bpf/process/bpf_map_test_p3.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* Copyright Authors of Cilium */ + +#include "vmlinux.h" +#include "api.h" +#include "bpf_tracing.h" +#include "bpf_helpers.h" +#include "compiler.h" + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 1); + __type(key, int); + __type(value, unsigned long); +} m1 SEC(".maps"); + +__attribute__((section("kprobe/wake_up_new_task"), used)) int +BPF_KPROBE(p2) +{ + map_lookup_elem(&m1, &(unsigned long){ 0 }); + return 0; +} diff --git a/pkg/sensors/test/sensors_test.go b/pkg/sensors/test/sensors_test.go index a9625155700..6262efa3818 100644 --- a/pkg/sensors/test/sensors_test.go +++ b/pkg/sensors/test/sensors_test.go @@ -197,6 +197,154 @@ func TestMapMultipleSensors(t *testing.T) { assert.Equal(t, m12.PinPath, m22.PinPath) } +func TestMapOther(t *testing.T) { + p1 := program.Builder( + "bpf_map_test_p1.o", + "wake_up_new_task", + "kprobe/wake_up_new_task", + "p1", + "kprobe", + ) + p2 := program.Builder( + "bpf_map_test_p2.o", + "wake_up_new_task", + "kprobe/wake_up_new_task", + "p2", + "kprobe", + ) + p3 := program.Builder( + "bpf_map_test_p3.o", + "wake_up_new_task", + "kprobe/wake_up_new_task", + "p3", + "kprobe", + ) + opts := program.MapOpts{ + Type: program.MapTypeGlobal, + Owner: program.MapOwnerOther, + } + + var err error + + // Create sensor with other map and make sure it's properly loaded + t.Run("ok", func(t *testing.T) { + m1 := program.MapBuilder("m1", p1) + m2 := program.MapBuilder("m2", p2) + + s1 := &sensors.Sensor{ + Name: "sensor1", + Progs: []*program.Program{p1}, + Maps: []*program.Map{m1, m2}, + Policy: "policy", + } + + // other-owner map + m1Other := program.MapBuilderOpts("m1", opts, p2) + + s2 := &sensors.Sensor{ + Name: "sensor2", + Progs: []*program.Program{p2}, + Maps: []*program.Map{m1Other}, + Policy: "policy", + } + + err = s1.Load(bpf.MapPrefixPath()) + defer s1.Unload() + assert.NoError(t, err) + + err = s2.Load(bpf.MapPrefixPath()) + defer s2.Unload() + assert.NoError(t, err) + }) + + // Create sensor with other map with wrong name (no existing pinned + // map file) and make sure the sensor fails to load + t.Run("fail_name", func(t *testing.T) { + m1 := program.MapBuilder("m1", p1, p2) + + // other-owner map with wrong name + m2 := program.MapBuilderOpts("non-existing", opts, p1, p2) + + s1 := &sensors.Sensor{ + Name: "sensor1", + Progs: []*program.Program{p1}, + Maps: []*program.Map{m1, m2}, + Policy: "policy", + } + + err = s1.Load(bpf.MapPrefixPath()) + assert.Error(t, err) + if err == nil { + defer s1.Unload() + } + }) + + // Create sensor with other map with different max entries setup + // from real owner map and make sure the sensor fails to load + t.Run("fail_max", func(t *testing.T) { + m1 := program.MapBuilder("m1", p1) + m1.SetMaxEntries(10) + + s1 := &sensors.Sensor{ + Name: "sensor1", + Progs: []*program.Program{p1}, + Maps: []*program.Map{m1}, + Policy: "policy", + } + + // other-owner map with extra max setup + m1Other := program.MapBuilderOpts("m1", opts, p2) + m1Other.SetMaxEntries(100) + + s2 := &sensors.Sensor{ + Name: "sensor2", + Progs: []*program.Program{p2}, + Maps: []*program.Map{m1Other}, + Policy: "policy", + } + + err = s1.Load(bpf.MapPrefixPath()) + defer s1.Unload() + assert.NoError(t, err) + + err = s2.Load(bpf.MapPrefixPath()) + defer s2.Unload() + assert.Error(t, err) + }) + + // Create sensor with other map with different spec from real owner + // map and make sure the sensor fails to load + t.Run("fail_spec", func(t *testing.T) { + m1 := program.MapBuilder("m1", p1) + + s1 := &sensors.Sensor{ + Name: "sensor1", + Progs: []*program.Program{p1}, + Maps: []*program.Map{m1}, + Policy: "policy", + } + + // The bpf_map_test_p3 has map with same name and different + // value type, so we should fail to load it. + m1Other := program.MapBuilderOpts("m1", opts, p3) + + s3 := &sensors.Sensor{ + Name: "sensor3", + Progs: []*program.Program{p3}, + Maps: []*program.Map{m1Other}, + Policy: "policy", + } + + err = s1.Load(bpf.MapPrefixPath()) + defer s1.Unload() + assert.NoError(t, err) + + err = s3.Load(bpf.MapPrefixPath()) + defer s3.Unload() + assert.Error(t, err) + }) +} + func TestPolicyMapPath(t *testing.T) { option.Config.HubbleLib = tus.Conf().TetragonLib option.Config.Verbosity = 5