From 1c0e273c76f86c5bafb791cf7bffa5054da7a987 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 29 Aug 2023 21:58:00 +0000 Subject: [PATCH] tetragon: Add killer tests Adding test for killer sensor and testing both killing application matching the selector and overriding syscall that matches the selector. Signed-off-by: Jiri Olsa --- contrib/tester-progs/Makefile | 3 +- contrib/tester-progs/killer-tester.c | 9 ++ pkg/sensors/tracing/killer_test.go | 172 +++++++++++++++++++++++++++ 3 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 contrib/tester-progs/killer-tester.c create mode 100644 pkg/sensors/tracing/killer_test.go diff --git a/contrib/tester-progs/Makefile b/contrib/tester-progs/Makefile index 05bb223bea3..1b7c7ab4fff 100644 --- a/contrib/tester-progs/Makefile +++ b/contrib/tester-progs/Makefile @@ -15,7 +15,8 @@ PROGS = sigkill-tester \ uprobe-test-1 \ uprobe-test-2 \ lseek-pipe \ - threads-tester + threads-tester \ + killer-tester all: $(PROGS) diff --git a/contrib/tester-progs/killer-tester.c b/contrib/tester-progs/killer-tester.c new file mode 100644 index 00000000000..cb95fc68366 --- /dev/null +++ b/contrib/tester-progs/killer-tester.c @@ -0,0 +1,9 @@ +#include +#include +#include + +int main(void) +{ + prctl(0xffff, 0, 0, 0, 0); + return errno; +} diff --git a/pkg/sensors/tracing/killer_test.go b/pkg/sensors/tracing/killer_test.go new file mode 100644 index 00000000000..76a74779562 --- /dev/null +++ b/pkg/sensors/tracing/killer_test.go @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Tetragon + +package tracing + +import ( + "context" + "os" + "os/exec" + "sync" + "syscall" + "testing" + + "github.com/cilium/tetragon/api/v1/tetragon/codegen/eventchecker" + ec "github.com/cilium/tetragon/api/v1/tetragon/codegen/eventchecker" + "github.com/cilium/tetragon/pkg/bpf" + "github.com/cilium/tetragon/pkg/jsonchecker" + lc "github.com/cilium/tetragon/pkg/matchers/listmatcher" + "github.com/cilium/tetragon/pkg/observer/observertesthelper" + "github.com/cilium/tetragon/pkg/testutils" + tus "github.com/cilium/tetragon/pkg/testutils/sensors" + "github.com/stretchr/testify/assert" +) + +func test_killer(t *testing.T, configHook string, test string, + checker *eventchecker.UnorderedEventChecker, + checkerFunc func(err error, rc int)) { + + var doneWG, readyWG sync.WaitGroup + defer doneWG.Wait() + + ctx, cancel := context.WithTimeout(context.Background(), tus.Conf().CmdWaitTime) + defer cancel() + + err := os.WriteFile(testConfigFile, []byte(configHook), 0644) + if err != nil { + t.Fatalf("writeFile(%s): err %s", testConfigFile, err) + } + + obs, err := observertesthelper.GetDefaultObserverWithFile(t, ctx, testConfigFile, tus.Conf().TetragonLib, observertesthelper.WithMyPid()) + if err != nil { + t.Fatalf("GetDefaultObserverWithFile error: %s", err) + } + observertesthelper.LoopEvents(ctx, t, &doneWG, &readyWG, obs) + readyWG.Wait() + + cmd := exec.Command(test) + err = cmd.Run() + + checkerFunc(err, cmd.ProcessState.ExitCode()) + + err = jsonchecker.JsonTestCheck(t, checker) + assert.NoError(t, err) +} + +func TestKillerOverride(t *testing.T) { + if !bpf.HasOverrideHelper() { + t.Skip("skipping killer test, bpf_override_return helper not available") + } + + test := testutils.RepoRootPath("contrib/tester-progs/killer-tester") + configHook := ` +apiVersion: cilium.io/v1alpha1 +kind: TracingPolicy +metadata: + name: "kill-syscalls" +spec: + lists: + - name: "mine" + type: "syscalls" + values: + - "sys_prctl" + killers: + - syscalls: + - "list:mine" + tracepoints: + - subsystem: "raw_syscalls" + event: "sys_enter" + args: + - index: 4 + type: "uint64" + selectors: + - matchArgs: + - index: 0 + operator: "InMap" + values: + - "list:mine" + matchBinaries: + - operator: "In" + values: + - "` + test + `" + matchActions: + - action: "NotifyKiller" + argError: -17 # EEXIST +` + + tpChecker := ec.NewProcessTracepointChecker(""). + WithArgs(ec.NewKprobeArgumentListMatcher(). + WithOperator(lc.Ordered). + WithValues( + ec.NewKprobeArgumentChecker().WithSizeArg(syscall.SYS_PRCTL), + )) + + checker := ec.NewUnorderedEventChecker(tpChecker) + + checkerFunc := func(err error, rc int) { + if rc != int(syscall.EEXIST) { + t.Fatalf("Wrong exit code %d expected %d", rc, int(syscall.EEXIST)) + } + } + + test_killer(t, configHook, test, checker, checkerFunc) +} + +func TestKillerSignal(t *testing.T) { + if !bpf.HasOverrideHelper() { + t.Skip("skipping killer test, bpf_override_return helper not available") + } + + test := testutils.RepoRootPath("contrib/tester-progs/killer-tester") + configHook := ` +apiVersion: cilium.io/v1alpha1 +kind: TracingPolicy +metadata: + name: "kill-syscalls" +spec: + lists: + - name: "mine" + type: "syscalls" + values: + - "sys_prctl" + killers: + - syscalls: + - "list:mine" + tracepoints: + - subsystem: "raw_syscalls" + event: "sys_enter" + args: + - index: 4 + type: "uint64" + selectors: + - matchArgs: + - index: 0 + operator: "InMap" + values: + - "list:mine" + matchBinaries: + - operator: "In" + values: + - "` + test + `" + matchActions: + - action: "NotifyKiller" + argSig: 9 # SIGKILL +` + + tpChecker := ec.NewProcessTracepointChecker(""). + WithArgs(ec.NewKprobeArgumentListMatcher(). + WithOperator(lc.Ordered). + WithValues( + ec.NewKprobeArgumentChecker().WithSizeArg(syscall.SYS_PRCTL), + )) + + checker := ec.NewUnorderedEventChecker(tpChecker) + + checkerFunc := func(err error, rc int) { + if err == nil || err.Error() != "signal: killed" { + t.Fatalf("Wrong error '%v' expected 'killed'", err) + } + } + + test_killer(t, configHook, test, checker, checkerFunc) +}