github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/link/kprobe_multi_test.go (about) 1 package link 2 3 import ( 4 "errors" 5 "os" 6 "testing" 7 8 "github.com/cilium/ebpf" 9 "github.com/cilium/ebpf/internal/testutils" 10 "github.com/cilium/ebpf/internal/unix" 11 ) 12 13 var kprobeMultiSyms = []string{"vprintk", "inet6_release"} 14 15 func TestKprobeMulti(t *testing.T) { 16 testutils.SkipIfNotSupported(t, haveBPFLinkKprobeMulti()) 17 18 prog := mustLoadProgram(t, ebpf.Kprobe, ebpf.AttachTraceKprobeMulti, "") 19 20 km, err := KprobeMulti(prog, KprobeMultiOptions{Symbols: kprobeMultiSyms}) 21 if err != nil { 22 t.Fatal(err) 23 } 24 defer km.Close() 25 26 testLink(t, km, prog) 27 } 28 29 func TestKprobeMultiInput(t *testing.T) { 30 // Program type that loads on all kernels. Not expected to link successfully. 31 prog := mustLoadProgram(t, ebpf.SocketFilter, 0, "") 32 33 // One of Symbols or Addresses must be given. 34 _, err := KprobeMulti(prog, KprobeMultiOptions{}) 35 if !errors.Is(err, errInvalidInput) { 36 t.Fatalf("expected errInvalidInput, got: %v", err) 37 } 38 39 // Symbols and Addresses are mutually exclusive. 40 _, err = KprobeMulti(prog, KprobeMultiOptions{ 41 Symbols: []string{"foo"}, 42 Addresses: []uintptr{1}, 43 }) 44 if !errors.Is(err, errInvalidInput) { 45 t.Fatalf("expected errInvalidInput, got: %v", err) 46 } 47 48 // One Symbol, two cookies.. 49 _, err = KprobeMulti(prog, KprobeMultiOptions{ 50 Symbols: []string{"one"}, 51 Cookies: []uint64{2, 3}, 52 }) 53 if !errors.Is(err, errInvalidInput) { 54 t.Fatalf("expected errInvalidInput, got: %v", err) 55 } 56 } 57 58 func TestKprobeMultiErrors(t *testing.T) { 59 testutils.SkipIfNotSupported(t, haveBPFLinkKprobeMulti()) 60 61 prog := mustLoadProgram(t, ebpf.Kprobe, ebpf.AttachTraceKprobeMulti, "") 62 63 // Nonexistent kernel symbol. 64 _, err := KprobeMulti(prog, KprobeMultiOptions{Symbols: []string{"bogus"}}) 65 if !errors.Is(err, os.ErrNotExist) && !errors.Is(err, unix.EINVAL) { 66 t.Fatalf("expected ErrNotExist or EINVAL, got: %s", err) 67 } 68 69 // Only have a negative test for addresses as it would be hard to maintain a 70 // proper one. 71 if _, err := KprobeMulti(prog, KprobeMultiOptions{ 72 Addresses: []uintptr{^uintptr(0)}, 73 }); !errors.Is(err, unix.EINVAL) { 74 t.Fatalf("expected EINVAL, got: %s", err) 75 } 76 } 77 78 func TestKprobeMultiCookie(t *testing.T) { 79 testutils.SkipIfNotSupported(t, haveBPFLinkKprobeMulti()) 80 81 prog := mustLoadProgram(t, ebpf.Kprobe, ebpf.AttachTraceKprobeMulti, "") 82 83 km, err := KprobeMulti(prog, KprobeMultiOptions{ 84 Symbols: kprobeMultiSyms, 85 Cookies: []uint64{0, 1}, 86 }) 87 if err != nil { 88 t.Fatal(err) 89 } 90 _ = km.Close() 91 } 92 93 func TestKprobeMultiProgramCall(t *testing.T) { 94 testutils.SkipIfNotSupported(t, haveBPFLinkKprobeMulti()) 95 96 m, p := newUpdaterMapProg(t, ebpf.Kprobe, ebpf.AttachTraceKprobeMulti) 97 98 // For simplicity, just assert the increment happens with any symbol in the array. 99 opts := KprobeMultiOptions{ 100 Symbols: []string{"__do_sys_getpid", "__do_sys_gettid"}, 101 } 102 km, err := KprobeMulti(p, opts) 103 if err != nil { 104 t.Fatal(err) 105 } 106 107 // Trigger ebpf program call. 108 unix.Getpid() 109 unix.Gettid() 110 111 // Assert that the value got incremented to at least 2, while allowing 112 // for bigger values, because we could race with other getpid/gettid 113 // callers. 114 assertMapValueGE(t, m, 0, 2) 115 116 // Close the link. 117 if err := km.Close(); err != nil { 118 t.Fatal(err) 119 } 120 121 // Reset map value to 0 at index 0. 122 if err := m.Update(uint32(0), uint32(0), ebpf.UpdateExist); err != nil { 123 t.Fatal(err) 124 } 125 126 // Retrigger the ebpf program call. 127 unix.Getpid() 128 unix.Gettid() 129 130 // Assert that this time the value has not been updated. 131 assertMapValue(t, m, 0, 0) 132 } 133 134 func TestHaveBPFLinkKprobeMulti(t *testing.T) { 135 testutils.CheckFeatureTest(t, haveBPFLinkKprobeMulti) 136 }