QT5.9.6不要遵循rpath搜索openssl

发布于 2025-02-10 08:53:17 字数 645 浏览 0 评论 0原文


我正在基于Linux的OS上的基于QT的项目。我们使用QT5.9.6。 我们从QT获得了该日志

qt.network.ssl: Incompatible version of OpenSSL

当我们启动应用程序时,经过一些研究, ,我发现QT加载了OpenSSL的1.1版,而QT5.9.6则需要1.0.2k版本。因此,我将正确的版本的OpenSL放在我们的应用程序旁边,并相应地设置了rpath。但这是行不通的。我将尝试使用ld_library_path,并且可以使用。

我使用ld_debug = libs查看程序尝试加载动态库的位置,看来对于QT,rpath是部分使用或根本不使用的。

我已经创建了一个名为eaglejoe/qtopenssl-bug的docker映像,其中最小的示例。 为了编译示例

cmake --preset default
cmake --build build

并使用build/testqt启动程序>

某人是否在这里不完全使用rpath?
(在示例中,使用的是Runpath,但我遇到同样的问题),

谢谢您的帮助

I'm working on Qt based project on Linux based OS. We use Qt5.9.6.
When we launch our application, we've got this log from Qt

qt.network.ssl: Incompatible version of OpenSSL

After a few research I found that Qt loads the version 1.1 of openssl whereas Qt5.9.6 needs the 1.0.2k version. So I put the right version of openssl next to our application and I set the RPATH accordingly. But it does not works. I'll try with LD_LIBRARY_PATH and that works.

I used LD_DEBUG=libs to see where the program try to load the dynamic library and it appears that for Qt, the RPATH is use partially or not at all.

I've created a docker image named eaglejoe/qtopenssl-bug with a minimal example.
To compile the example launch

cmake --preset default
cmake --build build

and launch the program with build/testqt

Does someone kwow why the RPATH is not use completely here ?
(In the example it's the RUNPATH that is used but I have the same issue with a RPATH)

Thank you for your help

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

狼亦尘 2025-02-17 08:53:17

因此,QT将OPENSL库作为插件加载,而Linux上的Dynamic Linker ld.so仅考虑可执行的可执行文件和/或共享对象的restable code> code> code> dlopen ()。而且,由于QT本身对您的OpenSSL复制设置没有责任,因此不会加载它。

最好的方法是(只要您不想将QT重新编译为rpath)即可在调用任何QT函数之前手动加载OpenSSL。因此,在main()的开头中添加以下内容:

void* crypto_handle = dlopen("libcrypto.so", RTLD_NOW | RTLD_GLOBAL);
if (!crypto_handle)
    std::cerr << "error loading libcrypto.so: " << dlerror() << std::endl;
void* ssl_handle = dlopen("libssl.so", RTLD_NOW | RTLD_GLOBAL);
if (!ssl_handle)
    std::cerr << "error loading libssl.so: " << dlerror() << std::endl;

请注意,您必须在libcrypto.so之前加载libssl.so,否则,否则libssl.so不会加载,因为libssl.so在您的安装中没有自己的rpath集,因此它找不到正确的libcypto.so,除非您自己也加载了。

进一步注意:从技术上讲,您可以使用官方Sonames libssl.so.1.0.0libcrypto.so.1.0.0.0(是的正确的Sonames),但是您的QT版本是针对OpenSSL的怪异版本编译的,该版本认为其Soname具有1.0.2k作为扩展名,而不是1.0.0应该是,因此它只会通过其通用名称找到库,您必须通过其通用名称加载库(libssl.solibcrypto.so)才能使动态链接器意识到这些是别名。

如果两者都加载了这些,QT将能够工作,因为那样的动态链接器将看到相关库已经已加载到程序中,因此将重复使用它们,而无需在文件系统中寻找它们。

然后,运行您的程序将提供以下输出:

build openssl: OpenSSL 1.0.2k-fips  26 Jan 2017
 load openssl: OpenSSL 1.0.2k  26 Jan 2017

全部说:OpenSSL 1.0.2已有2。5年了。您正在使用的版本,1.0.2k甚至更老,是从5。5年(!)以前。从那以后,OpenSSL中已经解决了一些安全问题,并且编写依赖于网络通信的过时软件的新代码的错误主意确实是一个坏主意。

请,请使用OpenSL 1.1,该1.1仍得到支持,直到明年9月。自5.12起,QT对此有所支持。根据我的经验,从5.9到5.12的升级完全没有痛苦。尽管理想情况下,我建议新代码应该使用QT6。

(不幸的是,即使QT6也没有与openssl 3.0一起工作尽快更改。)

So the thing is, Qt loads the OpenSSL library as a plugin, and the dynamic linker ld.so on Linux only takes into account the rpath of the executable and/or shared object that calls dlopen(). And because Qt itself doesn't have the rpath for your OpenSSL copy set, it won't load it.

The best way around that is (as long as you don't want to recompile Qt yourself with that rpath) to load OpenSSL manually before invoking any Qt function. So add the following to your code at the beginning of main():

void* crypto_handle = dlopen("libcrypto.so", RTLD_NOW | RTLD_GLOBAL);
if (!crypto_handle)
    std::cerr << "error loading libcrypto.so: " << dlerror() << std::endl;
void* ssl_handle = dlopen("libssl.so", RTLD_NOW | RTLD_GLOBAL);
if (!ssl_handle)
    std::cerr << "error loading libssl.so: " << dlerror() << std::endl;

Note that you must load libcrypto.so before libssl.so, otherwise libssl.so won't load, because libssl.so in your installation doesn't have an rpath set for itself, so it won't find the correct libcypto.so unless you load that yourself as well.

Further note: technically you could use the official SONAMEs libssl.so.1.0.0 and libcrypto.so.1.0.0 (yes, even for 1.0.2 those are the correct SONAMEs), but your Qt version is compiled against a weird version of OpenSSL that thinks its SONAME has 1.0.2k as the extension, not 1.0.0 as it should be, so it will only find the libraries by their generic names, and you have to load the libraries by their generic names (libssl.so, libcrypto.so) to make the dynamic linker aware that these are aliases.

If both of these are loaded, Qt will be able to work, because then the dynamic linker will see that the libraries in question have already been loaded into the program, and will hence reuse them, without looking for them in the filesystem.

Running your program will then give the following output:

build openssl: OpenSSL 1.0.2k-fips  26 Jan 2017
 load openssl: OpenSSL 1.0.2k  26 Jan 2017

That all said: OpenSSL 1.0.2 has not been supported for 2.5 years. And the version you're using, 1.0.2k is even older, that's from 5.5 years (!) ago. There are several security issues that have been fixed in OpenSSL since, and it is a really bad idea to write new code that relies on such outdated software when it comes to network communication.

Please, please use OpenSSL 1.1, which is still supported until September of next year. Qt has support for that since 5.12. From my experience the upgrade from 5.9 to 5.12 was completely painless. Though ideally I'd suggest that new code should use Qt6.

(Unfortunately not even Qt6 appears to work with OpenSSL 3.0 yet, but hopefully that'll change soon.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文