summaryrefslogtreecommitdiff
path: root/integrationtests/security_test.go
blob: a705a16c3a6640d3d6fcd47dea6760c6d8ced7b9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package integrationtests

import (
	"strings"
	"testing"
)

func TestSecurityKeysPtracePerf(t *testing.T) {
	result, _ := runScenarioResult(t, "security-keys-ptrace-perf", []ExpectedEvent{
		{Tracepoint: "enter_keyctl", Comm: "ioworkload", MinCount: 1},
		{Tracepoint: "enter_add_key", Comm: "ioworkload", MinCount: 1},
		{Tracepoint: "enter_request_key", Comm: "ioworkload", MinCount: 1},
		{Tracepoint: "enter_ptrace", Comm: "ioworkload", MinCount: 1},
		{Tracepoint: "enter_perf_event_open", Comm: "ioworkload", MinCount: 1},
	})

	// Key and ptrace operations are not fd/path based and should stay untracked.
	assertTracepointPathPrefix(t, result, "enter_keyctl", "N:file")
	assertTracepointPathPrefix(t, result, "enter_add_key", "N:file")
	assertTracepointPathPrefix(t, result, "enter_request_key", "N:file")
	assertTracepointPathPrefix(t, result, "enter_ptrace", "N:file")

	for _, tracepoint := range []string{
		"enter_keyctl",
		"enter_add_key",
		"enter_request_key",
		"enter_ptrace",
		"enter_perf_event_open",
	} {
		assertEventDurationPositive(t, result, ExpectedEvent{
			Tracepoint: tracepoint,
			Comm:       "ioworkload",
		})
	}

	// perf_event_open may fail (e.g. EPERM), so assert conditional behavior:
	// if a tracked perf descriptor appears, we must also observe a close on it.
	perfOpenTracked := totalTracepointPathCount(result, "enter_perf_event_open", "perf:")
	perfCloseTracked := totalTracepointPathCount(result, "enter_close", "perf:")
	if perfOpenTracked == 0 {
		if perfCloseTracked != 0 {
			t.Fatalf("unexpected tracked perf close events without tracked perf open: close=%d", perfCloseTracked)
		}
		return
	}

	assertTracepointPathPrefix(t, result, "enter_perf_event_open", "perf:")
	assertTracepointPathPrefix(t, result, "enter_close", "perf:")
	if perfCloseTracked < perfOpenTracked {
		t.Fatalf("tracked perf close count too small: close=%d open=%d", perfCloseTracked, perfOpenTracked)
	}

	// Tracked perf descriptor path should be stable between open and close records.
	openPaths := uniqueTracepointPathsWithPrefix(result, "enter_perf_event_open", "perf:")
	closePaths := uniqueTracepointPathsWithPrefix(result, "enter_close", "perf:")
	for path := range openPaths {
		if _, ok := closePaths[path]; !ok {
			t.Fatalf("tracked perf descriptor %q seen on open but not close", path)
		}
	}
}

func uniqueTracepointPathsWithPrefix(result TestResult, tracepoint, wantPrefix string) map[string]struct{} {
	paths := make(map[string]struct{})
	for _, rec := range result.Records {
		if !strings.Contains(rec.TraceID.String(), tracepoint) {
			continue
		}
		if !strings.HasPrefix(rec.Path, wantPrefix) {
			continue
		}
		paths[rec.Path] = struct{}{}
	}
	return paths
}