自行卸载的Linux共享库

时间:2019-05-15 12:37:47

标签: c++ c linux shared-libraries

我的目标是将多个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调用,而又不会碰到感兴趣的应用程序本身,我会很高兴的如果您让我知道它们(对OS配置进行一些修改,例如预加载,就可以)。谢谢!

1 个答案:

答案 0 :(得分:1)

我认为您有一些误解,而您要的只是没有道理:

  

在我的库ctor代码中,我检查我所处的进程是否是我需要的并进行必要的挂接,否则,它是空操作,库只是一个负担。

以及卸载它的工作,而不是仅仅让它无所事事,而是更多

  

更新过程需要卸载-如果要更新库,则不应将其加载到长时间运行的进程中-否则它们将在替换库时崩溃(这是预期的)。

仅当您错误地覆盖库文件而不是替换文件时,才会发生这种情况。可以通过将临时文件安装到同一目录并以旧文件为目标来执行rename函数(相当于mv命令)来执行后者。

  

如果还有其他方法可以在早期阶段自动可靠地挂接glibc调用

您对“可靠”的关注听起来像是要使用此机制来强加策略/访问控制,而这种方式可能会使恶意应用程序无法解决。在库级别,这根本上不可能。您需要在某种真实的沙箱中运行它们以实现此目的(例如,通过在适当的沙箱中调用它们的包装脚本替换文件)。