Solo – 适用于静态 Linux 二进制文件的 .so 加载器
一个新项目 Solo 将自己的 ELF 加载器嵌入静态链接的 Linux 二进制文件中,使它们即使在基于 musl 构建时,也能 `dlopen()` 宿主机上的 GPU 以及其他仅支持 glibc 的驱动。评论者一边讨论这种可移植、几乎静态的二进制文件的吸引力,一边警惕重新实现 glibc 的 ABI 和加载器语义所带来的风险,担心前向兼容性、安全性以及未文档化行为的脆弱性。讨论进一步延伸到对 Linux 用户态 ABI 与打包生态碎片化的批评,将容器、AppImage 和“基于旧 glibc 构建”等策略,与无 libc 的自由用户态等更激进的想法进行了对比。
项目目的与方法
- Solo 旨在让完全静态、基于 musl 链接的 Linux 二进制文件能够动态加载宿主机提供的
.so驱动(尤其是基于 glibc 构建的 GPU 驱动),其实现方式包括:- 一个自定义 ELF 加载器(x86‑64、aarch64)。
- 一个“glibc ABI 桥接”,在 musl 之上为 glibc 符号提供兼容层。
- 目标是生成可移植的二进制文件:无需修改即可在 glibc 发行版、musl 发行版(例如 Alpine)上运行,并最终也能支持 Android/bionic,同时从应用的角度仍然保持“静态”的感觉。
安全性与正确性方面的担忧
- 多条评论警告说,实现自定义 ELF 加载器和 ABI shim 很脆弱:
- 在映射和执行代码时的任何 bug 都可能成为 RCE 向量,尤其是在特权上下文中使用时。
- SysV/ELF ABI 存在一些未文档化的细节(例如 AT_SECURE),很容易出错。
- 作者回应称:
- ld.so 本来就做了类似的映射工作。
- 该项目有大量测试、100% 覆盖率,并且已经在大约 1000 个 Debian 包上运行,后续还计划进行 fuzzing。
glibc、musl 与 ABI 的纠缠
- 讨论很长,指出在 Linux 上:
ld.so、libc.so、libstdc++、TLS、原子操作、异常展开以及 C++ 全局对象彼此深度耦合,而且部分内容并未文档化。- 用 glibc 编译的共享库实际上依赖于那个精确版本的 glibc 以及它的加载器。
- 有人认为这种设计使得替代 libc(musl、bionic)处于次等地位,并迫使人们使用像 Solo 这样的“补丁式”方案。
- 也有人反驳说,对于 C 而言,ABI 大体上是稳定的,而且 glibc 通常保持向后兼容,尤其是在使用较旧的 glibc 进行构建时。
静态链接 vs 动态链接与发行版分发
- 支持静态链接的一方:
- 希望得到完全自包含的二进制文件,不信任 glibc 和发行版的频繁变动,并偏好无运行时依赖的 C/Rust 或直接系统调用。
- 指出在 musl 系统上使用专有/仅支持 glibc 的 GPU 驱动、NSS、Mesa 等会很痛苦。
- 持怀疑态度的一方:
- 认为 Solo 带来了前向兼容风险:未来驱动可能需要新的或带版本信息的 glibc 符号,而嵌入的 shim 不支持这些符号。
- 建议更简单的方法:用旧 glibc 做动态链接、使用容器(Docker/Flatpak),或者采用 AppImage/manylinux 风格的基线。
这是不是一个小众问题?
- 有人认为这只对基于 musl 的发行版或专有驱动有意义;大多数发行版使用标准动态链接就没问题。
- 也有人坚持认为,这对无法按发行版逐一构建/打包、但又希望单一二进制文件能在 glibc、musl 和 Android 上“开箱即用”的小型独立开发者来说,确实是个真实痛点。
LLM 生成的代码与文档
- 作者公开使用 LLM 编写代码和文档,并将其辩护为高生产力做法,同时有人类审核。
- 一些读者强烈不信任 LLM 撰写的 README,把它们视为“slop”,并将其与低投入项目联系在一起。
- 另一些人认为这种风格偏见并不恰当,技术质量和测试比文本“像不像 LLM”更重要。