Linux内核终于支持$ORIGIN了
Linux kernel will support $ORIGIN, sort of
在TacoSprint 2026期间,我突发奇想尝试在Nix中实现可重定位二进制文件。起初我担心向Linux内核提交补丁会遭到冷遇,没想到VFS维护者Christian Brauner不仅积极回应,还利用eBPF和binfmt_misc提出了更强大的解决方案。我们合作开发了一套补丁,通过eBPF程序动态选择解释器,不仅完美支持了$ORIGIN,还能灵活处理shebang。Christian还引入了新的L模式,解决了传统binfmt_misc导致进程身份混乱的问题。未来,我计划将这一功能集成到NixOS模块中,让Nix生成的二进制文件真正具备可重定位能力。
停泊在港口的船很安全,但那不是造船的目的。
HN 评论区
74- nextaccountic
我对 $ORIGIN 到底是什么意思有点困惑,所以稍微展开一下这篇文章的内容:
https://fzakaria.com/2026/06/21/nix-needs-relocatable-binari...
> 不过,Linux 的加载器原生支持 $ORIGIN 变量,它代表“包含可执行文件的目录”。
https://man7.org/linux/man-pages/man8/ld.so.8.html
但是,如果 ld.so 已经支持 $ORIGIN 了,为什么内核还需要支持它呢?或者说,为什么内核不能利用 ld.so,完全在用户空间完成这件事?
- wzdd
看到标题(又是政策!)时我的第一反应是负面的,但实际结果非常合理。“嘿,我们能不能把 $ORIGIN 加到 VFS 层以支持可重定位的解释器?”“你本来就可以用 binfmt_misc 和 ebpf 做到,这里有个例子。”
随后,又提交了几块补丁让 binfmt_misc 更好用。看起来是个不错的结果。
- stabbles
不错,PT_INTERP 是 ELF 文件中唯一不可重定位的东西,通常需要使用包装脚本或可执行文件。
关于 shebang,我一直不明白为什么内核不能根据 PATH 而不是 CWD 来解析例如 `#!sh`。Posix 规定你应该在 PATH 中查找 `sh`,而不要指望它就在 `/bin/sh` 里。而且使用 `/usr/bin/env sh` 也有同样的问题:万一 coreutils 安装在了别的地方呢。
- bobajeff
这里很多人似乎认为这个改动能让人们打包 Linux 应用,使其能在不同的发行版或发行版版本间移植。如果这是真的,那太棒了!
在基于 Debian 的发行版上,有时候某个包的版本只在新版本发行版中才有,这时你要么自己编译,要么升级系统,体验很糟糕。
我记得曾经尝试过通过下载新版本发行版的依赖并帮助程序找到它们来绕过这个问题,但我好像遇到了链接器版本被硬编码之类的问题,最后就放弃了。
- Asmod4n
等等,这是否意味着我们现在可以“虚拟化”ld.so 了?这或许终于能解决 glibc 带来的兼容性问题。