我正在尝试使用LD_PRELOAD
机制拦截所有使用库comm.so
调用系统调用openat
的动态加载函数。
考虑以下 /sbin/depmod
命令的使用:
#strace -f /sbin/depmod 3.10.0-693.17.1.el7.x86_64
(...)
openat(AT_FDCWD, "/lib/modules/3.10.0-693.17.1.el7.x86_64", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3
我想拦截调用此openat
系统调用的函数。
如何找出该功能是什么? openat
(可能是别名)和任何其他类似的函数都不起作用 - 没有任何内容被拦截。
我尝试使用此命令来查找我的命令正在使用哪些动态加载的函数:
#readelf -p .dynstr /sbin/depmod
这会打印出一些 .so
库,因此我递归地对它们使用了 readelf
。在递归结束时,我有以下包含 open
和 at
的函数列表:
openat
openat64
open_by_handle_at
__openat64_2
这些都不起作用 - 它们不会拦截返回文件描述符 3 的调用。
好的,那么如何找出我还需要拦截哪些其他函数呢?我是否必须一一递归地遍历 readelf 命令显示的所有函数(有很多)?
最佳答案
可以在不使用 openat
函数的情况下调用 openat
系统调用(或任何其他系统调用,请参阅 syscalls(2) 获取列表)来自标准库;可以从 ld-linux(8) 调用它(处理 LD_PRELOAD
)。在我的 Debian/Sid 系统上,动态链接器 /lib/ld-linux.so.2
正在使用 openat
系统调用(例如尝试 strace/bin/true
),当然它使用自己的 open
或 openat
函数(不是 libc.so
中的函数)。
任何系统调用都可以(原则上)通过直接机器代码(例如一些适当的SYSENTER
机器指令)或通过一些间接syscall(2)来调用。 (并且在这两种情况下都不会使用 openat
C 函数)。也许参见Linux Assembly HowTo了解更多和 Linux x86 ABI规范。
如果你想拦截所有这些(包括那些由ld-linux
完成的,这很奇怪),你需要使用ptrace(2)以类似于 strace(1) 的方式使用 PTRACE_SYSCALL
。此时您将能够获取程序计数器和调用堆栈。
如果您关心以下文件和文件描述符,另请考虑 inotify(7)设施。
如果您使用gdb
(在没有DWARF调试信息的程序上使用它可能会很痛苦),您可以 use catch syscall
(在 gdb
中使用 ptrace PTRACE_SYSCALL
的方法)找出(并且可能“中断”)每个原始系统调用。
顺便说一句,可能有一些C standard libraries使用 openat
系统调用(或在其他地方使用 openat
)来实现他们的 open
C 函数。通过研究特定 libc.so
的源代码进行检查(可能是 GNU glibc ,也可能是 musl-libc )。
关于linux - 如何找出LD_PRELOAD要拦截哪些函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49314057/