Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[btf] Cleanup AddModulesToSpec #2627

Merged
merged 1 commit into from
Jul 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions docs/data/tetragon_flags.yaml

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

54 changes: 0 additions & 54 deletions pkg/btf/btf.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,9 @@
package btf

import (
"bytes"
"fmt"
"os"
"path"
"path/filepath"
"strings"

"github.com/cilium/ebpf/btf"
"github.com/cilium/tetragon/pkg/defaults"
Expand Down Expand Up @@ -90,57 +87,6 @@ func NewBTF() (*btf.Spec, error) {
return btf.LoadSpec(btfFile)
}

func AddModulesToSpec(spec *btf.Spec, kmods []string) (*btf.Spec, error) {
allTypes := []btf.Type{}
modulePaths := []string{}

iter := spec.Iterate()
for iter.Next() {
allTypes = append(allTypes, iter.Type)
}

for _, module := range kmods {
path := filepath.Join("/sys/kernel/btf", module)
f, err := os.Open(path)
if err != nil {
logger.GetLogger().WithField("path", path).Warn("btf: Path does not exist")
continue
}
defer f.Close()

modulePaths = append(modulePaths, path)

modSpec, err := btf.LoadSplitSpecFromReader(f, spec)
if err != nil {
return nil, fmt.Errorf("failed to load %s btf: %w", module, err)
}

iter := modSpec.Iterate()
for iter.Next() {
allTypes = append(allTypes, iter.Type)
}
}

logger.GetLogger().WithField("modules", strings.Join(modulePaths, " ")).Info("btf: Loaded symbols from modules")

b, err := btf.NewBuilder(allTypes)
if err != nil {
return nil, fmt.Errorf("failed to call btf.NewBuilder: %w", err)
}

raw, err := b.Marshal(nil, nil)
if err != nil {
return nil, fmt.Errorf("failed to call b.Marshal: %w", err)
}

spec, err = btf.LoadSpecFromReader(bytes.NewReader(raw))
if err != nil {
return nil, fmt.Errorf("failed to call btf.LoadSpecFromReader: %w", err)
}

return spec, nil
}

func InitCachedBTF(lib, btf string) error {
var err error

Expand Down
19 changes: 18 additions & 1 deletion pkg/btf/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/cilium/ebpf/btf"
"github.com/cilium/tetragon/pkg/arch"
"github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1"
"github.com/cilium/tetragon/pkg/ksyms"
"github.com/cilium/tetragon/pkg/logger"
"github.com/cilium/tetragon/pkg/syscallinfo"
)
Expand Down Expand Up @@ -46,8 +47,24 @@ func (e *ValidationFailed) Error() string {
func ValidateKprobeSpec(bspec *btf.Spec, call string, kspec *v1alpha1.KProbeSpec) error {
var fn *btf.Func

// get kernel symbols
ks, err := ksyms.KernelSymbols()
if err != nil {
return fmt.Errorf("validateKprobeSpec: ksyms.KernelSymbols: %w", err)
}

// check if this functio name is part of a kernel module
if kmod, err := ks.GetKmod(call); err == nil {
// get the spec from the kernel module and continue the validation with that
kmodSpec, err := btf.LoadKernelModuleSpec(kmod)
if err != nil {
return fmt.Errorf("validateKprobeSpec: btf.LoadKernelModuleSpec: %w", err)
}
bspec = kmodSpec
}

origCall := call
err := bspec.TypeByName(call, &fn)
err = bspec.TypeByName(call, &fn)
if err != nil && kspec.Syscall {
// Try with system call prefix
call, err = arch.AddSyscallPrefix(call)
Expand Down
17 changes: 17 additions & 0 deletions pkg/ksyms/ksyms.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type ksym struct {
addr uint64
name string
ty string
kmod string
}

// Ksyms is a structure for kernel symbols
Expand Down Expand Up @@ -103,6 +104,11 @@ func NewKsyms(procfs string) (*Ksyms, error) {
break
}

// check if this symbol is part of a kmod
if sym.isFunction() && len(fields) >= 4 {
sym.kmod = string(strings.Trim(fields[3], "[]"))
}

if !needsSort && len(ksyms.table) > 0 {
lastSym := ksyms.table[len(ksyms.table)-1]
if lastSym.addr > sym.addr {
Expand Down Expand Up @@ -202,3 +208,14 @@ func (k *Ksyms) IsAvailable(name string) bool {
}
return false
}

func (k *Ksyms) GetKmod(name string) (string, error) {
// This linear search is slow. But this only happens during the validation
// of kprobe-based tracing polies. TODO: optimise if needed
for _, s := range k.table {
if s.name == name && s.kmod != "" {
return s.kmod, nil
}
}
return "", fmt.Errorf("symbol %s not found in kallsyms or is not part of a module", name)
}
2 changes: 0 additions & 2 deletions pkg/option/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,6 @@ type config struct {

EnableMsgHandlingLatency bool

KMods []string

EnablePodInfo bool
EnableTracingPolicyCRD bool

Expand Down
6 changes: 0 additions & 6 deletions pkg/option/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,6 @@ const (

KeyEnableMsgHandlingLatency = "enable-msg-handling-latency"

KeyKmods = "kmods"

KeyEnablePodInfo = "enable-pod-info"
KeyEnableTracingPolicyCRD = "enable-tracing-policy-crd"

Expand Down Expand Up @@ -189,8 +187,6 @@ func ReadAndSetFlags() error {

Config.TracingPolicyDir = viper.GetString(KeyTracingPolicyDir)

Config.KMods = viper.GetStringSlice(KeyKmods)

Config.EnablePodInfo = viper.GetBool(KeyEnablePodInfo)
Config.EnableTracingPolicyCRD = viper.GetBool(KeyEnableTracingPolicyCRD)

Expand Down Expand Up @@ -353,8 +349,6 @@ func AddFlags(flags *pflag.FlagSet) {

flags.Bool(KeyEnableMsgHandlingLatency, false, "Enable metrics for message handling latency")

flags.StringSlice(KeyKmods, []string{}, "List of kernel modules to load symbols from")

flags.String(KeyRBQueueSize, "65535", "Set size of channel between ring buffer and sensor go routines (default 65k, allows K/M/G suffix)")

flags.Bool(KeyEnablePodInfo, false, "Enable PodInfo custom resource")
Expand Down
12 changes: 4 additions & 8 deletions pkg/sensors/program/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"github.com/cilium/ebpf/link"
cachedbtf "github.com/cilium/tetragon/pkg/btf"
"github.com/cilium/tetragon/pkg/logger"
"github.com/cilium/tetragon/pkg/option"
"github.com/cilium/tetragon/pkg/sensors/unloader"
"golang.org/x/sys/unix"
)
Expand Down Expand Up @@ -719,19 +718,13 @@ func doLoadProgram(
verbose int,
) (*LoadedCollection, error) {
var btfSpec *btf.Spec
if btfFilePath := cachedbtf.GetCachedBTFFile(); btfFilePath != "/sys/kernel/btf/vmlinux" || len(option.Config.KMods) > 0 {
if btfFilePath := cachedbtf.GetCachedBTFFile(); btfFilePath != "/sys/kernel/btf/vmlinux" {
// Non-standard path to BTF, open it and provide it as 'KernelTypes'.
var err error
btfSpec, err = btf.LoadSpec(btfFilePath)
if err != nil {
return nil, fmt.Errorf("opening BTF file '%s' failed: %w", btfFilePath, err)
}
if len(option.Config.KMods) > 0 {
btfSpec, err = cachedbtf.AddModulesToSpec(btfSpec, option.Config.KMods)
if err != nil {
return nil, fmt.Errorf("adding modules to spec failed: %w", err)
}
}
}

spec, err := ebpf.LoadCollectionSpec(load.Name)
Expand Down Expand Up @@ -821,6 +814,9 @@ func doLoadProgram(
// as that makes the loading very slow.
opts.Programs.LogLevel = 1
opts.Programs.LogSize = verifierLogBufferSize
if load.KernelTypes != nil {
opts.Programs.KernelTypes = load.KernelTypes
}
// If we hit ENOSPC that means that our log size is not big enough,
// so keep trying again with log size * 2 until we succeed or the kernel
// complains.
Expand Down
4 changes: 4 additions & 0 deletions pkg/sensors/program/program.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"

"github.com/cilium/ebpf"
"github.com/cilium/ebpf/btf"
"github.com/cilium/tetragon/pkg/sensors/unloader"
)

Expand Down Expand Up @@ -109,6 +110,9 @@ type Program struct {
LC *LoadedCollection

RewriteConstants map[string]interface{}

// Type information used for CO-RE relocations.
KernelTypes *btf.Spec
}

func (p *Program) SetRetProbe(ret bool) *Program {
Expand Down
7 changes: 0 additions & 7 deletions pkg/sensors/tracing/generickprobe.go
Original file line number Diff line number Diff line change
Expand Up @@ -427,13 +427,6 @@ func preValidateKprobes(name string, kprobes []v1alpha1.KProbeSpec, lists []v1al
return err
}

if len(option.Config.KMods) > 0 {
btfobj, err = btf.AddModulesToSpec(btfobj, option.Config.KMods)
if err != nil {
return fmt.Errorf("adding modules to spec failed: %w", err)
}
}

// validate lists first
err = preValidateLists(lists)
if err != nil {
Expand Down
Loading