Linux Kernel Gets $ORIGIN Support via eBPF
Farid Zakaria, during TacoSprint 2026, set out to make Nix binaries relocatable. The result: a patch series from VFS maintainer Christian Brauner that adds eBPF-based dynamic interpreter selection to binfmt_misc. This enables $ORIGIN resolution in PT_INTERP and shebangs, with a new L dispatch mode that cleanly substitutes the loader.
The Problem: Fixed Interpreters
Dynamic binaries specify their interpreter (e.g., ld.so) via the PT_INTERP ELF segment. This path is absolute. Tools like Nix, Bazel, or Buck that use content-addressed stores want relocation: the interpreter should be relative to the binary's location ($ORIGIN). The kernel currently doesn't support that.
The Solution: eBPF in binfmt_misc
Brauner proposed extending binfmt_misc with eBPF programs. Instead of a fixed interpreter or a static match rule, the kernel invokes a BPF program that decides the interpreter at runtime. Zakaria provided an example:
SEC("struct_ops.s/match")
bool BPF_PROG(nix_match, struct linux_binprm *bprm)
{
return !bpf_strncmp(bprm->buf, 4, "\x7f" "ELF");
}
SEC("struct_ops.s/load")
int BPF_PROG(nix_load, struct linux_binprm *bprm)
{
char path[256];
long n;
n = bpf_path_d_path(&bprm->file->f_path, path, sizeof(path));
if (n < 0)
return n;
/* derive the loader location from the binary's path */
return bpf_binprm_set_interp(bprm, path, sizeof(path));
}
SEC(".struct_ops.link")
struct binfmt_misc_ops nix = {
.match = (void *)nix_match,
.load = (void *)nix_load,
.name = "nix",
};
Once loaded and registered via:
bpftool struct_ops register nix_origin.bpf.o /sys/fs/bpf
echo ':origin:B::::nix:' > /proc/sys/fs/binfmt_misc/register
Every ELF binary triggers the BPF program, which computes the interpreter path relative to the binary. The kernel then uses that interpreter.
The 'L' Dispatch Mode
Traditional binfmt_misc hands off execution to the registered interpreter, making it the main process. That breaks /proc/self/exe and argv[0]. Brauner's patch series adds a new L flag (loader substitution). With L, the kernel executes the matched binary natively and merely substitutes the interpreter. The binary retains its identity, so /proc/self/exe points to the binary, not the loader.
What This Means for Nix and Others
For Nix, this enables truly relocatable binaries. Zakaria plans to upstream a NixOS module that registers the BPF program at boot, gated on a new PT_INTERP_NIX ELF segment. Only binaries that opt-in get the dynamic behavior; existing binaries work unchanged.
Beyond $ORIGIN
Since the BPF program has full access to the binary's contents, possibilities expand: shebang $ORIGIN support, per-binary QEMU emulator selection, or custom security policies. The kernel now allows programmable interpreter selection without patching the VFS.
Next Steps
The patch series is heading to the -next branch for integration into a future Linux release. Developers can track progress and experiment with the eBPF approach today.

