Linux,共享库使用主程序中的函数而不是其他共享库

Posted

技术标签:

【中文标题】Linux,共享库使用主程序中的函数而不是其他共享库【英文标题】:Linux, Shared library uses functions from main program instead of other shared libraries 【发布时间】:2014-10-09 06:32:40 【问题描述】:

我正在构建一个从应用程序(我无法控制)加载的共享库。我的库使用其他共享库,而这些共享库又使用其他共享库,复杂但并不罕见。

问题在于主应用程序的函数存在于链中更靠后的一个库中,更具体地说,openLDAP 又使用 openSSL 函数:

Main app->My library->openLDAP libraries->openSSL libraries

我的猜测是,主应用程序正在通过静态链接或简单的源代码复制/粘贴来实现openSSL

我的问题是:我可以控制 openLDAP 使用我的库中的哪些函数,还是必须重新编译 openLDAP 并与 openSSL 建立静态链接?

由于openSSL 因安全问题而经常更新,因此如果不需要,我不想要它的静态副本。以及为什么要重新分发 openLDAP 的专有副本,因为它是大多数分发包的一部分...

【问题讨论】:

我使用 Mozilla NSS 而不是 openSSL 构建了 openLDAP。这样我就不会做任何尴尬的事情并尝试解决别人的错误。 【参考方案1】:

现在您所拥有的是可执行文件,它覆盖了系统默认选择的 OpenSSL 库。这样做是在可执行文件的权利范围内,您无法真正阻止它。

在您的库中静态链接 OpenSSL 也可能不是真正的解决方案。一方面,如果可执行文件确实是使用不同的版本怎么办?另一方面,如果 OpenSSL 有一些全局变量怎么办?现在您将在同一个进程中拥有该库的两个副本,这不是一个好主意,可能会导致错误。

对我来说,我们在 Linux 上的最佳答案是不要将这类事情视为问题。如果可执行文件加载了错误版本的 OpenSSL,那不是您的库的错。最多可以检查加载了哪个版本,如果已知它由于某种原因与您的库不兼容,则拒绝运行。

【讨论】:

【参考方案2】:

我的猜测是主应用程序正在实现 openSSL 通过静态链接或源代码的简单复制/粘贴。

这是错误的事情。如果应用程序开发人员在他的脚上开枪,那么您将无能为力。

应用开发者应该看到你的库依赖于 OpenSSL 库(使用 ldd 命令),那么他不应该链接OpenSSL again as staticly or copy paste its code.

如果来自 OpenSSL 的某些函数不会造成任何混乱,并且如果它们可以像任何 java 类的任何静态方法一样使用,那么只有应用程序开发人员应该冒险在应用程序中实现该代码。

【讨论】:

【参考方案3】:

解决方案是在 dlopen(3) 中使用 RTLD_DEEPBIND:

RTLD_DEEPBIND(自 glibc 2.3.4 起)

将此库中符号的查找范围放在 全球范围。这意味着一个独立的库将使用它的 自己的符号优先于同名的全局符号 包含在已加载的库中。这个标志不是 在 POSIX.1-2001 中指定。

这可能不是最好的解决方案,但在这种情况下,当进程由闭源软件创建时,它可以工作。

【讨论】:

以上是关于Linux,共享库使用主程序中的函数而不是其他共享库的主要内容,如果未能解决你的问题,请参考以下文章

Linux共享库两种加载方式简述

如何将共享库链接到Linux中的其他共享库?

Linux共享库静态库动态库详解

linux 函数库使用

如何找出共享对象的哪些函数被程序或其他库使用?

linux上动态链接期间符号的替代实现