...

Source file src/github.com/cilium/ebpf/link/tracing.go

Documentation: github.com/cilium/ebpf/link

     1  package link
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/cilium/ebpf"
     7  	"github.com/cilium/ebpf/btf"
     8  	"github.com/cilium/ebpf/internal/sys"
     9  )
    10  
    11  type tracing struct {
    12  	RawLink
    13  }
    14  
    15  func (f *tracing) Update(new *ebpf.Program) error {
    16  	return fmt.Errorf("tracing update: %w", ErrNotSupported)
    17  }
    18  
    19  // AttachFreplace attaches the given eBPF program to the function it replaces.
    20  //
    21  // The program and name can either be provided at link time, or can be provided
    22  // at program load time. If they were provided at load time, they should be nil
    23  // and empty respectively here, as they will be ignored by the kernel.
    24  // Examples:
    25  //
    26  //	AttachFreplace(dispatcher, "function", replacement)
    27  //	AttachFreplace(nil, "", replacement)
    28  func AttachFreplace(targetProg *ebpf.Program, name string, prog *ebpf.Program) (Link, error) {
    29  	if (name == "") != (targetProg == nil) {
    30  		return nil, fmt.Errorf("must provide both or neither of name and targetProg: %w", errInvalidInput)
    31  	}
    32  	if prog == nil {
    33  		return nil, fmt.Errorf("prog cannot be nil: %w", errInvalidInput)
    34  	}
    35  	if prog.Type() != ebpf.Extension {
    36  		return nil, fmt.Errorf("eBPF program type %s is not an Extension: %w", prog.Type(), errInvalidInput)
    37  	}
    38  
    39  	var (
    40  		target int
    41  		typeID btf.TypeID
    42  	)
    43  	if targetProg != nil {
    44  		btfHandle, err := targetProg.Handle()
    45  		if err != nil {
    46  			return nil, err
    47  		}
    48  		defer btfHandle.Close()
    49  
    50  		spec, err := btfHandle.Spec(nil)
    51  		if err != nil {
    52  			return nil, err
    53  		}
    54  
    55  		var function *btf.Func
    56  		if err := spec.TypeByName(name, &function); err != nil {
    57  			return nil, err
    58  		}
    59  
    60  		target = targetProg.FD()
    61  		typeID, err = spec.TypeID(function)
    62  		if err != nil {
    63  			return nil, err
    64  		}
    65  	}
    66  
    67  	link, err := AttachRawLink(RawLinkOptions{
    68  		Target:  target,
    69  		Program: prog,
    70  		Attach:  ebpf.AttachNone,
    71  		BTF:     typeID,
    72  	})
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  
    77  	return &tracing{*link}, nil
    78  }
    79  
    80  type TracingOptions struct {
    81  	// Program must be of type Tracing with attach type
    82  	// AttachTraceFEntry/AttachTraceFExit/AttachModifyReturn or
    83  	// AttachTraceRawTp.
    84  	Program *ebpf.Program
    85  }
    86  
    87  type LSMOptions struct {
    88  	// Program must be of type LSM with attach type
    89  	// AttachLSMMac.
    90  	Program *ebpf.Program
    91  }
    92  
    93  // attachBTFID links all BPF program types (Tracing/LSM) that they attach to a btf_id.
    94  func attachBTFID(program *ebpf.Program) (Link, error) {
    95  	if program.FD() < 0 {
    96  		return nil, fmt.Errorf("invalid program %w", sys.ErrClosedFd)
    97  	}
    98  
    99  	fd, err := sys.RawTracepointOpen(&sys.RawTracepointOpenAttr{
   100  		ProgFd: uint32(program.FD()),
   101  	})
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  
   106  	raw := RawLink{fd: fd}
   107  	info, err := raw.Info()
   108  	if err != nil {
   109  		raw.Close()
   110  		return nil, err
   111  	}
   112  
   113  	if info.Type == RawTracepointType {
   114  		// Sadness upon sadness: a Tracing program with AttachRawTp returns
   115  		// a raw_tracepoint link. Other types return a tracing link.
   116  		return &rawTracepoint{raw}, nil
   117  	}
   118  
   119  	return &tracing{RawLink: RawLink{fd: fd}}, nil
   120  }
   121  
   122  // AttachTracing links a tracing (fentry/fexit/fmod_ret) BPF program or
   123  // a BTF-powered raw tracepoint (tp_btf) BPF Program to a BPF hook defined
   124  // in kernel modules.
   125  func AttachTracing(opts TracingOptions) (Link, error) {
   126  	if t := opts.Program.Type(); t != ebpf.Tracing {
   127  		return nil, fmt.Errorf("invalid program type %s, expected Tracing", t)
   128  	}
   129  
   130  	return attachBTFID(opts.Program)
   131  }
   132  
   133  // AttachLSM links a Linux security module (LSM) BPF Program to a BPF
   134  // hook defined in kernel modules.
   135  func AttachLSM(opts LSMOptions) (Link, error) {
   136  	if t := opts.Program.Type(); t != ebpf.LSM {
   137  		return nil, fmt.Errorf("invalid program type %s, expected LSM", t)
   138  	}
   139  
   140  	return attachBTFID(opts.Program)
   141  }
   142  

View as plain text