【发布时间】:2019-05-15 12:37:46
【问题描述】:
我的目标是在位于特定路径的特定进程组中挂钩几个 glibc 函数。有多种方法可以做到这一点(gdb、strace 等)。但我需要在最早阶段自动可靠地制作它,这样我就不会错过任何一个电话。所以我决定使用LD_PRELOAD 方法。而且我需要它在没有任何用户干预的情况下自动完成,因此将LD_PRELOAD 注入环境有点脆弱,可能会被用户覆盖。所以我决定在 /etc/ld.so.preload 中指定我的库 - 这很好用。
在我的库 ctor 代码中,我检查我所在的进程是否是我需要的进程并进行必要的挂钩,否则它是无操作的,库只是一个死重。
__attribute__((constructor)) void my_lib_ctor()
{
if (is_relevant_process())
{
do_the_wiring();
}
}
该库不导出任何符号,并且默认情况下隐藏其中的所有内容(-fvisibility=hidden 编译器标志),因此任何进程对我的库没有任何真正的依赖关系。因此,如果注入到无关的进程中,它可以安全地卸载。
更新过程需要卸载 - 如果要更新库,则不应将其加载到长时间运行的进程中 - 否则它们将在库替换时崩溃(这是预期的)。感兴趣的过程是短暂的并且是由用户启动的,因此对它们的影响可以忽略不计。
问题是 - 我不知道如何安全卸载它。我在考虑dlclose,但是从库本身调用它会导致它从调用返回到已经卸载的库代码。
如果有其他方法可以自动且可靠地在早期(在应用程序的main() 执行之前)挂钩 glibc 调用而不触及感兴趣的应用程序本身,我会很高兴如果你让我知道它们(操作系统配置的轻微修改,例如预加载,是可以的)。谢谢!
【问题讨论】:
-
两阶段方法?为 LD_PRELOAD 使用一个小的、稳定的库,然后从那里加载大的。
-
另外,为什么更新库会崩溃,无论它加载了什么?运行代码保持旧文件打开,新代码获取新文件。
-
否则它们将在库替换时崩溃(这是预期的) 仅当您的更新过程覆盖现有库时。先删除吧。
-
Arkadiy,Andrew,我尝试先删除它,但它还是会导致进程崩溃
-
将新的库版本写入临时文件(在同一个磁盘上)并将其移动到正确的位置。应该没有崩溃的风险(或任何人无法加载它)。
标签: c++ c linux shared-libraries