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

4

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

问题在于主应用程序具有链中更深处库中存在的函数,更具体地说,它是openLDAP,而openLDAP又使用openSSL函数:

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

我的猜测是主要的应用程序通过静态链接或简单的源代码复制来实现openSSL。我的问题是:我可以控制openLDAP从我的库中使用哪些函数,还是必须重新编译具有静态链接到openSSLopenLDAP?由于openSSL由于安全问题经常更新,如果我没有必要,我不想静态复制它。而且openLDAP是大多数发行版包的一部分,为什么要重新分发专有的openLDAP副本...

我使用Mozilla NSS构建了openLDAP,而不是使用openSSL。这样我就不会做任何尴尬的事情,也不需要解决别人的错误。 - Tobias
3个回答

3

目前,你所拥有的是可执行文件覆盖了系统默认选择的OpenSSL库。这是可执行文件的权利,你无法阻止它。

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

对我来说,在Linux上最好的答案是不认为这种情况是一个问题。如果一个可执行文件加载了错误版本的OpenSSL,那不是你的库的错。最多,你可以检查加载的版本,如果因某种原因与你的库不兼容,则拒绝运行。


0
我的猜想是主应用程序是通过静态链接或简单的源代码复制/粘贴来实现openSSL的。
这是错误的做法。如果应用程序开发人员自己失误了,那么你就无能为力。
应用程序开发人员应该查看您的库是否依赖于OpenSSL库(使用ldd命令),然后不应将openssl重新链接为静态文件或者复制粘贴其代码。
如果OpenSSL中的某些函数不会引起任何问题,并且它们可以像任何Java类的静态方法一样使用,那么应用程序开发人员才应该冒着在应用程序中实现该代码的风险。

0
解决方案是在dlopen(3)中使用RTLD_DEEPBIND:
RTLD_DEEPBIND(自glibc 2.3.4以来) 将此库中符号的查找范围放在全局范围之前。这意味着,自包含库将优先使用其自己的符号,而不是已加载的库中包含的同名全局符号。该标志未在POSIX.1-2001中指定。
这可能不是最佳解决方案,但在由闭源软件创建进程时,在此情况下它有效。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接