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  }