【问题标题】:why doesn't LD_PRELOAD trick catch open() when called by fopen()?为什么 LD_PRELOAD 技巧在 fopen() 调用时不捕获 open()?
【发布时间】:2016-06-16 17:35:22
【问题描述】:

我使用LD_PRELOAD 技巧来捕获open64() 调用,我想我知道如何正确地做到这一点:使用编译自的程序foobar

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main() {
  open64("foobar.txt", 0);
  return 0;
}

如我所料,我抓住了open64

>LD_PRELOAD=$PWD/catch.so ./foobar
open64 called

但是,当open64fopen64 替换时:

#include <stdio.h>

int main() {
  fopen64("foobar.txt", "r");
  return 0;
}

现在open64 未被捕获。为什么?

如果fopen64 调用open,我确实同时拦截了openopen64,没有一个被捕获。

程序foobar 的两个版本在与strace 一起执行时都显示open 被调用,这意味着fopen64 确实在内部调用openopen64

我认为也许某些东西是静态链接的,但事实并非如此:

>ldd foobar

显示

libc.so.6 => /lib64/libc.so.6 

这是一个共享库,并且

>nm /lib64/libc.so.6

按定义显示open64fopen64(但不是fopen,这就是为什么在问题中,我使用“64”版本作为参数;也许fopen 是@987654348 的宏@ 或类似的东西,没关系,因为无论有没有 64 都会出现问题)。

【问题讨论】:

  • ltrace [sic] 和/或 LD_DEBUG=all 向您展示了两者之间的哪些区别?
  • @pilcrow 不确定你的意思...我在上面解释了所有这些,strace 显示 open(foobar.txt...(和其他不相关的东西),LD_PRELOAD 什么也没显示。跨度>
  • 有同样的问题。想知道发生了什么。

标签: linux ld-preload


【解决方案1】:

你想要ptracePTRACE_SYSCALL。这是blog on it

【讨论】:

  • 我读了这篇博文,我不确定你的意思.... 该博客描述了如何使用函数ptrace() 来实现一个简单版本的命令strace。我不需要 - 我对完整版的 strace 非常满意,我按照上面的说明使用它,它表明使用了系统调用 open。那不是我想要的。我想知道调用该系统调用的用户函数是什么,是open() 还是open64(),如果是,那为什么我不能捕捉到它。
【解决方案2】:

我认为它是这样工作的:用户空间程序调用 libc 中的库函数,而 libc 调用内核中的系统调用。使用 LD_PRELOAD 可以拦截程序和 libc 之间的 libc 调用。你不能拦截系统调用。如果 glibc 在内部调用另一个函数(例如 fopen 调用 open),则不能拦截它。

在这种情况下,最好使用ltrace,而不是使用strace,因为它显示了哪些库调用已完成。这些是您可以拦截的调用。

【讨论】:

  • 好的,如果我使用ltrace,它只是表明我的程序正在调用fopen(),仅此而已,我已经知道了。所以它根本没有帮助...fopen() 必须调用open() 或类似的,或者可能是syscall() 但这些在ltrace 中没有显示,为什么,我不确定,但它似乎没有帮助...
  • “如果 fopen 调用打开,则无法拦截”是什么意思?如果fopenlibc 中定义,那么是的,如果我使用LD_PRELOAD 加载libc,我应该能够拦截fopenfopen 正在调用什么并不重要。请发表评论。
  • “你不能拦截它”中的“它”指的是open,而不是fopen。如果fopen调用open,则无法拦截open
猜你喜欢
  • 2010-09-30
  • 2011-01-01
  • 2020-12-12
  • 1970-01-01
  • 2015-03-11
  • 2013-02-22
  • 1970-01-01
  • 1970-01-01
  • 2011-05-27
相关资源
最近更新 更多