Nix wanted $ORIGIN in the kernel. It got eBPF-driven loader swaps instead.
At TacoSprint 2026, Farid Zakaria asked the Linux kernel mailing list to teach the kernel to resolve $ORIGIN, the token that already lets Nix binaries find their own directory. VFS maintainer Christian Brauner replied that the pieces already existed: combine binfmt_misc with an eBPF program, and he had a working example ready.
$ORIGIN is the token that tells a Linux loader to find dependencies relative to its own folder; ld.so has honored it for years. Nix wanted the kernel to honor it too, so packages stop hardcoding /nix/store paths: what landed instead swaps loaders through binfmt_misc via eBPF, overriding only PT_INTERP so /proc/self/exe still points at the real binary.
One catch surfaced fast: it needs root, since it can't run in an unprivileged namespace yet. And one commenter had already hand-built a similar userspace trick before this became a kernel feature.
A packaging bug traced back to a four-letter token: $ORIGIN
Every Nix package lives at a fixed, content-addressed path like /nix/store/xyz-glibc/lib, baked into every binary that depends on it. Move the store, or try to run the binary somewhere else, and it breaks. Farid Zakaria, who works on relocatable binaries for Nix, wrote up a fix built on something the loader already half-has: $ORIGIN, a token ld.so has resolved for years, meaning "the directory containing the executable itself." If a binary could resolve its own dependencies relative to wherever it currently sits, the store could move and nothing would break.
The catch is that $ORIGIN only works after the dynamic loader is already running. The kernel picks which loader to run via PT_INTERP, a fixed absolute path baked into every ELF binary at link time, before $ORIGIN logic ever gets a chance to apply. So Zakaria took the request to the Linux kernel mailing list at TacoSprint 2026: teach the kernel to resolve $ORIGIN itself, before handing off to the interpreter.
What Christian Brauner actually shipped instead
The kernel didn't get $ORIGIN. VFS maintainer Christian Brauner's answer was closer to "you already have the pieces": combine binfmt_misc (the mechanism that lets the kernel hand a file type off to a custom handler) with an eBPF program that computes the right loader path at exec time, based on where the binary actually lives on disk. No new syscall, no new ELF field: just a small, verified, JIT-compiled program registered into a slot the kernel already exposes.
The part that took real iteration was identity. Standard binfmt_misc handoff replaces the running program with the interpreter: argv[0], /proc/self/cmdline, /proc/self/exe all end up pointing at the interpreter, not the actual binary, which breaks exactly the self-locating trick relocatable binaries depend on. The patch set that emerged adds a second dispatch mode that runs the real binary directly and overrides only PT_INTERP, so a relocated Nix binary can still read its own path from /proc/self/exe and find its dependencies next to itself. Zakaria says the mailing-list exchange was unusually collegial for a list with a famously combative reputation; engineers iterated the design with him rather than rejecting the premise outright.
The thread's first move: does this even need the kernel?
The 72-comment thread opened with pushback before anyone had even gotten to the mechanism, from a commenter with a long history on the site.
"But, if ld.so supports $ORIGIN already, why does the kernel needs to support it also? Or rather, why can't the kernel leverage ld.so and do this entirely on userspace?" — an HN user with over 6,000 karma
The answer, buried in the mechanism itself: ld.so never gets to run until the kernel has already committed to an interpreter path via PT_INTERP. By the time userspace $ORIGIN logic could act, the wrong loader may already have failed to load. The kernel patch isn't solving $ORIGIN resolution at all: it's solving what happens one step earlier.
A reader who expected a policy fight got a working patch
The framing "kernel will support X" tends to read as a feature request heading for the usual maintainer standoff. One systems programmer went in braced for exactly that.
"My reaction was negative when I read the title (policy!), but the actual outcome was very reasonable. 'Hey, can we add $ORIGIN to the VFS layer to support relocatable interpreters?' 'You can already do that with binfmt_misc and ebpf, here's an example.' Then, later, a couple of patches to make binfmt_misc more ergonomic. Seems like a good outcome." — wzdd, a systems programmer in Sydney
The pattern he's describing is the whole story in miniature: the ask got quietly declined, and what shipped was smaller and more general than what was requested.
The catch nobody mentions in the pitch: it needs root
Not every reaction was about the design. One reply zeroed in on a deployment limit the writeup doesn't dwell on.
"Its unfortunate that this is using eBPF and not cBPF. I'd want to enable this in a namespace using binfmt-misc's namespace support, but eBPF requires root." — a developer who wanted to run it inside an unprivileged namespace
That's a real limit on who can use this without a system administrator's cooperation: unprivileged containers, rootless build sandboxes, and CI runners that don't hand out root can't register their own binfmt eBPF handler yet. The convenience Nix wanted at the package level still needs a privileged operator at the machine level.
Someone had already half-solved this by hand
Before any of this landed, at least one person in the thread had been assembling the same outcome from spare parts.
"I have made appseed which used zapps which did a lot of tricks to achieve in end what this kernel patch could help in doing and hopefully more in the future! My appseed project didn't work for large projects like OBS but I feel like the approach that this does could lead to mass adoption given that its now a kernel feature." — a developer who built a portable-binary tool called appseed on top of zapps, in userspace, before this landed as a kernel feature
Not everyone welcomed the framing of Nix as the problem to be solved for. A different reply argued the burden runs the other way: Nix's need for a moving store keeps generating patches other projects have to carry, from custom shebangs to flake-specific build hooks, instead of Nix adapting to how the rest of the ecosystem already works.
The precedent outlasts $ORIGIN
The actual win here isn't that Nix binaries get to move around more freely, though they will. It's that "teach the kernel a new exec-time policy" no longer means a new syscall and a multi-year ABI commitment. It means writing a small eBPF program and registering it in a slot the kernel already has. Whoever needs the next narrow, binary-specific loader rule now has a template that skips the syscall review queue entirely.
Get breakdowns like this every day
The top Hacker News stories, unpacked — by email, Telegram, or RSS.
This is the last story in the July 22, 2026 issue.
Go to the issue archive