Skip to content

Commit

Permalink
Add features detection
Browse files Browse the repository at this point in the history
It's to prevent running --output-skb or --output-skb-shared-info on
kernel which does not support bpf_snprintf_btf() helper.

Meanwhile, avoid verifier roaring on Ubuntu 20.04:

; instruction poisoned by CO-RE
938: (85) call unknown#195896080
invalid func unknown#195896080
processed 519 insns (limit 1000000) max_states_per_insn 0 total_states 29 peak_states 29 mark_read 27

Signed-off-by: Leon Hwang <hffilwlqm@gmail.com>
  • Loading branch information
Asphaltt committed Nov 12, 2024
1 parent 690ce28 commit bba43d3
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ release
tags
kprobepwru_*
kprobemultipwru_*
featurespwru_*
!pwru/
26 changes: 26 additions & 0 deletions bpf/features.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
/* Copyright Leon Hwang */

#include "vmlinux.h"
#include "bpf/bpf_helpers.h"
#include "bpf/bpf_core_read.h"

struct pwru_features {
bool kprobe_happened;
bool has_snprintf_btf;
} features;

SEC("kprobe")
int kprobe__map_lookup_elem(struct pt_regs *ctx)
{
features.kprobe_happened = true;

/* Detect if bpf_snprintf_btf is available.
* Since: c4d0bfb45068 ("bpf: Add bpf_snprintf_btf helper")
*/
features.has_snprintf_btf = bpf_core_enum_value_exists(enum bpf_func_id, BPF_FUNC_snprintf_btf);

return BPF_OK;
}

char __license[] SEC("license") = "Dual BSD/GPL";
1 change: 1 addition & 0 deletions build.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
//go:generate sh -c "echo Generating for $TARGET_GOARCH"
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET_GOARCH -cc clang -no-strip KProbePWRU ./bpf/kprobe_pwru.c -- -I./bpf/headers -Wno-address-of-packed-member
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET_GOARCH -cc clang -no-strip KProbeMultiPWRU ./bpf/kprobe_pwru.c -- -DHAS_KPROBE_MULTI -I./bpf/headers -Wno-address-of-packed-member
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET_GOARCH -cc clang -no-strip FeaturesPWRU ./bpf/features.c -- -I./bpf/headers -Wno-address-of-packed-member

package main
58 changes: 58 additions & 0 deletions internal/pwru/features.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// SPDX-License-Identifier: Apache-2.0
/* Copyright Leon Hwang */

package pwru

import (
"log"

"github.com/cilium/ebpf"
"github.com/cilium/ebpf/btf"
"github.com/cilium/ebpf/link"
)

func DetectFeatures(spec *ebpf.CollectionSpec, btfSpec *btf.Spec, f *Flags) {
bssMap, err := ebpf.NewMap(spec.Maps[".bss"])
if err != nil {
log.Fatalf("Failed to create bss map: %v", err)
}
defer bssMap.Close()

coll, err := ebpf.NewCollectionWithOptions(spec, ebpf.CollectionOptions{
Programs: ebpf.ProgramOptions{
KernelTypes: btfSpec,
},
MapReplacements: map[string]*ebpf.Map{
".bss": bssMap,
},
})
if err != nil {
log.Fatalf("Failed to create collection: %v", err)
}
defer coll.Close()

kp, err := link.Kprobe("map_lookup_elem", coll.Programs["kprobe__map_lookup_elem"], nil)
if err != nil {
log.Fatalf("Failed to kprobe map_lookup_elem: %v", err)
}
defer kp.Close()

var features struct {
Happened uint8
HasSnprintfBtf uint8
}

// Trigger kprobe and retrieve features data
err = bssMap.Lookup(uint32(0), &features)
if err != nil {
log.Fatalf("Failed to lookup features data: %v", err)
}

if features.Happened == 0 {
log.Fatalf("Features detection was not triggered")
}

if (f.OutputSkb || f.OutputShinfo) && features.HasSnprintfBtf == 0 {
log.Fatalf("Unsupported to output skb or shinfo because bpf_snprintf_btf() is unavailable")
}
}
7 changes: 7 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@ func main() {
log.Fatalf("Failed to load BTF spec: %s", err)
}

featBpfSpec, err := LoadFeaturesPWRU()
if err != nil {
log.Fatalf("Failed to load features bpf spec: %v", err)
}

pwru.DetectFeatures(featBpfSpec, btfSpec, &flags)

if flags.AllKMods {
files, err := os.ReadDir("/sys/kernel/btf")
if err != nil {
Expand Down

0 comments on commit bba43d3

Please sign in to comment.