Skip to content

Commit

Permalink
link: attach multi-kprobes to entry and return of kernel symbols (ses…
Browse files Browse the repository at this point in the history
…sion)

Adding support to attach kprobe multi link as session [1] by adding
Session bool to KprobeMultiOptions. When set true it attaches the
link with BPF_TRACE_KPROBE_SESSION attach_type, which means:

  - program is attached to both function entry and return
  - entry program can decided if the return program gets executed
  - entry program can share u64 cookie value with return program

[1] https://lore.kernel.org/bpf/[email protected]/

Signed-off-by: Jiri Olsa <[email protected]>
Co-authored-by: Timo Beckers <[email protected]>
  • Loading branch information
olsajiri and ti-mo committed Jan 13, 2025
1 parent 1b27099 commit 638d6b6
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 11 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ jobs:
needs: build-and-lint
timeout-minutes: 15
env:
EBPF_TEST_IGNORE_VERSION: 'TestKprobeMulti,TestKprobeMultiErrors,TestKprobeMultiCookie,TestKprobeMultiProgramCall,TestHaveBPFLinkKprobeMulti,TestHaveProgramType/LircMode2'
EBPF_TEST_IGNORE_VERSION: 'TestKprobeMulti,TestKprobeMultiErrors,TestKprobeMultiCookie,TestKprobeMultiProgramCall,TestHaveBPFLinkKprobeMulti,TestKprobeSession,TestHaveBPFLinkKprobeSession,TestHaveProgramType/LircMode2'
steps:
- uses: actions/checkout@v4

Expand Down
5 changes: 3 additions & 2 deletions attachtype_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

79 changes: 71 additions & 8 deletions link/kprobe_multi.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ type KprobeMultiOptions struct {
// Each Cookie is assigned to the Symbol or Address specified at the
// corresponding slice index.
Cookies []uint64

// Session must be true when attaching Programs with the
// [ebpf.AttachTraceKprobeSession] attach type.
//
// This makes a Kprobe execute on both function entry and return. The entry
// program can share a cookie value with the return program and can decide
// whether the return program gets executed.
Session bool
}

// KprobeMulti attaches the given eBPF program to the entry point of a given set
Expand Down Expand Up @@ -82,9 +90,14 @@ func kprobeMulti(prog *ebpf.Program, opts KprobeMultiOptions, flags uint32) (Lin
return nil, fmt.Errorf("Cookies must be exactly Symbols or Addresses in length: %w", errInvalidInput)
}

attachType := sys.BPF_TRACE_KPROBE_MULTI
if opts.Session {
attachType = sys.BPF_TRACE_KPROBE_SESSION
}

attr := &sys.LinkCreateKprobeMultiAttr{
ProgFd: uint32(prog.FD()),
AttachType: sys.BPF_TRACE_KPROBE_MULTI,
AttachType: attachType,
KprobeMultiFlags: flags,
}

Expand All @@ -103,21 +116,30 @@ func kprobeMulti(prog *ebpf.Program, opts KprobeMultiOptions, flags uint32) (Lin
}

fd, err := sys.LinkCreateKprobeMulti(attr)
if err == nil {
return &kprobeMultiLink{RawLink{fd, ""}}, nil
}

if errors.Is(err, unix.ESRCH) {
return nil, fmt.Errorf("couldn't find one or more symbols: %w", os.ErrNotExist)
}
if errors.Is(err, unix.EINVAL) {
return nil, fmt.Errorf("%w (missing kernel symbol or prog's AttachType not AttachTraceKprobeMulti?)", err)
}

if err != nil {
if haveFeatErr := haveBPFLinkKprobeMulti(); haveFeatErr != nil {
if opts.Session {
if haveFeatErr := haveBPFLinkKprobeSession(); haveFeatErr != nil {
return nil, haveFeatErr
}
return nil, err
}
if haveFeatErr := haveBPFLinkKprobeMulti(); haveFeatErr != nil {
return nil, haveFeatErr
}

// Check EINVAL after running feature probes, since it's also returned when
// the kernel doesn't support the multi/session attach types.
if errors.Is(err, unix.EINVAL) {
return nil, fmt.Errorf("%w (missing kernel symbol or prog's AttachType not %s?)", err, ebpf.AttachType(attachType))
}

return &kprobeMultiLink{RawLink{fd, ""}}, nil
return nil, err
}

type kprobeMultiLink struct {
Expand Down Expand Up @@ -189,3 +211,44 @@ var haveBPFLinkKprobeMulti = internal.NewFeatureTest("bpf_link_kprobe_multi", fu

return nil
}, "5.18")

var haveBPFLinkKprobeSession = internal.NewFeatureTest("bpf_link_kprobe_session", func() error {
prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
Name: "probe_kps_link",
Type: ebpf.Kprobe,
Instructions: asm.Instructions{
asm.Mov.Imm(asm.R0, 0),
asm.Return(),
},
AttachType: ebpf.AttachTraceKprobeSession,
License: "MIT",
})
if errors.Is(err, unix.E2BIG) {
// Kernel doesn't support AttachType field.
return internal.ErrNotSupported
}
if err != nil {
return err
}
defer prog.Close()

fd, err := sys.LinkCreateKprobeMulti(&sys.LinkCreateKprobeMultiAttr{
ProgFd: uint32(prog.FD()),
AttachType: sys.BPF_TRACE_KPROBE_SESSION,
Count: 1,
Syms: sys.NewStringSlicePointer([]string{"vprintk"}),
})
switch {
case errors.Is(err, unix.EINVAL):
return internal.ErrNotSupported
// If CONFIG_FPROBE isn't set.
case errors.Is(err, unix.EOPNOTSUPP):
return internal.ErrNotSupported
case err != nil:
return err
}

fd.Close()

return nil
}, "6.10")
19 changes: 19 additions & 0 deletions link/kprobe_multi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"os"
"testing"

"github.com/go-quicktest/qt"

"github.com/cilium/ebpf"
"github.com/cilium/ebpf/internal/testutils"
"github.com/cilium/ebpf/internal/unix"
Expand Down Expand Up @@ -134,3 +136,20 @@ func TestKprobeMultiProgramCall(t *testing.T) {
func TestHaveBPFLinkKprobeMulti(t *testing.T) {
testutils.CheckFeatureTest(t, haveBPFLinkKprobeMulti)
}

func TestKprobeSession(t *testing.T) {
testutils.SkipIfNotSupported(t, haveBPFLinkKprobeMulti())

prog := mustLoadProgram(t, ebpf.Kprobe, ebpf.AttachTraceKprobeSession, "")

km, err := KprobeMulti(prog, KprobeMultiOptions{Symbols: kprobeMultiSyms, Session: true})
testutils.SkipIfNotSupported(t, err)
qt.Assert(t, qt.IsNil(err))
defer km.Close()

testLink(t, km, prog)
}

func TestHaveBPFLinkKprobeSession(t *testing.T) {
testutils.CheckFeatureTest(t, haveBPFLinkKprobeSession)
}
1 change: 1 addition & 0 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ const (
AttachSkReuseportSelectOrMigrate = AttachType(sys.BPF_SK_REUSEPORT_SELECT_OR_MIGRATE)
AttachPerfEvent = AttachType(sys.BPF_PERF_EVENT)
AttachTraceKprobeMulti = AttachType(sys.BPF_TRACE_KPROBE_MULTI)
AttachTraceKprobeSession = AttachType(sys.BPF_TRACE_KPROBE_SESSION)
AttachLSMCgroup = AttachType(sys.BPF_LSM_CGROUP)
AttachStructOps = AttachType(sys.BPF_STRUCT_OPS)
AttachNetfilter = AttachType(sys.BPF_NETFILTER)
Expand Down

0 comments on commit 638d6b6

Please sign in to comment.