假设 Linus Torvalds 没有提出异议,那么已经为即将到来的 Linux 6.17 合并窗口提交了一个早期的拉取请求,以解决一个晦涩难懂的内核限制,该限制可以追溯到 1993 年的 Linux v0.99 内核时代。
一位在阿里巴巴工作的 Linux 工程师最近报告了一个脚本生成的 Assembly 文件,当该文件由 GCC 编译器构建并作为 ELF 文件运行时,会导致奇怪的问题。如果使用标准 4K 页面大小内核,则由于“exec 格式错误”,此 ELF 文件将无法在 Linux AArch64/ARM64 上运行。但是,如果为 ARM64 使用现代 64K 页面大小,则此 ELF 文件将正常工作。
阿里巴巴工程师指出,在内核中的一个加载 ELF 函数中,有一个检查,以查看大小是否大于 ELF_MIN_ALIGN / PAGE_SIZE,如果是这种情况,则将其救助,它被赋予了这个特定 ELF 文件中的程序头数量。但尚不清楚为什么要进行这项检查。如果删除此内核,请检查特定的二进制文件在 4K 页面大小内核上运行正常。

长期的 Linux 开发人员 Kees Cook 深入研究了 Git 之前的旧代码,试图弄清楚它。他解释说:
“查看 https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git(它没有链接历史记录,所以你必须检查显式的”pre git“标签),我看到:
4779b38bcb96(”[PATCH] Linux-0.99.13(1993 年 9 月 19 日)“),其中说”ELF 二进制文件支持这是一个显着的变化“。在这里,PAGE_SIZE
检查不存在。当在 9e11983a5a3e (“Import 0.99.15f”) 中添加 ELF 插值支持时,我们看到出现了检查,但我找不到
任何理由。对于 6a8d38945cf4(“binfmt_elf:将 ELF 程序头加载到函数”),对于非插值加载,PAGE_SIZE检查是 _added_ 的。
看起来 64K 计数限制就足够了?(如果目标是避免用户空间发生大量内存分配,那么我们现在已经过去了 IPC、BPF 等之间的PAGE_SIZE。这对你有用吗?
因此,现在对于 Linux 6.17 是一个补丁,用于删除程序头大小的 4K 限制。
“我们有由脚本生成的汇编代码。GCC 成功编译了它。但是,内核无法在页面大小为 4K 的 ARM64 平台上加载它。相比之下,相同的 ELF 文件可以正确加载到页面大小为 64K 的同一平台上。
根本原因是 Linux 内核对 ELF 文件的程序头的ELF_MIN_ALIGN限制。ELF 文件包含 78 个程序头(脚本在生成汇编代码时插入了许多孔)。在页面大小为 4K 的 ARM64 上,ELF_MIN_ALLIGN最多强制执行 74 个程序标头,从而导致 ELF 文件失败。但是,对于 64K 页面大小,ELF_MIN_ALIGN放宽到超过 1,184 个程序头,从而允许文件正常运行。
Cook 善意地指出,此限制是在 Linux-0.99.15f 中引入的,但没有解释其目的。
ELF 规范没有对程序标头施加这样的限制。删除程序标头的ELF_MIN_ALIGN限制以与 ELF 规范保持一致。删除ELF_MIN_ALIGN限制后,64K 大小限制仍然存在,这应该足够了。
该补丁是作为 Linux 6.17 执行更改的一部分发送的。假设 Linus Torvalds 本人没有发现任何问题,则在 Linux 6.17 合并窗口打开后,应该合并此修复程序……假设 Linux 6.16 在周日按计划进行,这将最快在周一进行。
转自 Linux 6.17 Looks To Address An Old & Obscure Kernel Limitation From 1993 – Phoronix
Linuxeden开源社区