我正在尝试使用以下库openat()
拦截comm.c
次调用。这是非常标准的最小例子,没什么特别之处。我用
>gcc -shared -Wall -fPIC -Wl,-init,init comm.c -o comm.so
我正在粘贴这个标准的最小例子来表明,我想,我知道自己在做什么。
#define _GNU_SOURCE
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
typedef int (*openat_type)(int, const char *, int, ...);
static openat_type g_orig_openat;
void init() {
g_orig_openat = (openat_type)dlsym(RTLD_NEXT,"openat");
}
int openat(int dirfd, const char* pathname, int flags, ...) {
int fd;
va_list ap;
if (flags & (O_CREAT)) {
va_start(ap, flags);
fd = g_orig_openat(dirfd, pathname, flags, va_arg(ap, mode_t));
}
else
fd = g_orig_openat(dirfd, pathname, flags);
printf("openat dirfd %d pathname %s\n", dirfd, pathname);
return fd;
}
我正在运行tar
命令,这是一个最小的示例,将包含单个文件foobar
的存档解压缩到预先存在的子目录dir
:
>strace -f tar xf foobar.tar -C dir 2>&1 | grep openat
openat(AT_FDCWD, "dir", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
openat(4, "foobar", O_WRONLY|O_CREAT|O_EXCL|O_NOCTTY|O_NONBLOCK|O_CLOEXEC, 0600) = -1 EEXIST (File exists)
openat(4, "foobar", O_WRONLY|O_CREAT|O_EXCL|O_NOCTTY|O_NONBLOCK|O_CLOEXEC, 0600) = 5
然而,
>LD_PRELOAD=./comm.so tar xf foobar.tar -C dir
openat dirfd 4 pathname foobar
openat dirfd 4 pathname foobar
好的,我知道如何处理这个 - 我以前做过这个 - 这种差异的原因是openat()
显示的系统调用strace
不是由openat()
完成的同名用户函数tar
。要找出其他用户函数是什么,可以获取源代码,重建它们并查找。
所以,我得到了>$(which tar) --version
tar (GNU tar) 1.26
的来源:
tar
我得到了tar
1.26个来源并自己重建了它们,而且,如果我使用我构建的二进制comm.so
而不是上面安装的二进制openat
,那么{{1}确实捕获了所有3个{{1}}来电!
这意味着没有&#34;其他用户功能&#34;。
请帮忙,这里可能会发生什么?
不,之前的问题没有回答这个问题。前面的回答简单地说,库调用可能与底层系统调用的名称不同。在这里,情况并非如此,因为我自己重新编译了相同的代码,并且没有其他库调用。
答案 0 :(得分:0)
根据所提到的讨论,openat
可能会被不同的符号或函数调用。 strace
等工具转储的系统调用是原始系统调用。它可能由用户函数或 glibc 包装。如果你想通过 LD_PRELOAD 拦截它,你需要找出那些包装器而不是 openat
。根据我的经验,您可以尝试拦截 open64
或 open
,它可以重定向到您在 openat
上观察到的 strace
。
link 是从 openat
包装 open64
的一个示例。