kfeatures

package module
v0.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 12, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

README

kfeatures

Go Reference CI Latest release Go version License

Can my eBPF tool actually run here, and if not, exactly what needs to change?

kfeatures is a pure-Go library that answers this question.

It probes kernel capabilities at runtime and returns actionable diagnostics: not just unsupported, but why and how to fix it.

if err := kfeatures.Check(kfeatures.FeatureBPFLSM, kfeatures.FeatureBTF); err != nil {
    var fe *kfeatures.FeatureError
    if errors.As(err, &fe) {
        log.Fatalf("%s - %s", fe.Feature, fe.Reason)
        // Output: BPF LSM - CONFIG_BPF_LSM=y but 'bpf' not in active LSM list; add lsm=...,bpf to kernel boot params
    }
}

The same answers are available from the CLI for CI/CD gating (semantic exit codes), and from --mcp mode for AI agents (JSON-RPC over stdio, every subcommand exposed as an MCP tool with a discoverable input schema). See CLI.

Why not cilium/ebpf/features or bpftool?

cilium/ebpf/features answers: "Does this kernel support program type X?"

bpftool feature probe answers: "What BPF features does this kernel have?" (CLI only, not embeddable in Go)

Neither tells you whether your tool can actually run. For example, BPF LSM requires three things simultaneously: CONFIG_BPF_LSM=y in the kernel config, bpf in the active LSM boot parameter list, and the LSM program type supported by the running kernel. cilium/ebpf/features can only check the last one. bpftool can check the first and last, but not the second. Neither provides remediation guidance.

Capability cilium/ebpf/features bpftool feature probe kfeatures
BPF program type probes
BPF map type / helper probes ✓ †
BTF availability (/sys/kernel/btf/vmlinux) ✗ *
Kernel config parsing (any CONFIG_*, =y/=m)
Active LSM list (/sys/kernel/security/lsm)
BPF LSM enabled (config + boot params + program type)
IMA detection (LSM list + securityfs directory)
IMA any measurement active (runtime measurement activity)
IMA runtime measurement count (raw count for before/after probes)
IMA exec measurement active (fresh-inode exec probe)
IMA file-check measurement active (fresh-inode file-open probe)
Process capabilities (CAP_BPF, CAP_SYS_ADMIN, CAP_PERFMON)
Unprivileged BPF status
Mount-state gates (bpffs/tracefs/custom paths via superblock magic)
ELF requirement extraction (parse .o, derive requirements)
Composite feature validation
Actionable diagnostics (remediation steps)
Selective probing (minimize overhead) ✓ ‡ ✗ §
Pure Go, no CGO
Usable as a Go library

* bpftool checks CONFIG_DEBUG_INFO_BTF in the kernel config but does not verify /sys/kernel/btf/vmlinux exists. † Exposed in kfeatures as parameterized requirements (RequireMapType, RequireProgramHelper) consumed by Check(...). cilium/ebpf/features is per-function: callers invoke individual probe functions on demand. § bpftool feature probe runs the full probe set on every invocation.

Other Go projects (libbpfgo, Tetragon, Falco libs) have some feature detection built in, but none is a standalone reusable library. They are either CGO-dependent, tightly coupled to their parent project, or written in C/C++.

Installation

Library:

go get github.com/leodido/kfeatures

CLI binary (Linux amd64 / arm64):

# Replace VERSION (e.g. 0.5.1) and ARCH (amd64 or arm64).
curl -sSLO "https://github.com/leodido/kfeatures/releases/download/v${VERSION}/kfeatures_${VERSION}_linux_${ARCH}.tar.gz"
tar xzf "kfeatures_${VERSION}_linux_${ARCH}.tar.gz"
./kfeatures version

For supply-chain verification of the binary before extracting, see Verifying releases below.

Usage

Quick check

Validate that required kernel features are available:

import (
    "errors"
    "log"

    "github.com/leodido/kfeatures"
)

if err := kfeatures.Check(kfeatures.FeatureBPFLSM, kfeatures.FeatureBTF); err != nil {
    var fe *kfeatures.FeatureError
    if errors.As(err, &fe) {
        log.Fatalf("kernel not ready: %s - %s", fe.Feature, fe.Reason)
    }
}
Mixed requirements

Combine Feature enums with parameterized workload requirements:

import (
    "github.com/cilium/ebpf"
    "github.com/cilium/ebpf/asm"
    "github.com/leodido/kfeatures"
)

err := kfeatures.Check(
    kfeatures.FeatureBTF,
    kfeatures.RequireProgramType(ebpf.XDP),
    kfeatures.RequireMapType(ebpf.Hash),
    kfeatures.RequireProgramHelper(ebpf.XDP, asm.FnMapLookupElem),
)
Custom mount paths (RequireMount)

Gate on a filesystem mounted at an arbitrary path with the expected superblock magic. Useful when bpffs lives somewhere other than /sys/fs/bpf:

import (
    "github.com/leodido/kfeatures"
    "golang.org/x/sys/unix"
)

err := kfeatures.Check(
    kfeatures.RequireMount("/run/bpf", unix.BPF_FS_MAGIC),
)

Magic constants come from golang.org/x/sys/unix (e.g. unix.BPF_FS_MAGIC, unix.TRACEFS_MAGIC, unix.CGROUP2_SUPER_MAGIC).

Reusable presets (FeatureGroup)

FeatureGroup packages a set of requirements as a single value you can pass anywhere a Requirement is accepted:

var TracingTool = kfeatures.FeatureGroup{
    kfeatures.FeatureBTF,
    kfeatures.FeatureKprobeMulti,
    kfeatures.RequireProgramType(ebpf.Kprobe),
}

if err := kfeatures.Check(TracingTool); err != nil {
    log.Fatal(err)
}
Extract requirements from a compiled object (FromELF)

Point FromELF at an eBPF .o and get back a FeatureGroup describing its program types, map types, and helper-per-program requirements (directly consumable by Check):

reqs, err := kfeatures.FromELF("./bpf/probe.o")
if err != nil {
    log.Fatal(err)
}
if err := kfeatures.Check(reqs); err != nil {
    log.Fatalf("kernel cannot run probe.o: %v", err)
}

Output is deterministic (deduplicated, stably ordered). Unknown ELF kinds fail closed.

Render remediation (Diagnose)

Check returns the diagnosis for the first failing feature. To inspect any feature against a single probe snapshot, call Diagnose directly:

sf, _ := kfeatures.Probe()
if !sf.BPFLSMEnabled.Supported {
    fmt.Println(sf.Diagnose(kfeatures.FeatureBPFLSM))
    // CONFIG_BPF_LSM=y but 'bpf' not in active LSM list; add lsm=...,bpf to kernel boot params
}
Full probe

Probe all features for diagnostics and reporting:

sf, err := kfeatures.Probe()
if err != nil {
    log.Fatal(err)
}
fmt.Println(sf)

Sample output (truncated):

Kernel: 6.1.0-generic

Program Types:
  LSM: yes
  kprobe: yes
  kprobe.multi: yes

Core:
  BTF: yes

Security Subsystems:
  BPF LSM enabled: yes
  IMA enabled: no
  IMA directory: yes
  IMA any measurement active: no
  Active LSMs: lockdown, capability, yama, apparmor, bpf

Filesystems:
  tracefs: yes
  bpffs: yes

Individual fields are typed and inspectable programmatically (see SystemFeatures).

Selective probing

Probe only what you need:

sf, err := kfeatures.ProbeWith(
    kfeatures.WithProgramTypes(ebpf.LSM, ebpf.Kprobe),
    kfeatures.WithSecuritySubsystems(),
    kfeatures.WithCapabilities(),
)

WithX options select probe scope. They do not define requirements; use Check(...) for gating.

CLI

A CLI is included for operator diagnostics, CI/CD gating, and AI-agent integration:

go install github.com/leodido/kfeatures/cmd/kfeatures@latest
kfeatures probe                                    # probe all features
kfeatures check --require bpf-lsm,btf,cap-bpf      # exit 0 if met, 1 otherwise
kfeatures probe --json                             # JSON output
kfeatures config                                   # display kernel config
CI/CD gating (semantic exit codes)

kfeatures check exits 0 when all requirements are met and 1 when any are missing. Drop it into a Helm chart pre-install hook, an init container, or a CI job. With --json the verdict is a parse-friendly object on stdout:

$ kfeatures check --require bpf-lsm,btf --json
{
  "ok": false,
  "feature": "bpf-lsm",
  "reason": "CONFIG_BPF_LSM=y but 'bpf' not in active LSM list; add lsm=...,bpf to kernel boot params"
}
$ echo $?
1

Invocation errors (missing required flag, unknown flag, invalid value, unknown subcommand) emit a structured JSON envelope on stderr and exit with a semantic code so wrappers can distinguish "the user invoked us wrong" from "the kernel is missing a feature":

Exit code Category Example
0 OK check passed
1 Runtime FeatureError, probe failure, missing kernel config
10 Input missing_required_flag: required flag not provided
11 Input invalid_flag_value: wrong type or unknown enum
12 Input unknown_flag
14 Input unknown_command
$ kfeatures check --require bogus
{"error":"invalid_flag_value","exit_code":11,"flag":"require","got":"bogus","expected":"feature","command":"kfeatures check","message":"invalid argument \"bogus\" for \"-r, --require\" flag: unknown feature: \"bogus\" (available: …)"}
$ echo $?
11

Codes follow the structcli/exitcode categories: input errors 1019 are agent-fixable, runtime errors 19 are operator-fixable.

AI agents (--jsonschema, --mcp)

kfeatures is built to be driven by LLM agents and code-generation tooling without --help scraping.

--jsonschema dumps a JSON Schema describing a command's flags. Use =tree to walk the entire subtree:

$ kfeatures check --jsonschema | jq '.title, .properties | keys'
"kfeatures check"
[
  "json",
  "require"
]

$ kfeatures --jsonschema=tree | jq 'map(.title) | map(select(test("^kfeatures( probe| check| config| version)?$")))'
[
  "kfeatures",
  "kfeatures check",
  "kfeatures config",
  "kfeatures probe",
  "kfeatures version"
]

(--jsonschema=tree walks every node, including cobra-generated help and completion leaves; filter with jq to the ones you care about.)

--mcp turns kfeatures into a Model Context Protocol server over stdio. Each runnable leaf command becomes an MCP tool whose input schema mirrors the cobra flag set; agents introspect via tools/list and invoke via tools/call:

// Claude Desktop / any MCP-aware client config
{
  "mcpServers": {
    "kfeatures": {
      "command": "kfeatures",
      "args": ["--mcp"]
    }
  }
}

Tools exposed: probe, check, config. The server stays alive across business-outcome errors (a failing check does not terminate the session), and invocation errors flow through the same structured envelope as the CLI. Pure stdlib JSON-RPC inside structcli; no extra heavy SDK dependency.

What it detects

Category Features
Program types LSM, kprobe, kprobe.multi, tracepoint, fentry
Core BTF availability (CO-RE)
Security BPF LSM enabled, IMA enabled, IMA any measurement active, IMA exec measurement active, IMA file-check measurement active, active LSM list
Capabilities and runtime gates CAP_BPF, CAP_SYS_ADMIN, CAP_PERFMON, unprivileged BPF disabled, BPF stats enabled
Syscalls bpf(), perf_event_open()
JIT enabled, hardened, kallsyms, memory limit, CONFIG_BPF_JIT_ALWAYS_ON
Filesystems tracefs, debugfs, securityfs, bpffs (gated tracefs/bpffs checks verify the filesystem is mounted with the expected superblock magic)
Custom mount gates any path + superblock magic via RequireMount
Namespaces initial user namespace, initial PID namespace
Parameterized workload requirements program type, map type, helper-per-program-type via requirement items
ELF-derived requirements program/map types and helper-per-program requirements via FromELF
Mitigation context Spectre v1/v2 vulnerability status
Kernel config CONFIG_BPF_LSM, CONFIG_IMA, CONFIG_DEBUG_INFO_BTF, CONFIG_FPROBE, any CONFIG_*

Stability

Pre-1.0. The public API may change between minor versions; breaking changes are called out explicitly in CHANGELOG.md. The FromELF contract (signature, determinism, fail-closed semantics) is frozen; see CONTRIBUTING.md.

Requirements

  • Linux for runtime probing/checking (uses Linux-specific syscalls and sysfs).
  • FromELF is parser-only and works on any platform.
  • Some probes require CAP_BPF or CAP_SYS_ADMIN.

Verifying releases

Every release artifact (each platform tarball and the checksums.txt) is signed with cosign keyless signing backed by GitHub's OIDC token. Each artifact has a sibling <artifact>.sigstore.json bundle containing the signature, the signing certificate (with the workflow identity baked in), and the Rekor transparency-log inclusion proof.

To verify before extracting (replace VERSION and ARCH):

curl -sSLO "https://github.com/leodido/kfeatures/releases/download/v${VERSION}/kfeatures_${VERSION}_linux_${ARCH}.tar.gz"
curl -sSLO "https://github.com/leodido/kfeatures/releases/download/v${VERSION}/kfeatures_${VERSION}_linux_${ARCH}.tar.gz.sigstore.json"

cosign verify-blob \
  --bundle "kfeatures_${VERSION}_linux_${ARCH}.tar.gz.sigstore.json" \
  --certificate-identity "https://github.com/leodido/kfeatures/.github/workflows/release.yaml@refs/tags/v${VERSION}" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  "kfeatures_${VERSION}_linux_${ARCH}.tar.gz"

A successful verification proves that the artifact was produced by the release.yaml workflow at the tagged revision, signed by GitHub's OIDC issuer, and is recorded on the public Rekor transparency log. Requires cosign v2.0+.

Contributing

See CONTRIBUTING.md for the API model, the feature-addition checklist, and the development workflow.

License

Apache License 2.0. Project attribution in NOTICE, per Apache 2.0 §4(d).

Why Apache 2.0

kfeatures is pure-Go userspace. No kernel source embedded, no cgo, no GPL/LGPL deps. Kernel interaction is uABI only: reads from /proc and /sys, syscalls and constants via golang.org/x/sys/unix (BSD-3-Clause), ELF parsing via github.com/cilium/ebpf (MIT; never calls BPF_PROG_LOAD). The kernel's COPYING carves "user programs that use kernel services by normal system calls" out of GPL: the carve-out ps, ls, and mount rely on.

Apache 2.0 over MIT:

  • Patent grant (§3). Probing eBPF, LSM, IMA, namespaces, and Spectre mitigations is patent-adjacent. Apache 2.0 grants an irrevocable patent license with defensive termination. MIT has none.
  • Adopter alignment. Cilium, Tetragon, Tracee, Falco, Pixie, and Inspektor Gadget are Apache 2.0. No compatibility review needed.

Documentation

Overview

Package kfeatures provides kernel feature detection for eBPF programs.

This package probes kernel capabilities at runtime, enabling early failure with clear, actionable error messages when requirements aren't met. It complements github.com/cilium/ebpf/features by adding BTF availability detection, security subsystem probing (LSM, IMA), kernel config parsing, capability checking, and composite feature validation with operator-facing diagnostics.

API Model

kfeatures intentionally exposes two API families:

Keep these families separate:

  • model stable boolean gates as Feature
  • model parameterized gates as Requirement item types
  • keep context-only/descriptive signals probe-only unless a concrete deterministic gating policy is defined.

FromELF API contract (frozen):

  • FromELF returns FeatureGroup requirement items consumable by Check
  • output is deterministic (deduplicated, stable order)
  • extraction scope includes program/map types and helper-per-program requirements
  • unknown/unsupported ELF kinds fail closed with an error

Quick Check

Validate that required kernel features are available:

if err := kfeatures.Check(kfeatures.FeatureBPFLSM, kfeatures.FeatureBTF); err != nil {
    var fe *kfeatures.FeatureError
    if errors.As(err, &fe) {
        log.Fatalf("kernel not ready: %s - %s", fe.Feature, fe.Reason)
    }
    log.Fatal(err)
}

Full Probe

Probe all features for diagnostics:

sf, err := kfeatures.Probe()
if err != nil {
    log.Fatal(err)
}
fmt.Printf("BPF LSM program type: %v\n", sf.LSMProgramType.Supported)
fmt.Printf("BPF LSM enabled: %v\n", sf.BPFLSMEnabled.Supported)
fmt.Printf("BTF available: %v\n", sf.BTF.Supported)
fmt.Printf("Kernel: %s\n", sf.KernelVersion)
fmt.Println(sf) // human-readable summary

Selective Probing

Probe only specific features to minimize overhead:

sf, err := kfeatures.ProbeWith(
    kfeatures.WithProgramTypes(ebpf.LSM, ebpf.Kprobe),
    kfeatures.WithSecuritySubsystems(),
    kfeatures.WithCapabilities(),
)

Types

ProbeResult represents the outcome of probing a single feature:

  • Supported: true if the feature is available
  • Error: non-nil if the probe itself failed (not just unsupported)

SystemFeatures aggregates all probe results into a single struct.

KernelConfig holds parsed kernel configuration values with support for distinguishing between =m (module) and =y (built-in) settings.

Feature represents a kernel capability that can be checked via Check.

FeatureError provides actionable diagnostics when a required feature is unavailable, including the feature name, a human-readable reason with remediation steps, and the underlying probe error if any.

Index

Constants

This section is empty.

Variables

View Source
var ErrInvalidFeature = fmt.Errorf("not a valid Feature, try [%s]", strings.Join(_FeatureNames, ", "))
View Source
var ErrNoKernelConfig = errors.New("no kernel config found")

ErrNoKernelConfig is returned when no kernel config source is available.

View Source
var ErrUnsupportedPlatform = errors.New("probing requires Linux")

ErrUnsupportedPlatform is returned by all probe and check functions on non-Linux platforms where kernel feature detection is not possible.

Functions

func Check

func Check(required ...Requirement) error

Check validates the specified requirements and returns a *FeatureError for the first unsatisfied requirement, or nil if all are met.

Accepted requirement kinds:

Check is the only gate entrypoint. Keep ProbeWith/WithX for diagnostics-only data collection, not for expressing required readiness conditions. Kernel config is always probed to provide actionable diagnostics.

func FeatureNames

func FeatureNames() []string

FeatureNames returns a list of possible string values of Feature.

func ReadIMARuntimeMeasurementsCount

func ReadIMARuntimeMeasurementsCount() (int, error)

ReadIMARuntimeMeasurementsCount returns the current IMA runtime measurement count from /sys/kernel/security/ima/runtime_measurements_count. No side effects. Useful for diagnostics and for callers building before/after probes.

func ResetCache

func ResetCache()

ResetCache clears cached probe results, forcing the next Probe call to re-probe. This is primarily useful for testing.

Types

type ConfigValue

type ConfigValue int

ConfigValue represents a kernel configuration option's state.

const (
	// ConfigNotSet means the option is not set or not found.
	ConfigNotSet ConfigValue = iota
	// ConfigModule means the option is set to =m (module).
	ConfigModule
	// ConfigBuiltin means the option is set to =y (built-in).
	ConfigBuiltin
)

func (ConfigValue) IsBuiltin

func (v ConfigValue) IsBuiltin() bool

IsBuiltin returns true if the config option is built-in (=y).

func (ConfigValue) IsEnabled

func (v ConfigValue) IsEnabled() bool

IsEnabled returns true if the config option is set (either =m or =y).

func (ConfigValue) String

func (v ConfigValue) String() string

type Feature

type Feature int

Feature represents a kernel capability that can be checked via Check.

ENUM( bpf-lsm btf ima kprobe kprobe-multi fentry tracepoint cap-bpf cap-sys-admin cap-perfmon jit-enabled jit-hardened bpf-syscall perf-event-open sleepable-bpf trace-fs bpf-fs init-user-ns unprivileged-bpf-disabled bpf-stats-enabled ima-any-measurement-active )

const (
	// FeatureBPFLSM is a Feature of type Bpf-Lsm.
	FeatureBPFLSM Feature = iota
	// FeatureBTF is a Feature of type Btf.
	FeatureBTF
	// FeatureIMA is a Feature of type Ima.
	FeatureIMA
	// FeatureKprobe is a Feature of type Kprobe.
	FeatureKprobe
	// FeatureKprobeMulti is a Feature of type Kprobe-Multi.
	FeatureKprobeMulti
	// FeatureFentry is a Feature of type Fentry.
	FeatureFentry
	// FeatureTracepoint is a Feature of type Tracepoint.
	FeatureTracepoint
	// FeatureCapBPF is a Feature of type Cap-Bpf.
	FeatureCapBPF
	// FeatureCapSysAdmin is a Feature of type Cap-Sys-Admin.
	FeatureCapSysAdmin
	// FeatureCapPerfmon is a Feature of type Cap-Perfmon.
	FeatureCapPerfmon
	// FeatureJITEnabled is a Feature of type Jit-Enabled.
	FeatureJITEnabled
	// FeatureJITHardened is a Feature of type Jit-Hardened.
	FeatureJITHardened
	// FeatureBPFSyscall is a Feature of type Bpf-Syscall.
	FeatureBPFSyscall
	// FeaturePerfEventOpen is a Feature of type Perf-Event-Open.
	FeaturePerfEventOpen
	// FeatureSleepableBPF is a Feature of type Sleepable-Bpf.
	FeatureSleepableBPF
	// FeatureTraceFS is a Feature of type Trace-Fs.
	FeatureTraceFS
	// FeatureBPFFS is a Feature of type Bpf-Fs.
	FeatureBPFFS
	// FeatureInitUserNS is a Feature of type Init-User-Ns.
	FeatureInitUserNS
	// FeatureUnprivilegedBPFDisabled is a Feature of type Unprivileged-Bpf-Disabled.
	FeatureUnprivilegedBPFDisabled
	// FeatureBPFStatsEnabled is a Feature of type Bpf-Stats-Enabled.
	FeatureBPFStatsEnabled
	// FeatureIMAAnyMeasurementActive is a Feature of type Ima-Any-Measurement-Active.
	FeatureIMAAnyMeasurementActive
)

func FeatureValues

func FeatureValues() []Feature

FeatureValues returns a list of the values for Feature

func ParseFeature

func ParseFeature(name string) (Feature, error)

ParseFeature attempts to convert a string to a Feature.

func (*Feature) AppendText

func (x *Feature) AppendText(b []byte) ([]byte, error)

AppendText appends the textual representation of itself to the end of b (allocating a larger slice if necessary) and returns the updated slice.

Implementations must not retain b, nor mutate any bytes within b[:len(b)].

func (Feature) IsValid

func (x Feature) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (Feature) MarshalText

func (x Feature) MarshalText() ([]byte, error)

MarshalText implements the text marshaller method.

func (Feature) String

func (x Feature) String() string

String implements the Stringer interface.

func (*Feature) UnmarshalText

func (x *Feature) UnmarshalText(text []byte) error

UnmarshalText implements the text unmarshaller method.

type FeatureError

type FeatureError struct {
	Feature string
	Reason  string
	Err     error
}

FeatureError represents an error when a required kernel feature is unavailable.

func (*FeatureError) Error

func (e *FeatureError) Error() string

func (*FeatureError) Unwrap

func (e *FeatureError) Unwrap() error

type FeatureGroup

type FeatureGroup []Requirement

FeatureGroup is a reusable set of Requirement items.

Groups can include simple Feature values and parameterized requirements. It is a preset container, not a separate gate API family.

func FromELF

func FromELF(path string) (FeatureGroup, error)

FromELF derives workload requirements from an eBPF ELF object file.

Contract:

  • Signature: FromELF(path string) (FeatureGroup, error)
  • Determinism: output is deduplicated and stably ordered
  • Scope: extract program/map requirements and helper-per-program requirements
  • Unknown handling: fail closed (return error for unsupported/unknown kinds)

Returned requirements are directly consumable by Check.

type KernelConfig

type KernelConfig struct {

	// Convenience fields for common checks (populated from raw).
	BPFLSM      ConfigValue // CONFIG_BPF_LSM
	IMA         ConfigValue // CONFIG_IMA
	BTF         ConfigValue // CONFIG_DEBUG_INFO_BTF
	KprobeMulti ConfigValue // CONFIG_FPROBE (required for kprobe.multi)
	JITAlwaysOn ConfigValue // CONFIG_BPF_JIT_ALWAYS_ON
	Preempt     PreemptMode // Derived from CONFIG_PREEMPT_*
	// contains filtered or unexported fields
}

KernelConfig holds parsed kernel configuration values.

func NewKernelConfig

func NewKernelConfig(raw map[string]ConfigValue) *KernelConfig

NewKernelConfig creates a KernelConfig from a raw config map. The map is copied to ensure immutability after construction.

func (*KernelConfig) Get

func (kc *KernelConfig) Get(key string) ConfigValue

Get returns the ConfigValue for a kernel config key. The key should not include the CONFIG_ prefix.

func (*KernelConfig) IsSet

func (kc *KernelConfig) IsSet(key string) bool

IsSet returns true if the config option is enabled (=m or =y).

type MapTypeRequirement

type MapTypeRequirement struct {
	Type ebpf.MapType
}

MapTypeRequirement requires support for a specific eBPF map type.

func RequireMapType

func RequireMapType(mt ebpf.MapType) MapTypeRequirement

RequireMapType creates a requirement for a map type.

type MountRequirement

type MountRequirement struct {
	Path  string
	Magic uint32
}

MountRequirement requires that Path is mounted with a filesystem whose superblock magic equals Magic. Magic is the raw f_type value the kernel reports via Statfs (e.g. golang.org/x/sys/unix.BPF_FS_MAGIC for bpffs).

Use this when FeatureBPFFS / FeatureTraceFS are too restrictive: for example, bpffs mounted at a non-default path, or any other pseudo-FS the caller depends on (cgroupv2, debugfs, securityfs, tmpfs in tests, ...).

func RequireMount

func RequireMount(path string, magic uint32) MountRequirement

RequireMount creates a requirement that path is mounted with a filesystem whose superblock magic equals magic.

Magic numbers live in golang.org/x/sys/unix (e.g. unix.BPF_FS_MAGIC, unix.TRACEFS_MAGIC, unix.CGROUP2_SUPER_MAGIC). Pass the raw value.

Panics if path is empty or magic is zero. Both indicate API misuse: an empty path cannot be statfs'd, and a zero magic does not correspond to any known filesystem and would silently mismatch every real mount.

type PreemptMode

type PreemptMode int

PreemptMode represents the kernel preemption model.

const (
	// PreemptUnknown means the preemption model could not be determined.
	PreemptUnknown PreemptMode = iota
	// PreemptNone means no forced preemption (server workloads).
	PreemptNone
	// PreemptVoluntary means voluntary preemption (desktop default).
	PreemptVoluntary
	// PreemptFull means full preemption (low-latency).
	PreemptFull
	// PreemptDynamic means runtime-switchable preemption (kernel 5.12+).
	PreemptDynamic
)

func (PreemptMode) String

func (m PreemptMode) String() string

func (PreemptMode) SupportsSleepable

func (m PreemptMode) SupportsSleepable() bool

SupportsSleepable reports whether the preemption model supports sleepable BPF programs (BPF_F_SLEEPABLE). Requires full preemption or dynamic preemption.

type ProbeOption

type ProbeOption func(*probeConfig)

ProbeOption configures what ProbeWith collects for diagnostics/reporting. Probe options are not readiness requirements and are intentionally separate from Requirement values consumed by Check.

func WithAll

func WithAll() ProbeOption

WithAll enables probing of all features.

func WithCapabilities

func WithCapabilities() ProbeOption

WithCapabilities probes process capabilities (CAP_BPF, CAP_SYS_ADMIN, CAP_PERFMON), unprivileged BPF access status, and BPF runtime stats status.

func WithFilesystems

func WithFilesystems() ProbeOption

WithFilesystems probes filesystem mounts relevant to BPF operations (tracefs, debugfs, securityfs, bpffs).

func WithJIT

func WithJIT() ProbeOption

WithJIT probes BPF JIT compiler status (enabled, hardening, kallsyms, memory limit).

func WithKernelConfig

func WithKernelConfig() ProbeOption

WithKernelConfig parses and includes kernel configuration.

func WithLSMPath

func WithLSMPath(path string) ProbeOption

WithLSMPath sets a custom path for the LSM file. This is primarily for testing; production code uses the default /sys/kernel/security/lsm.

func WithMitigations

func WithMitigations() ProbeOption

WithMitigations probes CPU vulnerability mitigations that affect BPF JIT codegen and reads CONFIG_BPF_JIT_ALWAYS_ON from kernel config.

func WithNamespaces

func WithNamespaces() ProbeOption

WithNamespaces probes namespace context (user namespace, PID namespace).

func WithProgramTypes

func WithProgramTypes(types ...ebpf.ProgramType) ProbeOption

WithProgramTypes probes the specified eBPF program types.

func WithSecuritySubsystems

func WithSecuritySubsystems() ProbeOption

WithSecuritySubsystems probes security subsystem status (LSM list, IMA).

func WithSyscalls

func WithSyscalls() ProbeOption

WithSyscalls probes availability of BPF-relevant syscalls (bpf(), perf_event_open).

type ProbeResult

type ProbeResult struct {
	// Supported indicates whether the feature is available.
	Supported bool
	// Error is non-nil if the probe itself failed (not just unsupported).
	Error error
}

ProbeResult represents the outcome of a kernel feature probe.

func ProbeIMAAnyMeasurementActive

func ProbeIMAAnyMeasurementActive() ProbeResult

ProbeIMAAnyMeasurementActive checks whether at least one IMA measurement rule has fired. It does not identify which func= rule caused the measurement. Exported so consumers can call it directly without going through Check.

func ProbeIMAExecMeasurementActive

func ProbeIMAExecMeasurementActive() ProbeResult

ProbeIMAExecMeasurementActive checks whether an IMA measurement rule covering exec (e.g., func=BPRM_CHECK) is active by executing a fresh temporary binary and checking for a measurement count increase.

Unlike ProbeIMAAnyMeasurementActive, this probe does not use a count > 1 shortcut. It returns Supported=true only when the controlled exec stimulus increments the IMA measurement count.

func ProbeIMAFileCheckMeasurementActive

func ProbeIMAFileCheckMeasurementActive() ProbeResult

ProbeIMAFileCheckMeasurementActive checks whether an IMA measurement rule covering file open (e.g., func=FILE_CHECK) is active by opening a fresh temporary file and checking for a measurement count increase.

Unlike ProbeIMAAnyMeasurementActive, this probe does not use a count > 1 shortcut. It returns Supported=true only when the controlled file-open stimulus increments the IMA measurement count.

type ProgramHelperRequirement

type ProgramHelperRequirement struct {
	ProgramType ebpf.ProgramType
	Helper      asm.BuiltinFunc
}

ProgramHelperRequirement requires that a helper is supported for a program type.

func RequireProgramHelper

func RequireProgramHelper(pt ebpf.ProgramType, helper asm.BuiltinFunc) ProgramHelperRequirement

RequireProgramHelper creates a requirement for a helper/program-type pair.

type ProgramTypeRequirement

type ProgramTypeRequirement struct {
	Type ebpf.ProgramType
}

ProgramTypeRequirement requires support for a specific eBPF program type.

func RequireProgramType

func RequireProgramType(pt ebpf.ProgramType) ProgramTypeRequirement

RequireProgramType creates a requirement for a program type.

type Requirement

type Requirement interface {
	// contains filtered or unexported methods
}

Requirement describes a pass/fail gate condition consumable by Check.

API boundary:

  • Requirement values define what must pass.
  • ProbeOption/WithX values define what ProbeWith should collect.
  • Do not model probe-scope selection as requirements.

Built-in implementations include:

type SystemFeatures

type SystemFeatures struct {
	// Syscall availability
	// BPFSyscall: Supported=true means the bpf() syscall is available.
	BPFSyscall ProbeResult
	// PerfEventOpen: Supported=true means the perf_event_open() syscall is available.
	// Required for kprobe/tracepoint/uprobe attachment.
	PerfEventOpen ProbeResult

	// Program types (runtime probes via cilium/ebpf)
	LSMProgramType ProbeResult
	Kprobe         ProbeResult
	KprobeMulti    ProbeResult
	Tracepoint     ProbeResult
	Fentry         ProbeResult

	// BTF (BPF Type Format) for CO-RE programs
	BTF ProbeResult

	// Security subsystems (sysfs checks)
	// These use ProbeResult because reading /sys/kernel/security/lsm can fail
	// (permissions, securityfs not mounted, etc.)
	BPFLSMEnabled ProbeResult
	ActiveLSMs    []string

	// IMA detection (multiple signals for diagnostics)
	// IMAEnabled is the authoritative signal: true only if "ima" is in the LSM list.
	// This is required for bpf_ima_file_hash to work.
	IMAEnabled ProbeResult
	// IMADirectory indicates /sys/kernel/security/ima exists.
	// IMA securityfs is mounted, but IMA may not be actively measuring files.
	IMADirectory ProbeResult
	// IMAAnyMeasurementActive indicates at least one IMA measurement rule
	// has fired. It does not identify which func= rule caused the measurement.
	// Checked by reading the runtime measurement count and, if needed,
	// executing /bin/true to trigger a potential BPRM_CHECK rule.
	// When active, IMA caches file hashes in the inode security blob.
	IMAAnyMeasurementActive ProbeResult

	// Process capabilities relevant to BPF operations
	HasCapBPF      ProbeResult // CAP_BPF (kernel 5.8+)
	HasCapSysAdmin ProbeResult // CAP_SYS_ADMIN (fallback for pre-5.8 kernels)
	HasCapPerfmon  ProbeResult // CAP_PERFMON (perf events, tracepoints)

	// Unprivileged BPF access
	// Supported=true means unprivileged BPF is disabled (the common/secure default).
	UnprivilegedBPFDisabled ProbeResult

	// Filesystem mounts relevant to BPF operations
	// TraceFS: required for kprobe/tracepoint attachment via ftrace.
	TraceFS ProbeResult
	// DebugFS: legacy mount point, fallback for tracefs on older kernels.
	DebugFS ProbeResult
	// SecurityFS: required for reading LSM state (/sys/kernel/security/*).
	SecurityFS ProbeResult
	// BPFFS: required for pinning BPF maps and programs (/sys/fs/bpf).
	BPFFS ProbeResult

	// JIT compiler status (sysctl values)
	// JITEnabled: Supported=true means BPF JIT compiler is enabled.
	// Values: 0=disabled, 1=enabled, 2=enabled+debug (emit to kernel log).
	JITEnabled ProbeResult
	// JITHardened: Supported=true means BPF JIT hardening is active.
	// Values: 0=disabled, 1=enabled for unprivileged, 2=enabled for all.
	JITHardened ProbeResult
	// JITKallsyms: Supported=true means JIT-compiled BPF programs are exposed in /proc/kallsyms.
	JITKallsyms ProbeResult
	// JITLimit: the memory limit in bytes for JIT-compiled BPF programs (0 if unavailable).
	JITLimit int64

	// JIT always-on mode (derived from kernel config).
	// When CONFIG_BPF_JIT_ALWAYS_ON=y, the BPF interpreter is disabled and
	// all programs must be JIT-compiled. Forced by some Spectre mitigation policies.
	JITAlwaysOn ConfigValue

	// CPU vulnerability mitigations.
	// Each field contains the raw mitigation string from /sys/devices/system/cpu/vulnerabilities/
	// or empty if the file doesn't exist. Values like "Mitigation: ..." mean active protection.
	SpectreV1 string // spectre_v1
	SpectreV2 string // spectre_v2

	// Kernel preemption model (derived from kernel config).
	// Affects sleepable BPF programs (BPF_F_SLEEPABLE).
	PreemptMode PreemptMode

	// Namespace awareness.
	// InInitUserNS: Supported=true means the process runs in the initial user namespace.
	// BPF is often restricted in non-initial user namespaces.
	InInitUserNS ProbeResult
	// InInitPIDNS: Supported=true means the process runs in the initial PID namespace.
	// bpf_get_current_pid_tgid() returns the PID in the current PID namespace, which
	// differs from the host PID when running in a nested PID namespace.
	InInitPIDNS ProbeResult

	// BPF runtime statistics
	// BPFStatsEnabled: Supported=true means /proc/sys/kernel/bpf_stats_enabled is non-zero.
	// When enabled, the kernel collects per-program runtime stats (run count, run time).
	// Useful for verifier profiling and performance debugging.
	BPFStatsEnabled ProbeResult

	// Kernel config (optional, may be nil if not probed)
	KernelConfig *KernelConfig

	// Metadata
	KernelVersion string
}

SystemFeatures holds the results of all kernel feature probes.

func Probe

func Probe() (*SystemFeatures, error)

Probe probes all kernel features and caches the result. Subsequent calls return the cached result without re-probing. Use ProbeNoCache if you need fresh results.

func ProbeNoCache

func ProbeNoCache() (*SystemFeatures, error)

ProbeNoCache probes all kernel features without using the cache. Use this when you need fresh results, e.g., after loading kernel modules.

func ProbeWith

func ProbeWith(opts ...ProbeOption) (*SystemFeatures, error)

ProbeWith probes kernel features based on the provided options. BTF and kernel version are always probed regardless of options (both are cheap). If no options are provided, only BTF and kernel version are populated.

func (*SystemFeatures) Diagnose

func (sf *SystemFeatures) Diagnose(f Feature) string

Diagnose returns an enriched reason string explaining why a feature is not supported and what the operator can do to fix it.

func (*SystemFeatures) Result

func (sf *SystemFeatures) Result(f Feature) (ProbeResult, bool)

Result maps a Feature to its corresponding ProbeResult in SystemFeatures. Returns false as the second value if the feature is unknown.

func (*SystemFeatures) String

func (sf *SystemFeatures) String() string

String returns a human-readable summary of all probe results.

Directories

Path Synopsis
cmd
kfeatures command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL