Home / Alt manpages / bpftool-prog(8)

  • bpftool-prog(8)
  • Admin command
  • linux

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.

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 version should 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 sudo only 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_ID or map name MAP_NAME pinned FILE form lets you reuse an existing map. Check the map's definition and owner before doing so.
  • Pin maps deliberately. pinmaps MAP_DIR pins maps under a directory.
  • Autoattach pins a link. If you use autoattach, verify the corresponding link with bpftool 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 show instead 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.