Skip to content

Commit

Permalink
fix: update selector_filter index assignment to use sel->index
Browse files Browse the repository at this point in the history
Signed-off-by: arthur-zhang <[email protected]>
  • Loading branch information
arthur-zhang committed Jan 6, 2025
1 parent c3df31c commit 0ce1cb4
Show file tree
Hide file tree
Showing 4 changed files with 233 additions and 1 deletion.
4 changes: 4 additions & 0 deletions bpf/process/pfilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -342,15 +342,19 @@ selector_match(__u32 *f, struct selector_filter *sel,
four:
res4 = process_filter(sel, f, enter, &msg->ns, &msg->caps);
index = next_pid_value(index, f, ty);
sel->index = index;
three:
res3 = process_filter(sel, f, enter, &msg->ns, &msg->caps);
index = next_pid_value(index, f, ty);
sel->index = index;
two:
res2 = process_filter(sel, f, enter, &msg->ns, &msg->caps);
index = next_pid_value(index, f, ty);
sel->index = index;
one:
res1 = process_filter(sel, f, enter, &msg->ns, &msg->caps);
index = next_pid_value(index, f, ty);
sel->index = index;

if (ty == op_filter_notin)
return res1 & res2 & res3 & res4;
Expand Down
2 changes: 1 addition & 1 deletion bpf/tests/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
include ../Makefile.defs

TESTS = prepend_name_test.o
TESTS = prepend_name_test.o pid_match_test.o

OBJSDIR := objs/
OBJS := $(addprefix $(OBJSDIR),$(TESTS))
Expand Down
71 changes: 71 additions & 0 deletions bpf/tests/pid_match_test.c
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;
}
157 changes: 157 additions & 0 deletions bpf/tests/pid_match_test.go
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)
})
}
}

0 comments on commit 0ce1cb4

Please sign in to comment.