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  }