Inspect eBPF Objects Safely with bpftool
You will finish with a small, repeatable workflow for identifying the installed bpftool build, listing active eBPF programs and maps, inspecting one object as JSON, and checking which BPF features the running kernel exposes. The local command comes from linux-tools-common version 6.8.0-139.139, while the matching kernel-specific executable is not installed on this machine. That distinction matters: a package can provide the manual and wrapper while the command still warns that tools for the current kernel are missing.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about fifteen minutes. You need a shell and a readable terminal. The first checks are ordinary, unprivileged commands. Some information is hidden from unprivileged users, and commands that load, attach, pin, update or delete BPF objects can change kernel state. This guide keeps those operations out of the copy-and-paste path.
1. Check the installed command and its version
Start by checking the executable that your shell resolves, then ask for its version:
$ command -v bpftool
/usr/sbin/bpftool
$ bpftool version
WARNING: bpftool not found for kernel 6.8.0-139
...
The exact warning depends on the running kernel and installed packages. On this machine, the command warns that linux-tools-6.8.0-139-generic and related cloud tools may be needed. Do not treat a warning as a successful feature probe. Check the exit status and save the complete output when diagnosing packaging:
bpftool version
status=$?
printf 'bpftool exit status: %s\n' "$status"
Checkpoint: if command -v prints nothing, stop here and install the tool through your normal distribution process. Do not copy an executable from a different kernel release into /usr/sbin.
2. Read the top-level help before choosing an object
The top-level manual describes map, prog, link, cgroup, perf, net, feature, btf, gen, struct_ops and iter objects. Ask the installed binary for its own syntax:
$ bpftool help
Usage: bpftool [OPTIONS] OBJECT { COMMAND | help }
bpftool batch file FILE
bpftool version
Output is not a stable interface. The manual explicitly warns that output formats may change, so scripts should prefer documented JSON fields for the command and version you have installed, and should still tolerate fields being added.
The global options are useful at this point. --json requests JSON where the selected command supports it, --pretty requests human-readable JSON and implies JSON, --debug prints library and verifier logs, and --nomount prevents automatic attempts to mount virtual filesystems such as tracefs or the BPF filesystem. Use --nomount when an inspection must not mount anything.
3. List loaded programs and maps
Inspect the two object types most often needed during a first investigation:
$ bpftool --nomount prog list
$ bpftool --nomount map list
A working system may print no rows. That is a valid result: it means the command found no objects visible to this invocation, not that BPF is absent. If the command reports insufficient permission or cannot access a kernel interface, repeat the same read-only check with elevation only when your system policy permits it:
$ sudo bpftool --nomount prog list
$ sudo bpftool --nomount map list
sudo does not install missing kernel support and does not make an unavailable program appear. Keep the unprivileged result and the elevated result separate in an incident record. The object list can include names, IDs, types, tags, owners and load information, but field presentation varies with kernel and bpftool versions.
4. Capture machine-readable details for one object
Once the list shows an ID, request JSON for that object. Replace the placeholder with an ID that really appeared in your list:
$ BPF_PROG_ID=12345
$ bpftool --nomount --json prog show id "$BPF_PROG_ID"
$ BPF_MAP_ID=12345
$ bpftool --nomount --json map show id "$BPF_MAP_ID"
If the ID is stale, the kernel will reject it. That is useful evidence, not a reason to guess another identifier. Capture the JSON as a file only after checking that the destination is new:
test ! -e /tmp/bpftool-prog.json || {
printf '%s\n' 'Refusing to overwrite /tmp/bpftool-prog.json' >&2
exit 1
}
bpftool --nomount --json prog show id "$BPF_PROG_ID" > /tmp/bpftool-prog.json
test -s /tmp/bpftool-prog.json && echo 'JSON capture is non-empty'
This creates a temporary diagnostic file, not a pinned BPF object. Remove it after review if it contains information your operational policy does not permit keeping. Do not assume the JSON is a permanent schema: validate the fields your script needs and fail clearly when they are absent.
5. Probe available kernel features
Use the feature object to ask what this running kernel supports:
$ bpftool --nomount feature probe
The probe covers supported program and map types and other BPF capabilities. It may require elevated privileges, depending on the kernel and the parts being queried:
$ sudo bpftool --nomount feature probe
Compare the command output with the workload you intend to run. A feature being listed means the kernel reports support; it does not prove that your program will pass the verifier, that required privileges are available to its service account, or that a particular helper is allowed for a chosen program type. The official kernel documentation describes bpftool as a central tool for BPF debugging and introspection, which is the right mental model here.
6. Keep state-changing commands behind a deliberate review
The same command family includes operations such as prog load, prog attach, prog detach, map update, map delete and pin. These can change packet handling, tracing, service behaviour or the lifetime of objects. The manual also documents batch file FILE, which can run several commands; treat a batch file as executable change, not as harmless configuration.
Before using any mutating command, record the exact program, map, link or cgroup target, check the command with bpftool OBJECT help, and arrange a rollback that matches the operation. Never test an attach or delete command against a production ID copied from a list without an owner and maintenance window. If an inspection command unexpectedly tries to mount a virtual filesystem, stop it and rerun with --nomount; do not grant broader privilege just to silence the symptom.
Common failure traps
- Version warning: the installed common package is not proof that the kernel-specific tool is present. Check the executable and its exit status.
- Empty output: an empty list can be normal. It is not evidence that the kernel lacks BPF.
- Permission errors: try elevation for read-only diagnosis only when authorised, and report the original privilege boundary.
- Unstable output: do not parse human-readable listings as a long-term API. Prefer JSON, but still handle version differences.
- Destructive shorthand: never paste a
delete,detachor batch command until its target and recovery path are written down.
Done means
- You identified the resolved
bpftoolexecutable and recorded its version output and exit status. - You used
--nomountfor read-only program, map and feature inspection. - You distinguished empty output, missing kernel tooling and insufficient permission.
- You captured JSON only for a verified object ID and did not overwrite an existing diagnostic file.
- You kept loading, attaching, updating, deleting and batch execution outside the unattended workflow.