github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/operators/ebpf/attach.go (about)

     1  // Copyright 2024 The Inspektor Gadget authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package ebpfoperator
    16  
    17  import (
    18  	"fmt"
    19  	"net"
    20  	"strings"
    21  
    22  	"github.com/cilium/ebpf"
    23  	"github.com/cilium/ebpf/link"
    24  
    25  	"github.com/inspektor-gadget/inspektor-gadget/pkg/operators"
    26  	"github.com/inspektor-gadget/inspektor-gadget/pkg/uprobetracer"
    27  )
    28  
    29  const (
    30  	kprobePrefix    = "kprobe/"
    31  	kretprobePrefix = "kretprobe/"
    32  	iterPrefix      = "iter/"
    33  	fentryPrefix    = "fentry/"
    34  	fexitPrefix     = "fexit/"
    35  	uprobePrefix    = "uprobe/"
    36  	uretprobePrefix = "uretprobe/"
    37  	usdtPrefix      = "usdt/"
    38  )
    39  
    40  func (i *ebpfInstance) attachProgram(gadgetCtx operators.GadgetContext, p *ebpf.ProgramSpec, prog *ebpf.Program) (link.Link, error) {
    41  	switch p.Type {
    42  	case ebpf.Kprobe:
    43  		switch {
    44  		case strings.HasPrefix(p.SectionName, kprobePrefix):
    45  			i.logger.Debugf("Attaching kprobe %q to %q", p.Name, p.AttachTo)
    46  			return link.Kprobe(p.AttachTo, prog, nil)
    47  		case strings.HasPrefix(p.SectionName, kretprobePrefix):
    48  			i.logger.Debugf("Attaching kretprobe %q to %q", p.Name, p.AttachTo)
    49  			return link.Kretprobe(p.AttachTo, prog, nil)
    50  		case strings.HasPrefix(p.SectionName, uprobePrefix) ||
    51  			strings.HasPrefix(p.SectionName, uretprobePrefix) ||
    52  			strings.HasPrefix(p.SectionName, usdtPrefix):
    53  			uprobeTracer := i.uprobeTracers[p.Name]
    54  			switch strings.Split(p.SectionName, "/")[0] {
    55  			case "uprobe":
    56  				return nil, uprobeTracer.AttachProg(p.Name, uprobetracer.ProgUprobe, p.AttachTo, prog)
    57  			case "uretprobe":
    58  				return nil, uprobeTracer.AttachProg(p.Name, uprobetracer.ProgUretprobe, p.AttachTo, prog)
    59  			case "usdt":
    60  				return nil, uprobeTracer.AttachProg(p.Name, uprobetracer.ProgUSDT, p.AttachTo, prog)
    61  			}
    62  		}
    63  		return nil, fmt.Errorf("unsupported section name %q for program %q", p.SectionName, p.Name)
    64  	case ebpf.TracePoint:
    65  		i.logger.Debugf("Attaching tracepoint %q to %q", p.Name, p.AttachTo)
    66  		parts := strings.Split(p.AttachTo, "/")
    67  		return link.Tracepoint(parts[0], parts[1], prog, nil)
    68  	case ebpf.SocketFilter:
    69  		i.logger.Debugf("Attaching socket filter %q to %q", p.Name, p.AttachTo)
    70  		networkTracer := i.networkTracers[p.Name]
    71  		return nil, networkTracer.AttachProg(prog)
    72  	case ebpf.Tracing:
    73  		switch {
    74  		case strings.HasPrefix(p.SectionName, iterPrefix):
    75  			i.logger.Debugf("Attaching iter %q to %q", p.Name, p.AttachTo)
    76  			switch p.AttachTo {
    77  			case "task", "tcp", "udp":
    78  				return link.AttachIter(link.IterOptions{
    79  					Program: prog,
    80  				})
    81  			}
    82  			return nil, fmt.Errorf("unsupported iter type %q", p.AttachTo)
    83  		case strings.HasPrefix(p.SectionName, fentryPrefix):
    84  			i.logger.Debugf("Attaching fentry %q to %q", p.Name, p.AttachTo)
    85  			return link.AttachTracing(link.TracingOptions{
    86  				Program:    prog,
    87  				AttachType: ebpf.AttachTraceFEntry,
    88  			})
    89  		case strings.HasPrefix(p.SectionName, fexitPrefix):
    90  			i.logger.Debugf("Attaching fexit %q to %q", p.Name, p.AttachTo)
    91  			return link.AttachTracing(link.TracingOptions{
    92  				Program:    prog,
    93  				AttachType: ebpf.AttachTraceFExit,
    94  			})
    95  		}
    96  		return nil, fmt.Errorf("unsupported section name %q for program %q as type ebpf.Tracing", p.SectionName, p.Name)
    97  	case ebpf.RawTracepoint:
    98  		i.logger.Debugf("Attaching raw tracepoint %q to %q", p.Name, p.AttachTo)
    99  		return link.AttachRawTracepoint(link.RawTracepointOptions{
   100  			Name:    p.AttachTo,
   101  			Program: prog,
   102  		})
   103  	case ebpf.SchedCLS:
   104  		handler := i.tcHandlers[p.Name]
   105  
   106  		ifaceName := i.paramValues[ParamIface]
   107  		if ifaceName != "" {
   108  			iface, err := net.InterfaceByName(ifaceName)
   109  			if err != nil {
   110  				return nil, fmt.Errorf("getting interface %q: %w", ifaceName, err)
   111  			}
   112  
   113  			if err := handler.AttachIface(iface); err != nil {
   114  				return nil, fmt.Errorf("attaching iface %q: %w", ifaceName, err)
   115  			}
   116  		}
   117  
   118  		i.logger.Debugf("Attaching sched_cls %q", p.Name)
   119  		return nil, handler.AttachProg(prog)
   120  	case ebpf.LSM:
   121  		i.logger.Debugf("Attaching LSM %q to %q", p.Name, p.AttachTo)
   122  		return link.AttachLSM(link.LSMOptions{
   123  			Program: prog,
   124  		})
   125  	default:
   126  		return nil, fmt.Errorf("unsupported program %q of type %q", p.Name, p.Type)
   127  	}
   128  }