Skip to content

Commit

Permalink
tetragon: Add HasMissedStatsKprobe/Multi functions
Browse files Browse the repository at this point in the history
Signed-off-by: Jiri Olsa <[email protected]>
  • Loading branch information
olsajiri committed Jun 13, 2024
1 parent c80736a commit 23d15ac
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 9 deletions.
5 changes: 3 additions & 2 deletions cmd/tetragon/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,6 @@ func tetragonExecute() error {
}
defer pidfile.Delete()

log.Info("BPF detected features: ", bpf.LogFeatures())

if option.Config.ForceLargeProgs && option.Config.ForceSmallProgs {
log.Fatalf("Can't specify --force-small-progs and --force-large-progs together")
}
Expand Down Expand Up @@ -352,6 +350,9 @@ func tetragonExecute() error {
return err
}

// needs BTF, so caling it after InitCachedBTF
log.Info("BPF detected features: ", bpf.LogFeatures())

if err := observer.InitDataCache(option.Config.DataCacheSize); err != nil {
return err
}
Expand Down
126 changes: 119 additions & 7 deletions pkg/bpf/detect.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import (

"github.com/cilium/ebpf"
"github.com/cilium/ebpf/asm"
ebtf "github.com/cilium/ebpf/btf"
"github.com/cilium/ebpf/features"
"github.com/cilium/ebpf/link"
"github.com/cilium/tetragon/pkg/arch"
"github.com/cilium/tetragon/pkg/btf"
"github.com/cilium/tetragon/pkg/logger"
"golang.org/x/sys/unix"
)
Expand All @@ -27,11 +29,13 @@ type Feature struct {
}

var (
kprobeMulti Feature
uprobeMulti Feature
buildid Feature
modifyReturn Feature
modifyReturnSyscall Feature
kprobeMulti Feature
uprobeMulti Feature
buildid Feature
modifyReturn Feature
modifyReturnSyscall Feature
missedStatsKprobe Feature
missedStatsKprobeMulti Feature
)

func HasOverrideHelper() bool {
Expand Down Expand Up @@ -218,8 +222,116 @@ func HasProgramLargeSize() bool {
return features.HaveLargeInstructions() == nil
}

func detectMissedStats() (bool, bool) {
spec, err := btf.NewBTF()
if err != nil {
return false, false
}

// bpf_link_info
var linkInfo *ebtf.Struct
if err := spec.TypeByName("bpf_link_info", &linkInfo); err != nil {
return false, false
}

if len(linkInfo.Members) < 4 {
return false, false
}

// bpf_link_info::union
m := linkInfo.Members[3]
union, ok := m.Type.(*ebtf.Union)
if !ok {
return false, false
}

kprobe := false
kprobeMulti := false

hasField := func(st *ebtf.Struct, name string) bool {
for _, m := range st.Members {
if m.Name == name {
return true
}
}
return false
}

detectKprobeMulti := func(m ebtf.Member) bool {
// bpf_link_info::kprobe_multi
st, ok := m.Type.(*ebtf.Struct)
if !ok {
return false
}
// bpf_link_info::kprobe_multi::missed
return hasField(st, "missed")
}

detectKprobe := func(m ebtf.Member) bool {
// bpf_link_info::perf_event
st, ok := m.Type.(*ebtf.Struct)
if !ok {
return false
}

if len(st.Members) < 2 {
return false
}

// bpf_link_info::perf_event::union
tm := st.Members[1]
un, ok := tm.Type.(*ebtf.Union)
if !ok {
return false
}

for _, mu := range un.Members {
// bpf_link_info::perf_event::kprobe
if mu.Name == "kprobe" {
st2, ok := mu.Type.(*ebtf.Struct)
if !ok {
return false
}
// bpf_link_info::perf_event::kprobe::missed
return hasField(st2, "missed")
}
}
return false
}

for _, m := range union.Members {
if m.Name == "kprobe_multi" {
kprobeMulti = detectKprobeMulti(m)
} else if m.Name == "perf_event" {
kprobe = detectKprobe(m)
}
}

return kprobe, kprobeMulti
}

func detectMissedStatsOnce() {
missedStatsKprobe.init.Do(func() {
kprobe, kprobeMulti := detectMissedStats()
missedStatsKprobe.detected = kprobe
missedStatsKprobeMulti.detected = kprobeMulti
})
}

func HasMissedStatsPerfEvent() bool {
detectMissedStatsOnce()
return missedStatsKprobe.detected
}

func HasMissedStatsKprobeMulti() bool {
detectMissedStatsOnce()
return missedStatsKprobeMulti.detected
}

func LogFeatures() string {
return fmt.Sprintf("override_return: %t, buildid: %t, kprobe_multi: %t, uprobe_multi %t, fmodret: %t, fmodret_syscall: %t, signal: %t, large: %t",
HasMissedStatsPerfEvent()
return fmt.Sprintf("override_return: %t, buildid: %t, kprobe_multi: %t, uprobe_multi %t, fmodret: %t, fmodret_syscall: %t, signal: %t, large: %t, missed_stats_kprobe_multi: %t, missed_stats_kprobe: %t",
HasOverrideHelper(), HasBuildId(), HasKprobeMulti(), HasUprobeMulti(),
HasModifyReturn(), HasModifyReturnSyscall(), HasSignalHelper(), HasProgramLargeSize())
HasModifyReturn(), HasModifyReturnSyscall(), HasSignalHelper(), HasProgramLargeSize(),
HasMissedStatsKprobeMulti(), HasMissedStatsPerfEvent())
}

0 comments on commit 23d15ac

Please sign in to comment.