gpt4 book ai didi

c++ - dlsym() + RTLD_NEXT 在 Ubuntu 20.04 上无法正常工作

转载 作者:行者123 更新时间:2023-12-05 01:58:57 38 4
gpt4 key购买 nike

当使用 dlsym() 调用时,我在 Ubuntu 20.04 (gcc v 9.3.0) 上遇到了一个奇怪的运行时行为。

请看下面一个简单的例子:

  • 文件test.cpp:
#include <iostream>
#include <dlfcn.h>
#include <execinfo.h>
#include <typeinfo>
#include <string>
#include <memory>
#include <cxxabi.h>
#include <cstdlib>

extern "C"
{
void __cxa_throw(void *ex, void *info, void (*dest)(void *))
{
std::cout << "__cxa_throw() invoked \n";

static void (*const rethrow)(void *, void *, void (*)(void *)) __attribute__((noreturn))
= (void (*)(void *, void *, void (*)(void *)))dlsym(RTLD_NEXT, "__cxa_throw");

std::cout << "addr in lib=" << &rethrow << "\n";

rethrow(ex, info, dest);

std::terminate();
}
}

  • 文件 main.cpp:
#include <iostream>

void foo()
{
throw std::runtime_error("error");
}

int main()
{
foo();
return 0;
}

按如下方式构建这 2 个文件:

g++ -fPIC -std=c++17 test.cpp -g -c -o test.o
g++ -shared ./test.o -o libtest.so
g++ main.cpp -std=c++17 -g -pedantic -L./ -ltest -ldl

将 ldd 馈送到 ./a.out 得到:

ldd a.out 
linux-vdso.so.1 (0x00007ffe01186000)
/usr/local/lib/AppProtection/libAppProtection.so (0x00007f1dbd738000)
libtest.so (0x00007f1dbd733000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f1dbd708000)
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f1dbd526000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f1dbd50b000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1dbd319000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f1dbd2f4000)
libX11.so.6 => /lib/x86_64-linux-gnu/libX11.so.6 (0x00007f1dbd1b7000)
libxcb.so.1 => /lib/x86_64-linux-gnu/libxcb.so.1 (0x00007f1dbd18d000)
libXi.so.6 => /lib/x86_64-linux-gnu/libXi.so.6 (0x00007f1dbd17b000)
/lib64/ld-linux-x86-64.so.2 (0x00007f1dbd964000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f1dbd02c000)
libXau.so.6 => /lib/x86_64-linux-gnu/libXau.so.6 (0x00007f1dbd024000)
libXdmcp.so.6 => /lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007f1dbd01c000)
libXext.so.6 => /lib/x86_64-linux-gnu/libXext.so.6 (0x00007f1dbd007000)
libbsd.so.0 => /lib/x86_64-linux-gnu/libbsd.so.0 (0x00007f1dbcfed000)

我们可以看到libtest.solibstdc++.so之前被解析。我期望这段代码应该如何工作:

  • __cxa_throw() 在 2 个共享库中定义:libtest.solibstdc++.so
  • foo() 调用中抛出异常时,__cxa_throwlibtest.so 解析并调用。
  • 调用 dlsym(RTLD_NEXT, "__cxa_throw"); 在共享库列表中进一步查找 __cxa_throw,在 libstdc++.so 中找到并调用。

这在除 Ubuntu 20.04 以外的所有平台上都按预期工作,其中 rethrow 引用 libtest.so 中的 __cxa_throw(但不是 libstc++.so) 从而导致无限递归。

请协助,因为我对运行时行为感到困惑。

最佳答案

Citrix ICA 客户端的“应用程序保护”组件安装库 /usr/local/lib/AppProtection/libAppProtection.so 并将其添加到 /etc/ld .so.preload,导致它被加载到每个动态链接的进程中。除此之外,该库用它自己的函数替换了 dlsym 函数。 (如果您好奇这为什么不总是通过进入无限循环来破坏一切,请参阅 How can I intercept dlsym calls using LD_PRELOAD? 。实际上,Citrix 的代码似乎是直接从该答案中复制和粘贴的。)问题是,自从RTLD_NEXT 取决于能够检查返回地址,需要特别注意避免在挂接 dlsym 时破坏它,而他们没有特别注意。结果,RTLD_NEXT 将在 libAppProtection.so 之后的下一个库中查找符号,而不是在您的代码之后的下一个库中查找符号,这正是您运行的问题进入。

这里有一些关于如何处理它的选择:

  • 向 Citrix 支持部门投诉,直到他们修复有问题的库
  • sudo apt-get purge icaclient(之后可选择重新安装,但是 choosing no when asked about the app protection component)
  • 修改您的程序以从 libdl.so 加载真正的 dlsym,然后将其用于任何使用 RTLD_NEXT
  • 的调用

关于c++ - dlsym() + RTLD_NEXT 在 Ubuntu 20.04 上无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68128568/

38 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com