Bringing BPF to binfmt_misc [LWN.net]
LWN<br>.net<br>News from the source
Content Weekly Edition<br>Archives<br>Search<br>Kernel<br>Security<br>Events calendar<br>Unread comments
LWN FAQ<br>Write for us
User:<br>Password: |
Log in /<br>Subscribe /<br>Register
Bringing BPF to binfmt_misc
[LWN subscriber-only content]
LWN needs you
LWN counts on its subscribing readers to support its mission of creating relevant human-written news coverage of the Linux and free-software communities. Please subscribe to LWN and help to keep us on the net.
As a special offer, subscribe to LWN now for at least six months, and receive a 25% discount on your subscription.
[+] Proceed to the article
By Jonathan Corbet<br>August 6, 2026
The kernel is able to run a few types of executable files, including native<br>binaries in the ELF format and interpreted programs that begin with the<br>#! marker. It also, however, has a mechanism, called binfmt_misc,<br>that can be configured from user space to enable the transparent execution<br>of programs in just about any format. This feature has been relatively<br>static for years, but it seems likely to receive some significant updates<br>in the near future, including the ability to load BPF programs that can<br>decide how to run a given program.
binfmt_misc
In the beginning, Linux used the a.out format for binary<br>executables. Support for the Executable<br>and Linkable Format (ELF) was added to the 0.99.13 release in 1993,<br>with distribution support (involving upgrades so painful that they still<br>cause post-traumatic stress many years later) arriving around 1995. But,<br>from the earliest days, there was interest in running programs in different<br>formats as well. There were a number of Unix variants available for x86<br>systems, for example, each with its own binary format. There are<br>languages, such as Java, that compile to their own virtual machines and<br>need a separate interpreter. The kernel could gain support for all<br>of these formats, but it was understood early on that a more general<br>solution was called for.
That solution is binfmt_misc, which was added for the 2.1.43pre1<br>development release in 1997. In its current form, binfmt_misc presents a<br>directory under /proc/sys/fs/binfmt_misc containing a file called<br>register. Writing a string to that file registers a new format<br>and tells the kernel how to recognize executables in that format;<br>recognition can be based on a pattern in the first 256 bytes of the<br>file itself, or on the file's name extension. For example, the<br>documentation states that support for packed DOS applications can be had by<br>writing this string to the register file:
:DEXE:M::\x0eDEX::/usr/bin/dosexec:
This line causes the kernel to recognized a packed DOS executable by the<br>four-byte sequence \x0eDEX at the beginning of the file; it will<br>invoke /usr/bin/dosexec to run that executable. As another<br>example, any file with a .py extension and execute permission can<br>be executed directly with:
:python:E::py::/usr/bin/python3:
After that has been done, .py files will be executed by the Python<br>interpreter regardless of whether they contain a #! line.<br>Multiple binfmt_misc entries can be made; the first matching entry is<br>selected whenever an interpreter for a program must be found. In a<br>delightful quirk, entries are checked in the opposite order that one might<br>expect; the most recently added entries are checked first.
With binfmt_misc in place, the kernel developers allowed user space to set<br>up whatever policy it needs for its own special executable formats; there<br>was no longer a need to add dedicated support to the kernel for them. While<br>this feature has seen a slow stream of improvements over the years, it has<br>not seen many fundamental changes since its introduction nearly three<br>decades ago.
Hermetic binaries
The formats defined with binfmt_misc all involve an interpreter that<br>handles the actual execution of the program. Native binaries, instead, run<br>directly on the CPU, but (unless they are statically linked) they still<br>involve an interpreter; in that case, the interpreter is the dynamic<br>linker, which is charged with loading the binary code into memory, loading<br>libraries, and resolving references. The location of that interpreter is,<br>for ELF files, found in the ELF binary itself, in the PT_INTERP<br>segment; it is typically something like<br>/lib64/ld-linux-x86-64.so.2. The kernel loads the interpreter,<br>then lets it do the rest of the work in user space.
This scheme has worked well for many years, but there is always somebody<br>who wants to do something different. Back in June, Farid Zakaria made<br>the case that the Nix distribution needs relocatable binaries — binary<br>programs that are fully self-contained (hermetic) and can run regardless of<br>where they are placed in the filesystem hierarchy. A hermetic binary<br>needs, among other things, a specific version of the dynamic linker, which<br>may not be the default one installed on the system where the binary is<br>expected to run. The PT_INTERP mechanism can allow for the<br>specification of a...