-
Notifications
You must be signed in to change notification settings - Fork 378
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: update selector_filter index assignment to use sel->index
Signed-off-by: arthur-zhang <[email protected]>
- Loading branch information
1 parent
c3df31c
commit 0ce1cb4
Showing
4 changed files
with
233 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
/* Copyright Authors of Cilium */ | ||
|
||
//go:build ignore | ||
|
||
#include "vmlinux.h" | ||
#include "compiler.h" | ||
#include "bpf_core_read.h" | ||
#include "bpf_helpers.h" | ||
#include "process/retprobe_map.h" | ||
|
||
#include "process/types/basic.h" | ||
#include "process/generic_calls.h" | ||
#include "process/pfilter.h" | ||
|
||
char _license[] __attribute__((section("license"), used)) = "Dual BSD/GPL"; | ||
|
||
struct filter_map_value { | ||
unsigned char buf[FILTER_SIZE]; | ||
}; | ||
|
||
struct { | ||
__uint(type, BPF_MAP_TYPE_ARRAY); | ||
__uint(max_entries, 1); | ||
__type(key, int); | ||
__type(value, struct filter_map_value); | ||
} test_filter_map SEC(".maps"); | ||
|
||
struct { | ||
__uint(type, BPF_MAP_TYPE_ARRAY); | ||
__uint(max_entries, 1); | ||
__type(key, __u32); | ||
__type(value, int); | ||
} test_result_map SEC(".maps"); | ||
|
||
__attribute__((section("raw_tracepoint/test"), used)) int | ||
test_pid_match() | ||
{ | ||
__u32 *f; | ||
int zero = 0, index = 0, res = -1, err = 0; | ||
struct pid_filter *pid; | ||
struct execve_map_value *enter; | ||
|
||
f = map_lookup_elem(&test_filter_map, &zero); | ||
|
||
if (!f) { | ||
return 0; | ||
} | ||
pid = (struct pid_filter *)((u64)f + index); | ||
index += sizeof(struct pid_filter); | ||
|
||
enter = map_lookup_elem(&execve_map, &zero); | ||
if (!enter) { | ||
return 0; | ||
} | ||
|
||
struct selector_filter sel = { | ||
.index = index, | ||
.ty = pid->op, | ||
.flags = pid->flags, | ||
.len = pid->len, | ||
}; | ||
res = selector_match(f, &sel, enter, NULL, &process_filter_pid); | ||
|
||
err = map_update_elem(&test_result_map, &zero, &res, BPF_ANY); | ||
if (err) { | ||
return 0; | ||
} | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// Copyright Authors of Tetragon | ||
|
||
package bpf | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/cilium/ebpf" | ||
"github.com/cilium/tetragon/pkg/api/processapi" | ||
"github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1" | ||
"github.com/cilium/tetragon/pkg/selectors" | ||
"github.com/cilium/tetragon/pkg/sensors/exec/execvemap" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
const programNamePidMatch = "test_pid_match" | ||
|
||
type testContext struct { | ||
coll *ebpf.Collection | ||
prog *ebpf.Program | ||
execvMap *ebpf.Map | ||
resultMap *ebpf.Map | ||
t *testing.T | ||
} | ||
|
||
func setupTest(t *testing.T) (*testContext, error) { | ||
ctx := &testContext{t: t} | ||
|
||
coll, err := ebpf.LoadCollection("objs/pid_match_test.o") | ||
if err != nil { | ||
var ve *ebpf.VerifierError | ||
if errors.As(err, &ve) { | ||
return nil, fmt.Errorf("verifier error: %+v", ve) | ||
} | ||
return nil, err | ||
} | ||
ctx.coll = coll | ||
|
||
var ok bool | ||
ctx.prog, ok = coll.Programs[programNamePidMatch] | ||
require.True(t, ok, "program %s not found", programNamePidMatch) | ||
|
||
ctx.execvMap, ok = coll.Maps["execve_map"] | ||
require.True(t, ok, "execve_map not found") | ||
|
||
ctx.resultMap, ok = coll.Maps["test_result_map"] | ||
require.True(t, ok, "test_result_map not found") | ||
|
||
return ctx, nil | ||
} | ||
|
||
func (ctx *testContext) cleanup() { | ||
if ctx.coll != nil { | ||
ctx.coll.Close() | ||
} | ||
} | ||
|
||
func (ctx *testContext) runProg(selfPid uint32) error { | ||
err := ctx.execvMap.Update(uint32(0), &execvemap.ExecveValue{ | ||
Process: processapi.MsgExecveKey{Pid: selfPid}, | ||
}, 0) | ||
if err != nil { | ||
return fmt.Errorf("failed to update execve map: %w", err) | ||
} | ||
_, err = ctx.prog.Run(&ebpf.RunOptions{}) | ||
return err | ||
} | ||
|
||
func (ctx *testContext) getResult() (int32, error) { | ||
var res int32 | ||
err := ctx.resultMap.Lookup(uint32(0), &res) | ||
return res, err | ||
} | ||
|
||
func (ctx *testContext) initKernelStatedata(pids []uint32) error { | ||
k := &selectors.KernelSelectorState{} | ||
err := selectors.ParseMatchPid(k, &v1alpha1.PIDSelector{ | ||
Operator: "In", | ||
Values: pids, | ||
IsNamespacePID: false, | ||
FollowForks: false, | ||
}) | ||
if err != nil { | ||
return fmt.Errorf("failed to parse PID selector: %w", err) | ||
} | ||
|
||
filterMap, ok := ctx.coll.Maps["test_filter_map"] | ||
if !ok { | ||
return errors.New("test_filter_map not found") | ||
} | ||
|
||
return filterMap.Update(uint32(0), k.Buffer(), 0) | ||
} | ||
|
||
func (ctx *testContext) resetResult() error { | ||
return ctx.resultMap.Update(uint32(0), int32(-1), 0) | ||
} | ||
|
||
func Test_PidMatch(t *testing.T) { | ||
ctx, err := setupTest(t) | ||
require.NoError(t, err) | ||
defer ctx.cleanup() | ||
|
||
tests := []struct { | ||
name string | ||
pids []uint32 | ||
testPid uint32 | ||
expected int32 | ||
}{ | ||
{ | ||
name: "Match_1_PID", | ||
pids: []uint32{1}, | ||
testPid: 1, | ||
expected: 1, | ||
}, | ||
{ | ||
name: "Match_2_PID", | ||
pids: []uint32{1, 2}, | ||
testPid: 2, | ||
expected: 1, | ||
}, | ||
{ | ||
name: "Match_2_PID_NOT_IN_LIST", | ||
pids: []uint32{1, 2}, | ||
testPid: 3, | ||
expected: 0, | ||
}, | ||
{ | ||
name: "Match_4_PID", | ||
pids: []uint32{1, 2, 3, 4}, | ||
testPid: 4, | ||
expected: 1, | ||
}, | ||
{ | ||
name: "Match_4_PID_NOT_IN_LIST", | ||
pids: []uint32{1, 2, 3, 4}, | ||
testPid: 5, | ||
expected: 0, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
require.NoError(t, ctx.resetResult()) | ||
require.NoError(t, ctx.initKernelStatedata(tt.pids)) | ||
require.NoError(t, ctx.runProg(tt.testPid)) | ||
|
||
result, err := ctx.getResult() | ||
require.NoError(t, err) | ||
assert.Equal(t, tt.expected, result) | ||
}) | ||
} | ||
} |