Skip to content

Commit e900a2c

Browse files
tetragon: test uprobe resolve failure
Test that the resolve error depth is expected when NULL pointers are encountered. Test that matchArgs will not match when resolve fails. Signed-off-by: Andy Strohman <[email protected]>
1 parent 39c3852 commit e900a2c

File tree

1 file changed

+171
-0
lines changed

1 file changed

+171
-0
lines changed

pkg/sensors/tracing/uprobe_amd64_test.go

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,3 +504,174 @@ func TestUprobePtRegsDataMatch(t *testing.T) {
504504
func TestUprobePtRegsDataNotMatch(t *testing.T) {
505505
testUprobePtRegsMatch(t, 10, true)
506506
}
507+
508+
func TestUprobeResolveNull(t *testing.T) {
509+
if !config.EnableLargeProgs() || !bpf.HasUprobeRefCtrOffset() {
510+
t.Skip("Need 5.3 or newer kernel for uprobe ref_ctr_off support for this test.")
511+
}
512+
513+
if !bpf.HasProbeWriteUserHelper() {
514+
t.Skip("need bpf_probe_write_user() for this test")
515+
}
516+
517+
uprobe := testutils.RepoRootPath("contrib/tester-progs/uprobe-null")
518+
uprobeBtf := testutils.RepoRootPath("contrib/tester-progs/uprobe-null.btf")
519+
520+
tt := []struct {
521+
arg string
522+
kpArgs []*ec.KprobeArgumentChecker
523+
}{
524+
{"first", []*ec.KprobeArgumentChecker{
525+
ec.NewKprobeArgumentChecker().WithResolveErrDepth(1),
526+
}},
527+
{"middle", []*ec.KprobeArgumentChecker{
528+
ec.NewKprobeArgumentChecker().WithResolveErrDepth(2),
529+
}},
530+
{"nonull", []*ec.KprobeArgumentChecker{
531+
ec.NewKprobeArgumentChecker().WithIntArg(0).WithResolveErrDepth(0),
532+
}},
533+
}
534+
535+
uprobeHook := `
536+
apiVersion: cilium.io/v1alpha1
537+
kind: TracingPolicy
538+
metadata:
539+
name: "uprobe-null"
540+
spec:
541+
uprobes:
542+
- path: "` + uprobe + `"
543+
btfPath: "` + uprobeBtf + `"
544+
symbols:
545+
- "func"
546+
args:
547+
- index: 0
548+
type: "int32"
549+
btfType: "mystruct"
550+
resolve: "subp.val"
551+
`
552+
553+
uprobeConfigHook := []byte(uprobeHook)
554+
err := os.WriteFile(testConfigFile, uprobeConfigHook, 0644)
555+
if err != nil {
556+
t.Fatalf("writeFile(%s): err %s", testConfigFile, err)
557+
}
558+
559+
var checkers []ec.EventChecker
560+
for i := range tt {
561+
checkers = append(checkers, ec.NewProcessUprobeChecker("uprobe-null").
562+
WithProcess(ec.NewProcessChecker().
563+
WithBinary(sm.Full(uprobe)).
564+
WithArguments(
565+
sm.Full(tt[i].arg)),
566+
).WithArgs(ec.NewKprobeArgumentListMatcher().
567+
WithOperator(lc.Ordered).
568+
WithValues(tt[i].kpArgs...)))
569+
}
570+
571+
var doneWG, readyWG sync.WaitGroup
572+
defer doneWG.Wait()
573+
574+
ctx, cancel := context.WithTimeout(context.Background(), tus.Conf().CmdWaitTime)
575+
defer cancel()
576+
577+
obs, err := observertesthelper.GetDefaultObserverWithFile(t, ctx, testConfigFile, tus.Conf().TetragonLib, observertesthelper.WithMyPid())
578+
if err != nil {
579+
t.Fatalf("GetDefaultObserverWithFile error: %s", err)
580+
}
581+
observertesthelper.LoopEvents(ctx, t, &doneWG, &readyWG, obs)
582+
readyWG.Wait()
583+
584+
for i := range tt {
585+
cmd := exec.Command(uprobe, tt[i].arg)
586+
cmdErr := testutils.RunCmdAndLogOutput(t, cmd)
587+
require.NoError(t, cmdErr)
588+
}
589+
590+
err = jsonchecker.JsonTestCheck(t, ec.NewUnorderedEventChecker(checkers...))
591+
require.NoError(t, err)
592+
}
593+
594+
func UprobeResolveNullMatch(t *testing.T, expectCheckerFailure bool, arg string) {
595+
if !config.EnableLargeProgs() || !bpf.HasUprobeRefCtrOffset() {
596+
t.Skip("Need 5.3 or newer kernel for uprobe ref_ctr_off support for this test.")
597+
}
598+
599+
if !bpf.HasProbeWriteUserHelper() {
600+
t.Skip("need bpf_probe_write_user() for this test")
601+
}
602+
603+
uprobe := testutils.RepoRootPath("contrib/tester-progs/uprobe-null")
604+
uprobeBtf := testutils.RepoRootPath("contrib/tester-progs/uprobe-null.btf")
605+
606+
uprobeHook := `
607+
apiVersion: cilium.io/v1alpha1
608+
kind: TracingPolicy
609+
metadata:
610+
name: "uprobe-null"
611+
spec:
612+
uprobes:
613+
- path: "` + uprobe + `"
614+
btfPath: "` + uprobeBtf + `"
615+
symbols:
616+
- "func"
617+
args:
618+
- index: 0
619+
type: "int32"
620+
btfType: "mystruct"
621+
resolve: "subp.val"
622+
selectors:
623+
- matchArgs:
624+
- args: [0]
625+
operator: "Equal"
626+
values:
627+
- "0"
628+
`
629+
630+
uprobeConfigHook := []byte(uprobeHook)
631+
err := os.WriteFile(testConfigFile, uprobeConfigHook, 0644)
632+
if err != nil {
633+
t.Fatalf("writeFile(%s): err %s", testConfigFile, err)
634+
}
635+
636+
kpArgs := []*ec.KprobeArgumentChecker{
637+
ec.NewKprobeArgumentChecker(),
638+
}
639+
640+
var checkers []ec.EventChecker
641+
checkers = append(checkers, ec.NewProcessUprobeChecker("uprobe-null").
642+
WithProcess(ec.NewProcessChecker().
643+
WithBinary(sm.Full(uprobe)).
644+
WithArguments(
645+
sm.Full(arg)),
646+
).WithArgs(ec.NewKprobeArgumentListMatcher().
647+
WithOperator(lc.Ordered).
648+
WithValues(kpArgs...)))
649+
650+
var doneWG, readyWG sync.WaitGroup
651+
defer doneWG.Wait()
652+
653+
ctx, cancel := context.WithTimeout(context.Background(), tus.Conf().CmdWaitTime)
654+
defer cancel()
655+
656+
obs, err := observertesthelper.GetDefaultObserverWithFile(t, ctx, testConfigFile, tus.Conf().TetragonLib, observertesthelper.WithMyPid())
657+
if err != nil {
658+
t.Fatalf("GetDefaultObserverWithFile error: %s", err)
659+
}
660+
observertesthelper.LoopEvents(ctx, t, &doneWG, &readyWG, obs)
661+
readyWG.Wait()
662+
663+
cmd := exec.Command(uprobe, arg)
664+
cmdErr := testutils.RunCmdAndLogOutput(t, cmd)
665+
require.NoError(t, cmdErr)
666+
667+
err = jsonchecker.JsonTestCheckExpect(t, ec.NewUnorderedEventChecker(checkers...), expectCheckerFailure)
668+
require.NoError(t, err)
669+
}
670+
671+
func TestUprobeResolveNullMatchPositive(t *testing.T) {
672+
UprobeResolveNullMatch(t, false, "nonull")
673+
}
674+
675+
func TestUprobeResolveNullMatchNegative(t *testing.T) {
676+
UprobeResolveNullMatch(t, true, "first")
677+
}

0 commit comments

Comments
 (0)