Skip to content

Commit c9bf1d8

Browse files
tetragon: add negative resolve argsMatch test
When a pointer to a BTF struct is NULL, every type of matchArgs selector should fail to match, because the argument was not really resolved. Signed-off-by: Andy Strohman <[email protected]>
1 parent 1f40cfa commit c9bf1d8

File tree

2 files changed

+64
-23
lines changed

2 files changed

+64
-23
lines changed

contrib/tester-progs/uprobe-resolve.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@ struct mystruct {
2222
void usage(char *argv0)
2323
{
2424
fprintf(stderr, "Usage: %s <field> <val>\n", argv0);
25-
fprintf(stderr, "field can be one of: v8, v16, v32, v64, sub.v32\n");
25+
fprintf(stderr, "field can be one of: v8, v16, v32, v64, sub.v32, null\n");
2626
}
2727

2828
// without noinline, the symbol is found, but no event fires
2929
__attribute__((noinline)) int func(int ret, struct mystruct *ms) {
30+
if (ms == NULL)
31+
return ret;
3032
// without doing something with ms, all the resolved args have
3133
// value 0, presumably due to optimization
3234
printf("v64:%lu\n", ms->v64);
@@ -58,6 +60,8 @@ int main(int argc, char *argv[])
5860
s.v64 = val;
5961
} else if (!strcmp(field, "sub.v32")) {
6062
s.sub.v32 = val;
63+
} else if (!strcmp(field, "null")) {
64+
return func(0, NULL);
6165
} else {
6266
usage(argv[0]);
6367
exit(1);

pkg/sensors/tracing/uprobe_amd64_test.go

Lines changed: 59 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515

1616
"github.com/stretchr/testify/require"
1717

18+
"github.com/cilium/tetragon/api/v1/tetragon/codegen/eventchecker"
1819
ec "github.com/cilium/tetragon/api/v1/tetragon/codegen/eventchecker"
1920
"github.com/cilium/tetragon/pkg/bpf"
2021
"github.com/cilium/tetragon/pkg/config"
@@ -157,6 +158,25 @@ spec:
157158
require.NoError(t, err)
158159
}
159160

161+
type TestInvocation struct {
162+
specTy string
163+
filterVal int
164+
field string
165+
kpArgs []*ec.KprobeArgumentChecker
166+
}
167+
168+
func get_checker(ti TestInvocation, uprobe string) *eventchecker.ProcessUprobeChecker {
169+
return ec.NewProcessUprobeChecker("uprobe-resolve").
170+
WithProcess(ec.NewProcessChecker().
171+
WithBinary(sm.Full(uprobe)).
172+
WithArguments(
173+
sm.Full(ti.field + " " + strconv.Itoa(ti.filterVal)),
174+
),
175+
).WithArgs(ec.NewKprobeArgumentListMatcher().
176+
WithOperator(lc.Ordered).
177+
WithValues(ti.kpArgs...))
178+
}
179+
160180
func TestUprobeResolve(t *testing.T) {
161181
if !config.EnableLargeProgs() || !bpf.HasUprobeRefCtrOffset() {
162182
t.Skip("Need 5.3 or newer kernel for uprobe ref_ctr_off support for this test.")
@@ -169,33 +189,39 @@ func TestUprobeResolve(t *testing.T) {
169189
uprobe := testutils.RepoRootPath("contrib/tester-progs/uprobe-resolve")
170190
uprobeBtf := testutils.RepoRootPath("contrib/tester-progs/uprobe-resolve.btf")
171191

172-
tt := []struct {
173-
specTy string
174-
filterVal int
175-
returnVal int
176-
field string
177-
kpArgs []*ec.KprobeArgumentChecker
178-
}{
179-
{"uint64", 10, 120, "v64", []*ec.KprobeArgumentChecker{
192+
tt := []TestInvocation{
193+
{"uint64", 10, "v64", []*ec.KprobeArgumentChecker{
180194
ec.NewKprobeArgumentChecker().WithIntArg(0),
181195
ec.NewKprobeArgumentChecker().WithSizeArg(10), // uint64(10)
182196
ec.NewKprobeArgumentChecker().WithUintArg(0),
183197
ec.NewKprobeArgumentChecker().WithUintArg(0),
198+
ec.NewKprobeArgumentChecker().WithUintArg(0),
184199
}},
185-
{"uint32", 11, 130, "v32", []*ec.KprobeArgumentChecker{
200+
{"uint32", 11, "v32", []*ec.KprobeArgumentChecker{
186201
ec.NewKprobeArgumentChecker().WithIntArg(0),
187202
ec.NewKprobeArgumentChecker().WithSizeArg(0),
188203
ec.NewKprobeArgumentChecker().WithUintArg(11), // uint32(11)
189204
ec.NewKprobeArgumentChecker().WithUintArg(0),
205+
ec.NewKprobeArgumentChecker().WithUintArg(0),
190206
}},
191-
{"uint32", 12, 140, "sub.v32", []*ec.KprobeArgumentChecker{
207+
{"uint32", 12, "sub.v32", []*ec.KprobeArgumentChecker{
192208
ec.NewKprobeArgumentChecker().WithIntArg(0),
193209
ec.NewKprobeArgumentChecker().WithSizeArg(0),
194210
ec.NewKprobeArgumentChecker().WithUintArg(0),
195211
ec.NewKprobeArgumentChecker().WithUintArg(12), // uint32(12)
212+
ec.NewKprobeArgumentChecker().WithUintArg(0),
196213
}},
197214
}
198215

216+
/* filterVal is ignored by uprobe-resolve "null" type mode */
217+
negative_tests := []TestInvocation{{"uint8", 7, "null", []*ec.KprobeArgumentChecker{
218+
ec.NewKprobeArgumentChecker().WithIntArg(0),
219+
ec.NewKprobeArgumentChecker().WithSizeArg(0),
220+
ec.NewKprobeArgumentChecker().WithUintArg(0),
221+
ec.NewKprobeArgumentChecker().WithUintArg(0),
222+
ec.NewKprobeArgumentChecker().WithUintArg(0),
223+
}}}
224+
199225
uprobeHook := `
200226
apiVersion: cilium.io/v1alpha1
201227
kind: TracingPolicy
@@ -222,6 +248,17 @@ spec:
222248
type: "` + tt[2].specTy + `"
223249
btfType: "mystruct"
224250
resolve: "` + tt[2].field + `"
251+
- index: 1
252+
type: "uint8"
253+
btfType: "mystruct"
254+
resolve: "sub.v8"
255+
selectors:
256+
- matchArgs:
257+
- args: [4]
258+
operator: "Equal"
259+
values:
260+
- "0"
261+
225262
`
226263

227264
uprobeConfigHook := []byte(uprobeHook)
@@ -231,16 +268,13 @@ spec:
231268
}
232269

233270
var checkers []ec.EventChecker
234-
for i := range tt {
235-
checkers = append(checkers, ec.NewProcessUprobeChecker("uprobe-resolve").
236-
WithProcess(ec.NewProcessChecker().
237-
WithBinary(sm.Full(uprobe)).
238-
WithArguments(
239-
sm.Full(tt[i].field+" "+strconv.Itoa(tt[i].filterVal)),
240-
),
241-
).WithArgs(ec.NewKprobeArgumentListMatcher().
242-
WithOperator(lc.Ordered).
243-
WithValues(tt[i].kpArgs...)))
271+
for _, ti := range tt {
272+
checkers = append(checkers, get_checker(ti, uprobe))
273+
}
274+
275+
var negative_checkers []ec.EventChecker
276+
for _, ti := range negative_tests {
277+
negative_checkers = append(negative_checkers, get_checker(ti, uprobe))
244278
}
245279

246280
var doneWG, readyWG sync.WaitGroup
@@ -256,12 +290,15 @@ spec:
256290
observertesthelper.LoopEvents(ctx, t, &doneWG, &readyWG, obs)
257291
readyWG.Wait()
258292

259-
for i := range tt {
260-
cmd := exec.Command(uprobe, tt[i].field, strconv.Itoa(tt[i].filterVal))
293+
for _, ti := range append(tt, negative_tests...) {
294+
cmd := exec.Command(uprobe, ti.field, strconv.Itoa(ti.filterVal))
261295
cmdErr := testutils.RunCmdAndLogOutput(t, cmd)
262296
require.NoError(t, cmdErr)
263297
}
264298

265299
err = jsonchecker.JsonTestCheck(t, ec.NewUnorderedEventChecker(checkers...))
266300
require.NoError(t, err)
301+
302+
err = jsonchecker.JsonTestCheckExpect(t, ec.NewUnorderedEventChecker(negative_checkers...), true)
303+
require.NoError(t, err)
267304
}

0 commit comments

Comments
 (0)