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