@@ -504,3 +504,174 @@ func TestUprobePtRegsDataMatch(t *testing.T) {
504504func 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