Skip to content

Commit

Permalink
tetragon: Pin kprobe/multi/tracepoint links
Browse files Browse the repository at this point in the history
Signed-off-by: Jiri Olsa <[email protected]>
  • Loading branch information
olsajiri committed Jun 26, 2024
1 parent 0beb76e commit 56ff75f
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 12 deletions.
66 changes: 55 additions & 11 deletions pkg/sensors/program/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/cilium/ebpf"
"github.com/cilium/ebpf/btf"
"github.com/cilium/ebpf/link"
"github.com/cilium/tetragon/pkg/bpf"
cachedbtf "github.com/cilium/tetragon/pkg/btf"
"github.com/cilium/tetragon/pkg/logger"
"github.com/cilium/tetragon/pkg/option"
Expand Down Expand Up @@ -75,7 +76,31 @@ func RawAttachWithFlags(targetFD int, flags uint32) AttachFunc {
}
}

func TracepointAttach(load *Program) AttachFunc {
func linkPin(lnk link.Link, bpfDir string, load *Program, extra ...string) error {
if !bpf.HasLinkPin() {
return nil
}

pinPath := filepath.Join(bpfDir, load.PinPath)
if load.Override {
pinPath = pinPath + "_override"
}
if load.RetProbe {
pinPath = pinPath + "_return"
}
if len(extra) != 0 {
pinPath = pinPath + "_" + strings.Join(extra, "_")
}
pinPath = pinPath + "_link"

err := lnk.Pin(pinPath)
if err != nil {
return fmt.Errorf("pinning link '%s' failed: %w", pinPath, err)
}
return nil
}

func TracepointAttach(load *Program, bpfDir string) AttachFunc {
return func(_ *ebpf.Collection, _ *ebpf.CollectionSpec,
prog *ebpf.Program, spec *ebpf.ProgramSpec) (unloader.Unloader, error) {

Expand All @@ -87,6 +112,11 @@ func TracepointAttach(load *Program) AttachFunc {
if err != nil {
return nil, fmt.Errorf("attaching '%s' failed: %w", spec.Name, err)
}
err = linkPin(tpLink, bpfDir, load)
if err != nil {
tpLink.Close()
return nil, err
}
return &unloader.RelinkUnloader{
UnloadProg: unloader.PinUnloader{Prog: prog}.Unload,
IsLinked: true,
Expand Down Expand Up @@ -157,7 +187,7 @@ func KprobeOpen(load *Program) OpenFunc {
}
}

func kprobeAttach(load *Program, prog *ebpf.Program, spec *ebpf.ProgramSpec, symbol string) (unloader.Unloader, error) {
func kprobeAttach(load *Program, prog *ebpf.Program, spec *ebpf.ProgramSpec, symbol, bpfDir string, extra ...string) (unloader.Unloader, error) {
var linkFn func() (link.Link, error)

if load.RetProbe {
Expand All @@ -170,6 +200,13 @@ func kprobeAttach(load *Program, prog *ebpf.Program, spec *ebpf.ProgramSpec, sym
if err != nil {
return nil, fmt.Errorf("attaching '%s' failed: %w", spec.Name, err)
}

err = linkPin(lnk, bpfDir, load, extra...)
if err != nil {
lnk.Close()
return nil, err
}

return &unloader.RelinkUnloader{
UnloadProg: unloader.PinUnloader{Prog: prog}.Unload,
IsLinked: true,
Expand Down Expand Up @@ -202,7 +239,7 @@ func kprobeAttachOverride(load *Program, bpfDir string,
return fmt.Errorf("pinning '%s' to '%s' failed: %w", load.Label, pinPath, err)
}

load.unloaderOverride, err = kprobeAttach(load, prog, spec, load.Attach)
load.unloaderOverride, err = kprobeAttach(load, prog, spec, load.Attach, bpfDir)
if err != nil {
logger.GetLogger().Warnf("Failed to attach override program: %w", err)
}
Expand Down Expand Up @@ -271,7 +308,7 @@ func KprobeAttach(load *Program, bpfDir string) AttachFunc {
}
}

return kprobeAttach(load, prog, spec, load.Attach)
return kprobeAttach(load, prog, spec, load.Attach, bpfDir)
}
}

Expand Down Expand Up @@ -404,7 +441,7 @@ func LSMAttach() AttachFunc {
}

func multiKprobeAttach(load *Program, prog *ebpf.Program,
spec *ebpf.ProgramSpec, opts link.KprobeMultiOptions) (unloader.Unloader, error) {
spec *ebpf.ProgramSpec, bpfDir string, opts link.KprobeMultiOptions) (unloader.Unloader, error) {

var lnk link.Link
var err error
Expand All @@ -417,6 +454,13 @@ func multiKprobeAttach(load *Program, prog *ebpf.Program,
if err != nil {
return nil, fmt.Errorf("attaching '%s' failed: %w", spec.Name, err)
}

err = linkPin(lnk, bpfDir, load)
if err != nil {
lnk.Close()
return nil, err
}

return unloader.ChainUnloader{
unloader.PinUnloader{
Prog: prog,
Expand Down Expand Up @@ -462,7 +506,7 @@ func MultiKprobeAttach(load *Program, bpfDir string) AttachFunc {
Symbols: data.Overrides,
}

load.unloaderOverride, err = multiKprobeAttach(load, progOverride, progOverrideSpec, opts)
load.unloaderOverride, err = multiKprobeAttach(load, progOverride, progOverrideSpec, bpfDir, opts)
if err != nil {
logger.GetLogger().Warnf("Failed to attach override program: %w", err)
}
Expand All @@ -473,7 +517,7 @@ func MultiKprobeAttach(load *Program, bpfDir string) AttachFunc {
Cookies: data.Cookies,
}

return multiKprobeAttach(load, prog, spec, opts)
return multiKprobeAttach(load, prog, spec, bpfDir, opts)
}
}

Expand All @@ -486,7 +530,7 @@ func LoadTracepointProgram(bpfDir string, load *Program, verbose int) error {
}
}
opts := &LoadOpts{
Attach: TracepointAttach(load),
Attach: TracepointAttach(load, bpfDir),
TcMap: tc.name,
TcPrefix: tc.prefix,
}
Expand Down Expand Up @@ -517,7 +561,7 @@ func LoadKprobeProgram(bpfDir string, load *Program, verbose int) error {
return loadProgram(bpfDir, load, opts, verbose)
}

func KprobeAttachMany(load *Program, syms []string) AttachFunc {
func KprobeAttachMany(load *Program, syms []string, bpfDir string) AttachFunc {
return func(_ *ebpf.Collection, _ *ebpf.CollectionSpec,
prog *ebpf.Program, spec *ebpf.ProgramSpec) (unloader.Unloader, error) {

Expand All @@ -528,7 +572,7 @@ func KprobeAttachMany(load *Program, syms []string) AttachFunc {
}

for idx := range syms {
un, err := kprobeAttach(load, prog, spec, syms[idx])
un, err := kprobeAttach(load, prog, spec, syms[idx], bpfDir, fmt.Sprintf("%d_%s", idx, syms[idx]))
if err != nil {
return nil, err
}
Expand All @@ -541,7 +585,7 @@ func KprobeAttachMany(load *Program, syms []string) AttachFunc {

func LoadKprobeProgramAttachMany(bpfDir string, load *Program, syms []string, verbose int) error {
opts := &LoadOpts{
Attach: KprobeAttachMany(load, syms),
Attach: KprobeAttachMany(load, syms, bpfDir),
}
return loadProgram(bpfDir, load, opts, verbose)
}
Expand Down
18 changes: 17 additions & 1 deletion pkg/sensors/unloader/unloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/cilium/ebpf"
"github.com/cilium/ebpf/link"
"github.com/cilium/tetragon/pkg/bpf"
"github.com/vishvananda/netlink"
"go.uber.org/multierr"
"golang.org/x/sys/unix"
Expand Down Expand Up @@ -55,6 +56,13 @@ type PinUnloader struct {
Prog *ebpf.Program
}

func linkUnpin(lnk link.Link) error {
if bpf.HasLinkPin() {
return lnk.Unpin()
}
return nil
}

func (pu PinUnloader) Unload() error {
defer pu.Prog.Close()
return pu.Prog.Unpin()
Expand All @@ -66,7 +74,8 @@ type LinkUnloader struct {
}

func (lu LinkUnloader) Unload() error {
return lu.Link.Close()
defer lu.Link.Close()
return linkUnpin(lu.Link)
}

// rawDetachUnloader can be used to unload cgroup and sockmap programs.
Expand Down Expand Up @@ -163,6 +172,9 @@ type RelinkUnloader struct {
func (u *RelinkUnloader) Unload() error {
var ret error
if u.IsLinked {
if err := linkUnpin(u.Link); err != nil {
ret = multierr.Append(ret, err)
}
if err := u.Link.Close(); err != nil {
ret = multierr.Append(ret, err)
} else {
Expand All @@ -178,6 +190,10 @@ func (u *RelinkUnloader) Unlink() error {
return errors.New("Unlink failed: program not linked")
}

if err := linkUnpin(u.Link); err != nil {
return fmt.Errorf("Unlink failed: %w", err)
}

if err := u.Link.Close(); err != nil {
return fmt.Errorf("Unlink failed: %w", err)
}
Expand Down

0 comments on commit 56ff75f

Please sign in to comment.