glibc - 如何在 dlopen() 中拦截文件系统访问?

标签 glibc dlopen

我想拦截 dlopen() 内部发生的所有文件系统访问。起初,它看起来像 LD_PRELOAD-Wl,-wrap,将是可行的解决方案,但由于某些技术原因,我无法使其正常工作:

  • ld.so 在处理 LD_PRELOAD 时已经映射了它自己的符号。拦截初始加载对我来说并不重要,但 _dl_*工作函数此时已解决,因此将来的调用会通过它们。我认为 LD_PRELOAD太晚了。
  • 不知怎的malloc规避了上述问题,因为 malloc() ld.so 内部没有功能 free() , 它只是调用 memset() .
  • 文件系统 worker 功能,例如__libc_read() , 包含在 ld.so是静态的,所以我无法用 -Wl,-wrap,__libc_read 拦截它们.

  • 这可能都意味着我需要建立自己的ld.so直接从源代码而不是将其链接到包装器中。那里的挑战是libcrtld-libc是从相同的来源构建的。我知道宏IS_IN_rtld在构建 rtld-libc 时定义,但是如何保证只有一个静态数据结构的副本,同时仍然导出一个公共(public)接口(interface)函数呢? (这是一个 glibc 构建系统问题,但我还没有找到这些细节的文档。)

    有没有更好的方法进入dlopen() ?

    注意:我不能使用像 FUSE 这样的 Linux 特定解决方案。因为这是针对不支持此类事物的最小“计算节点”内核。

    最佳答案

    it would seem like LD_PRELOAD or -Wl,-wrap, would be viable solutions

    --wrap 解决方案不可能可行:它仅在(静态)链接时有效,并且您的 ld.solibc.so.6libdl.so.2 都已经链接,所以现在使用 --wrap 为时已晚。LD_PRELOAD 本来可以工作,除了 ... ld.so 认为 dlopen() 调用 open() 是一个内部实现细节。因此,它只是调用内部 __open 函数,绕过 PLT ,以及您插入 open 的能力。

    Somehow malloc circumvents the issue


    这是因为 libc 支持实现自己的 malloc 的用户(例如用于调试目的)。所以调用例如来自 callocdlopen 确实经过 PLT ,并且可以通过 LD_PRELOAD 插入。

    This might all mean that I need to build my own ld.so directly from source instead of linking it into a wrapper.


    重建后的 ld.so 会做什么?我认为您希望它调用 __libc_open (在 libc.so.6 中),但是由于显而易见的原因,这不可能起作用:首先是 ld.so open s libc.so.6 (在进程启动时)。
    您可以用对 ld.so 的调用替换为对 __open 的调用来重建 open 。这将导致 ld.so 穿过 PLT ,并将其暴露给 LD_PRELOAD 插入。
    如果你走那条路,我建议你不要用你的新副本覆盖系统 ld.so(出错并导致系统无法启动的可能性太大了)。相反,将其安装到例如/usr/local/my-ld.so ,然后将您的二进制文件与 -Wl,--dynamic-linker=/usr/local/my-ld.so 链接。
    另一种选择:运行时修补。这有点小技巧,但是您可以(一旦获得主控制权)只需扫描 .textld.so ,然后查找 CALL __open 指令。如果 ld.so 没有被剥离,那么您可以找到内部 __open 和您要修补的功能(例如 open_verify 中的 dl-load.c )。一旦你找到有趣的 CALLmprotect 包含它的页面是可写的,并修补你自己的插入器的地址(如果需要,它可以反过来调用 __libc_open ),然后 mprotect 它回来。任何 future 的 dlopen() 现在都将通过您的插入器。

    关于glibc - 如何在 dlopen() 中拦截文件系统访问?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7699583/

    上一篇:vim 设置工作目录

    下一篇:.NET ETL 流程

    相关文章:

    c - dlopen() 是否设置了 errno?

    c++ - 共享库中全局静态变量的析构函数未在 dlclose 上调用

    c - 如果 memcpy 实际上不返回任何内容,如何以 memcpy 作为第一个参数调用 memset?

    c - 将已编译的库链接到更新版本的 glibc

    c++ - 复制结构 tm

    c++ - dlopen'ing 时是否运行静态初始化(和/或其他)代码?

    android - Android ndk 上的 dlopen

    c++ - 使目标文件符号成为可执行文件中的动态符号

    c++ - stdint.h 与 C++ 不兼容?

    linux - 单个主机上的多个 glibc 库