Inspect, Dump and Pin eBPF Programs with bpftool prog
A program you did not write is running inside your kernel, and bpftool prog shows you what it is. You will list loaded programs, read their identifiers and instructions, then load and pin one for later use. Allow 15 minutes for inspection, or longer if you are loading an object from another project. The examples split cleanly between read-only checks and commands that change kernel state.
The route
Jump straight to the step you need, or tick off Done means at the end.
This guide follows the bpftool-prog(8) page installed with Ubuntu's linux-tools-common package, version 6.8.0-139.139. The executable normally comes from the matching kernel tools package as well, so check both the package and the command before relying on a feature.
1. Check the tool and your privileges
Start with read-only checks. The command may sit under a kernel-specific directory, depending on the distribution:
$ command -v bpftool
$ bpftool version
$ dpkg-query -W -f='${Package} ${Version}\n' linux-tools-common
- Expect a version.
bpftool versionshould print a bpftool version, the libbpf version and compiled-in features. - Missing command means a package. Install the tools package matching the running kernel through your normal package-management process. The manpage package alone does not prove the executable is available.
- Privileges vary. Listing may work as an ordinary user on some systems, but access to BPF objects and bpffs depends on kernel policy and permissions. Use
sudoonly when the command reports a permission failure, and keep the first investigation read-only.
2. List loaded programs and select one precisely
List every program visible to the command:
$ sudo bpftool prog show
10: xdp name some_prog tag 005a3d2123620c8b gpl
loaded_at 2017-09-29T20:11:00+0000 uid 0
xlated 528B jited 370B memlock 4096B map_ids 10
The numbers are host-specific, so do not copy an ID from this example. The leading number is the program ID. The type, name and tag help you identify the right object.
A program selector can be id, pinned, tag or name. A name or tag can match more than one program, so use an ID or a pinned path when a later command needs exactly one.
For scripts, ask for JSON instead of scraping aligned text:
$ sudo bpftool --json --pretty prog show
[{"id":10,"type":"xdp","tag":"005a3d2123620c8b","jited":true}]
$ sudo bpftool -j prog show > /tmp/bpftool-progs.json
The fields shown depend on the kernel and the program. Since Linux 5.1, run-time statistics can be reported when the kernel statistics switch is enabled, but collection is off by default because it costs performance. Since Linux 5.8, the listing can also show processes holding BPF program file descriptors.
3. Dump the program before changing anything
Replace PROGRAM_ID with an ID you just checked. The translated eBPF instructions are the most useful first view:
$ sudo bpftool prog dump xlated id PROGRAM_ID linum
0: (b7) r0 = 0
1: (95) exit
Exact instructions and source locations vary. Add opcodes for raw opcode bytes, or visual for a control-flow graph in DOT format. The latter needs a single match, so do not combine it with a broad name or tag that selects several programs.
JIT output is host machine code, not portable eBPF:
$ sudo bpftool prog dump jited id PROGRAM_ID opcodes
0: push %rbp
55
Save a binary dump when you want to compare it later:
$ sudo bpftool prog dump xlated id PROGRAM_ID file /tmp/program.xlated
$ test -s /tmp/program.xlated && echo "translated dump written"
translated dump written
Warning
Ordinary shell redirection and the file destination overwrite what is already there. Use a new temporary name if the old evidence matters.
4. Check bpffs before pinning
Pinning gives a BPF program a filesystem reference that survives the creating process. The destination must be inside a mounted BPF filesystem, usually /sys/fs/bpf, and its final name must not contain a dot:
$ findmnt /sys/fs/bpf
TARGET SOURCE FSTYPE OPTIONS
/sys/fs/bpf bpf bpf rw,nosuid,nodev,noexec,relatime
$ sudo bpftool prog show id PROGRAM_ID
If the mount is absent, ask the system administrator to provide the expected bpffs mount. Do not mount a new filesystem in a production namespace without checking its ownership and boot configuration.
Tip
Some bpftool commands try to mount virtual filesystems automatically. Use --nomount when you want a command to fail instead of attempting that convenience.
5. Pin one program, then verify the reference
This is the first state-changing command. Confirm the ID and destination twice before you run it:
$ sudo bpftool prog pin id PROGRAM_ID /sys/fs/bpf/example_prog
$ sudo bpftool -f prog show id PROGRAM_ID
10: xdp name some_prog ...
pinned /sys/fs/bpf/example_prog
The -f or --bpffs option asks the listing to show pinned filenames. Verify the path is present with stat. To undo this particular pin, remove the bpffs entry after confirming that no service still needs it:
$ sudo stat /sys/fs/bpf/example_prog
$ sudo rm -- /sys/fs/bpf/example_prog
Warning
Removing the pin removes that filesystem reference. It does not necessarily unload a program still referenced by a process, link or another pin. The rm command is irreversible for that path, so check the consumers before you use it as cleanup.
6. Load an object after reviewing its scope
Loading an ELF object can create maps, consume kernel resources and, with autoattach, attach a program before pinning it. Treat an object from outside your build as executable, kernel-facing input. Review its provenance, program sections, map definitions and intended hook before using elevated privileges.
load pins only the first program. loadall pins every program under a directory. The type can be inferred from section names, but stating it makes the operation easier to review:
$ sudo bpftool prog load ./PROGRAM.o /sys/fs/bpf/example_prog type xdp
$ sudo bpftool -f prog show pinned /sys/fs/bpf/example_prog
- Maps are created afresh by default. The
map name MAP_NAME id MAP_IDormap name MAP_NAME pinned FILEform lets you reuse an existing map. Check the map's definition and owner before doing so. - Pin maps deliberately.
pinmaps MAP_DIRpins maps under a directory. - Autoattach pins a link. If you use
autoattach, verify the corresponding link withbpftool link show -f, because the pinned path represents the link rather than the program itself.
7. Diagnose without widening the change
Use -d or --debug when a load fails. It includes libbpf and verifier messages, which often identify the instruction, map or permission that needs attention:
$ sudo bpftool -d prog load ./PROGRAM.o /sys/fs/bpf/example_prog type xdp
libbpf: loading object './PROGRAM.o'
libbpf: prog 'example' rejected: Permission denied
The wording and verifier details are kernel-specific. A non-zero exit status is the useful signal, so do not retry a failing load repeatedly against a live hook.
For loader-program diagnostics, -L attempts the load without pinning, and bpftool prog tracelog prints the kernel trace pipe until you press Ctrl+C.
Warning
Tracelog is for debugging only and can expose data written by other BPF programs.
Done means
- Versions checked. You read the installed bpftool and libbpf versions, and matched the manpage to the package on the host.
- Real ID used. You selected a program ID from
bpftool prog showinstead of reusing an example. - Inspected first. You looked at translated or JIT instructions before pinning or loading anything.
- Pin verified. You confirmed bpffs, used a dot-free destination and checked the pin with
-f. - Cleanup understood. You know whether a later cleanup removes only a pin or also affects an attached link, map or service.