Something is hooked into your kernel via perf and you want to know who, so run bpftool perf. It lists the BPF programs attached through perf events, and you can turn the same inventory into JSON for scripts or incident notes. The command is read-only: it does not detach programs, unload BPF objects or change a service. Allow about ten minutes, or longer if the matching kernel-tools package is missing.
This guide follows the installed bpftool-perf(8) manual from linux-tools-common version 6.8.0-139.139. The local package supplies a wrapper, but this machine lacks the kernel-specific executable for kernel 6.8.0-139. That is a packaging problem, not evidence that the host has no BPF attachments.
Start with ordinary, read-only checks, and do not add sudo yet. The first command identifies the program your shell selects. The second asks the wrapper for its version:
$ command -v bpftool
/usr/sbin/bpftool
$ bpftool -V
WARNING: bpftool not found for kernel 6.8.0-139
You may need to install the following packages for this specific kernel:
linux-tools-6.8.0-139-generic
linux-cloud-tools-6.8.0-139-generic
Exact wording varies with the distribution and running kernel. On the machine used for this guide, the wrapper exits after this warning because the matching tool is absent. Check the package version separately when you need an audit trail:
$ dpkg-query -W -f='${Package}\t${Version}\n' linux-tools-common
linux-tools-common 6.8.0-139.139
Checkpoint: if bpftool -V names a missing kernel-specific package, stop here and install it through your normal change process. Do not work around the mismatch by copying a binary from another host.
Once a working bpftool binary is present, the perf family accepts show and list as equivalent inventory commands. The default invocation is:
$ bpftool perf
pid 21711 fd 5: prog_id 5 kprobe func __x64_sys_write offset 0
pid 21767 fd 5: prog_id 8 tracepoint sys_enter_nanosleep
The process ID and file descriptor identify the process holding the perf event. prog_id identifies the BPF program. The remaining fields describe the attachment type and point. The sample values are illustrative: your host can legitimately print no records, or a completely different set.
Use the explicit spelling in scripts when clarity matters:
$ bpftool perf show
$ bpftool perf list
Tip: both commands list raw tracepoint, tracepoint and probe attachments known to the running system. They do not list every kind of BPF link, so an empty perf inventory does not prove the kernel has no BPF programs.
Tracepoint records use a probe name, such as sys_enter_nanosleep. Kernel probes use a function and offset, or a kernel virtual address. User probes use a file name and file offset:
$ bpftool perf show
pid 21765 fd 5: prog_id 7 kretprobe func __x64_sys_nanosleep offset 0
pid 21767 fd 5: prog_id 8 tracepoint sys_enter_nanosleep
pid 21800 fd 5: prog_id 9 uprobe filename /home/yhs/a.out offset 1159
Use -j or --json when another tool will consume the result. The output is an array of objects, with field names that match the attachment kind:
$ bpftool -j perf
[{"pid":21711,"fd":5,"prog_id":5,"fd_type":"kprobe","func":"__x64_sys_write","offset":0},
{"pid":21767,"fd":5,"prog_id":8,"fd_type":"tracepoint","tracepoint":"sys_enter_nanosleep"},
{"pid":21800,"fd":5,"prog_id":9,"fd_type":"uprobe","filename":"/home/yhs/a.out","offset":1159}]
For readable JSON during a manual review, add -p. It implies JSON:
$ bpftool -p perf
Prefer JSON for scripts over parsing the human-readable spacing. Test for a field such as func, tracepoint or filename according to fd_type, and do not assume every object has all three.
The perf subsystem is subject to the host's security policy. Run the inventory as the account that will normally use it. If it reports a permission error, inspect the error and your organisation's perf policy before trying elevation:
$ bpftool perf show
[permission diagnostic from this host]
$ printf 'exit status: %s\n' "$?"
exit status: 1
sudo. Elevated access may reveal more system information, but it does not repair a missing kernel-specific bpftool binary and it does not detach anything.bpftool perf show.Every command in this workflow reads program and attachment metadata. There is no undo command because nothing was changed.
Warning: do not follow an unexpected attachment by killing the listed process or deleting a pinned BPF object. Those actions can disrupt tracing or an application, and they need a separate ownership and rollback decision.
For an incident record, save JSON to a new file rather than overwriting an existing report:
$ output_file="bpftool-perf-$(date +%Y%m%d-%H%M%S).json"
$ bpftool -j perf > "$output_file"
$ test -s "$output_file" && echo 'inventory saved'
Shell globbing can match several old reports, so use a dedicated empty directory or an explicit destination when automating this. Keep the file access-controlled if attachment names or process IDs are sensitive in your environment.
bpftool perf show or bpftool perf list produced the current perf attachment list.-j output and handle attachment-specific fields.