【问题标题】:How to verify which version of getaddrinfo is in an executable如何验证可执行文件中的 getaddrinfo 版本
【发布时间】:2019-03-07 20:56:12
【问题描述】:

我的公司销售带有许多可执行文件的基于 linux 的设备。其中一个应用程序每隔几天就会挂在我们产品的最新版本中。

我们正在使用 glibc 2.19 和 gcc 4.8.3 以及 Linux 内核版本 3.16.38。我们正在为 x86_64 构建。

我们的 glibc 版本非常旧,据说我们在一年前对它进行了修补,修复了以下问题: 错误 #12926:getaddrinfo()/make_request() 永远旋转 (https://sourceware.org/bugzilla/show_bug.cgi?id=12926)

我们的 crosstool 的维护者发誓我们使用的那个有一个补丁 glibc。然而,还有其他失败的可能性,比如我们的构建可能出于某种原因选择了不同的 glibc。

在我们的构建机器上,我们保存了应用程序可执行文件和共享对象二进制文件的未剥离版本,以便以后在调试核心文件时使用。

我通过登录到一个应用程序挂起的设备并向进程发送 SIGILL 生成了一些核心文件。

核心文件似乎表明我们在 getaddrinfo() 中遇到了挂起,并且堆栈跟踪看起来像我们在修补 glibc 之前获得的那些。使用最新部署构建的最新核心文件示例:

Thread #18 1456 (Suspended : Container)
recvmsg() at 0x7f1fa276c17d
make_request() at 0x7f1fa278695d
__check_pf() at 0x7f1fa2786e54
getaddrinfo() at 0x7f1fa2759501

Thread #16 1454 (Suspended : Container)
__lll_lock_wait_private() at 0x7f1fa277777b
_L_lock_443() at 0x7f1fa2786f4d
__check_pf() at 0x7f1fa2786d05
getaddrinfo() at 0x7f1fa2759501

我希望能够验证我们已部署的发布可执行文件正在执行哪个版本的 getaddrinfo():已修补或未修补。在我的个人开发箱上这样做无济于事,因为那只会验证我自己的工具链/构建环境。有什么办法可以用我们部署的发布二进制文件来做到这一点?

编辑:我忘了提到我们是静态链接的。

编辑 2:我对静态链接的看法是错误的。我们过去几乎静态链接所有内容,但我们不再与系统库静态链接。感谢那些指出这一点的人。

【问题讨论】:

  • 你是静态链接的吗?
  • 如果你正确使用你的构建服务器,你有一组可执行文件,你可以通过它们的哈希值进行比较(剥离可执行文件将产生相同的结果,无论它是为交付而剥离还是在事实 - 并给出一个可比较的哈希值)。
  • 如何反汇编函数并将其与已知良好函数的反汇编进行比较?
  • 您可以在已编译和安装的二进制文件上运行ldd,以查看它将实际获取哪些动态库。但是调试器也应该告诉你。
  • "忘了说我们是静态链接的。" -- 你几乎肯定错了。

标签: gcc gdb glibc freeze getaddrinfo


【解决方案1】:

bug 12926 中的更改仅仅是一个诊断辅助。如果您需要它们,您的应用程序中有一个文件描述符竞争。结果可能更容易找到,但这并不清楚。但是与文件描述符竞争条件相关的应用程序错误肯定需要独立修复。

glibc 本身存在一个错误,可能会触发不正确的文件描述符重用,bug 15946。此修复比错误 12926 中的更改重要得多。错误 15946 可以通过多种不同方式实现,其中一种可能是错误 12926 中的挂起。

请注意,错误 15946 的更改会影响 libresolv,默认情况下它是动态链接的,即使应用程序是静态链接的。除非您覆盖 glibc 的构建设置并静态链接 libresolv,或者安排搜索路径以便拾取您提供的 libresolv 的副本,否则系统 glibc 仍然需要修复。

一旦发生下一次挂起,您可以尝试查看/proc/PID/fdlsof -p 输出。有时,文件描述符后面的文件或套接字会为您提供有关它来自何处的线索,并指出应用程序内不正确的文件描述符重用。

【讨论】:

    【解决方案2】:

    我们的 crosstool 的维护者发誓我们使用的那个有一个修补过的 glibc。

    除非您是静态链接(根据堆栈跟踪中的0x7f1fa276c17d 地址判断,您不要),您的交叉工具中的 GLIBC 版本可能不 很重要。

    但是,还有其他失败的可能性,例如我们的构建可能出于某种原因选择了不同的 glibc。

    通常您会从系统中获取 GLIBC,如果没有对 GLIBC 进行类似的修补,那么预计您仍然会遇到该错误。这就是动态链接的工作原理

    可以使用您自己的 GLIBC,与系统一并行安装。但是,这不是entirely trivial

    【讨论】:

      猜你喜欢
      • 2012-06-29
      • 2012-12-18
      • 1970-01-01
      • 1970-01-01
      • 2021-04-26
      • 2011-11-06
      • 2012-06-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多