llseek 和 e2fsck 发生了什么?

use*_*438 9 linux system-calls glibc

lseek 手册页:

当用户抱怨 e2fsck(8) 编译错误导致数据丢失时,glibc 2.1.3 添加了链接时警告

“该llseek函数可能很危险;请改用 `lseek64。”

如果需要无警告编译,这使得该函数无法使用。

从 glibc 2.28 开始,该函数符号不再对新链接的应用程序可用。

这背后有什么故事?

Ste*_*itt 11

问题是 glibc 包含一个llseek符号,但在其头文件中没有相应的声明。e2fsck\xe2\x80\x99s 配置脚本检测到该符号,并假设这意味着该函数可用。然而,隐式函数声明\xe2\x80\x99与函数期望的不匹配,导致函数调用最终被错误编译。特别是,llseek需要 64 位偏移量,但隐式声明导致int参数 \xe2\x80\x94 这就是导致数据丢失的原因,因为e2fsck在与预期不同的偏移量处进行了更改。

\n

e2fsck使用的原因llseek是 libc5,Linux 上的 glibc\xe2\x80\x99 的前身,声明了它并使其可用(它在unistd.h)。因此e2fsck,当针对 libc5 构建时,正确使用llseek;但是当针对 glibc 构建时,构建成功但无法正常工作。

\n

此问题已在 e2fsprogs 1.12 中修复,更改日志条目如下:

\n
\n

E2fsprogs 现在可以与 glibc 一起使用(至少与 RedHat 5.0 附带的版本一起使用)。即使 llseek() 不存在,ext2fs_llseek() 函数现在也应该可以使用 \ni386 ELF 共享库。我们还\n显式地进行配置测试,以查看 (a) llseek 是否在 libc 中,以及\n(b) llseek 是否在系统头文件中声明。(请参阅有关 libc 开发人员不理解与以前版本的 libc 的兼容性概念的标准\n投诉。)

\n
\n

llseekC 库也进行了更改,以便在代码尝试使用;时发出警告。讨论可以在邮件列表档案中找到

\n

  • 隐式声明假定所有参数都是“int”,但偏移量是 64 位类型;因此调用者认为它正在寻找给定的偏移量,但传递给函数的值是不同的。这就是导致数据丢失的原因。你的结论是正确的,隐含的声明才是危险的。 (4认同)
  • “llseek”的具体问题在于它在 libc5 中可用,在“unistd.h”中声明。因此,尝试使用它的代码在 libc5 中可以工作,但在 libc6 中却做了错误的事情。 (2认同)