如何在Linux中检测文件访问? [英] How can I detect file accesses in Linux?

查看:122
本文介绍了如何在Linux中检测文件访问?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一堆流和数据处理应用程序,我偶尔需要窥探,这意味着我需要知道他们阅读什么文件。这主要是帮助包装测试用例,但也可以在调试时使用。



有没有办法以这种方式运行可执行文件,生成这样的列表?



我有两个想法:


  1. 可以调用,该命令调用我的应用程序。沿着GDB的线。我调用GDB,给它一个路径的可执行文件和一些参数和GDB调用它为我。也许有类似的东西类似告诉我如何使用系统资源。

  2. 也许更有趣(但不必要的边路径)解决方案。

  3. 更改LD_LIBRARY_PATH以指向新库
  4. >
  5. 在编辑器中创建真实libc.so的副本并重命名fopen(nepof,可能)

  6. 我的库加载副本并调用重命名的函数必须提供fopen功能。

  7. 调用应用程序,然后调用我的代理fopen。


替代#1肯定会是最好的,但是对于如何更容易地做#2的评论也很受欢迎。

解决方案

一个选项是使用strace:

  strace -o logfile -eopen yourapp 

这将记录所有打开文件的事件,但它会强加性能惩罚。它具有易于使用的优点。



另一个选择是使用LD_PRELOAD。这对应于您的选项#2。其基本思路是做这样的事情:

 的#define _GNU_SOURCE 
&#包括LT; stdio.h中>
#include< dlfcn.h>

int open(const char * fn,int flags){
static int(* real_open)(const char * fn,int flags);

if(!real_open){
real_open = dlsym(RTLD_NEXT,open);
}

fprintf(stderr,打开的文件'%s'\ n,fn);
return real_open(fn,flags);
}

然后建立:

  gcc -fPIC -shared -ldl -o preload-example.so preload-example.c 

运行程序,例如:

  $ LD_PRELOAD = $ PWD / preload-example .so cat / dev / null 
打开文件'/ dev / null'

。少得多的开销



请注意,但是,还有其他入口点的打开文件 - 例如,fopen()函数,openat(),或许多遗留的兼容性之一入口点:

  00000000000747d0摹DF的.text 000000000000071c GLIBC_2.2.5 _IO_file_fopen 
0000000000068850克DF的.text 000000000000000a GLIBC_2.2.5 FOPEN
000000000006fe60摹DF的.text 00000000000000e2 GLIBC_2.4 open_wmemstream
00000000001209c0W¯¯DF .text区段00000000000000ec GLIBC_2.2.5 posix_openpt
0000000000069e50摹DF的.text 00000000000003fb GLIBC_2.2.5 _IO_proc_open
00000000000dcf70摹DF的.text 0000000000000021 GLIBC_2.7 __open64_2
0000000000068a10摹DF的.text 00000000000000f5 GLIBC_2.2.5 fopencookie的
000000000006a250摹DF的.text 000000000000009b GLIBC_2.2.5的popen
00000000000d7b10W¯¯DF .text区段0000000000000080 GLIBC_2.2.5 __open64
0000000000068850克DF的.text 000000000000000a GLIBC_2.2.5 _IO_fopen
00000000000d7e70W¯¯DF .text区段0000000000000020 GLIBC_2.7 __openat64_2
00000000000e1ef0摹DF的.text 000000000000005b GLIBC_2.2.5 openlog
00000000000d7b10W¯¯DF的.text 0000000000000080 GLIBC_2.2.5 open64
0000000000370c10 g执行的.bss 0000000000000008 GLIBC_PRIVATE _dl_open_hook
0000000000031680克DF的.text 0000000000000240 GLIBC_2.2.5的catopen
000000000006a250摹DF的.text 000000000000009b GLIBC_2.2.5 _IO_popen
0000000000071af0摹DF的.text 000000000000026a GLIBC_2.2.5 freopen64
00000000000723a0摹DF的.text 0000000000000183 GLIBC_2.2.5 fmemopen
00000000000a44f0W¯¯DF .text区段0000000000000088 GLIBC_2.4 fdopendir
00000000000d7e70摹DF的.text 0000000000000020 GLIBC_2.7 __openat_2
00000000000a3d00W¯¯DF .text区段0000000000000095 GLIBC_2.2.5执行opendir
00000000000dcf40摹DF的.text 0000000000000021 GLIBC_2.7 __open_2
00000000000d7b10W¯¯DF .text区段0000000000000080 GLIBC_2.2.5 __open
0000000000074370克DF的.text 00000000000000d7 GLIBC_2.2.5 _IO_file_open
0000000000070b40摹DF的.text 00000000000000d2 GLIBC_2.2.5 open_memstream
0000000000070450克DF的.text 0000000000000272 GLIBC_2.2.5 freopen函数
00000000000318c0摹DF的.text 00000000000008c4 GLIBC_PRIVATE __open_catalog
00000000000d7b10W¯¯DF .text区段0000000000000080 GLIBC_2.2.5开放
0000000000067e80摹DF的.text 0000000000000332 GLIBC_2.2.5 fdopen
000000000001e9b0摹DF的.text 00000000000003f5 GLIBC_2.2.5 iconv_open子
00000000000daca0摹DF的.text 000000000000067b GLIBC_2 .2.5 fts_open
00000000000d7d60W¯¯DF .text区段0000000000000109 GLIBC_2.4 openat
0000000000068850瓦特DF的.text 000000000000000a GLIBC_2.2.5 fopen64
00000000000d7d60W¯¯DF .text区段0000000000000109 GLIBC_2.4 openat64
00000000000d6490摹DF .text区段00000000000000b6 GLIBC_2.2.5 posix_spawn_file_actions_addopen
0000000000121b80摹DF的.text 000000000000008a GLIBC_PRIVATE __libc_dlopen_mode
0000000000067e80摹DF的.text 0000000000000332 GLIBC_2.2.5 _IO_fdopen

您可能需要连接所有这些设备的完整性 - 最起码,不是_应迷上前缀的人。尤其是,一定要挂钩的fopen单独的,从fopen()函数打开()不是由LD_PRELOAD库大呼过瘾。


$ B $ libc中内部通话b

一个类似的警告适用于与strace - 还有就是'openat'系统调用为好,并根据您的架构有可能是其他传统的系统调用为好。但没有LD_PRELOAD挂钩那么多,所以如果你不介意性能影响,它可能是一个更容易的选择。


I have a bunch of flows and data processing applications that I occasionally need to spy on, meaning I need to know what files they read. This is mostly to aid in packaging testcases, but can also be useful when debugging.

Is there a way to run the executables in such a way that produces such a list?

I have two thoughts on this:

  1. There is a command that I can invoke and that command invokes my apps. Something along the lines of GDB. I call GDB, give it a path to the executable and some arguments and GDB calls it for me. Perhaps there's something similar to telling me how system resources are used.
  2. Maybe the more interesting (but unnecessary side path) solution.

    1. create library called libc.so which implements fopen (and some others)
    2. change LD_LIBRARY_PATH to point at the new library
    3. make a copy of the real libc.so and rename fopen (nepof, perhaps) in an editor
    4. my library loads the copy and calls the renamed function as necessary to provide fopen functionality.
    5. call the app which then calls my proxy fopen.

Alternative #1 would certainly be the preferable one but comments on how to do #2 more easily are welcome too.

解决方案

One option is to use strace:

strace -o logfile -eopen yourapp

This will log all file-open events, but it will impose a performance penalty that may be significant. It has the advantage of being easy to use however.

Another option is to use LD_PRELOAD. This corresponds to your option #2. The basic idea is to do something like this:

#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>

int open(const char *fn, int flags) {
    static int (*real_open)(const char *fn, int flags);

    if (!real_open) {
    	real_open = dlsym(RTLD_NEXT, "open");
    }

    fprintf(stderr, "opened file '%s'\n", fn);
    return real_open(fn, flags);
}

Then build with:

gcc -fPIC -shared -ldl -o preload-example.so preload-example.c

And run your program with eg:

$ LD_PRELOAD=$PWD/preload-example.so cat /dev/null
opened file '/dev/null'

This has much less overhead.

Note, however, that there are other entry points for opening files - eg, fopen(), openat(), or one of the many legacy compatibility entry points:

00000000000747d0 g    DF .text      000000000000071c  GLIBC_2.2.5 _IO_file_fopen
0000000000068850 g    DF .text      000000000000000a  GLIBC_2.2.5 fopen
000000000006fe60 g    DF .text      00000000000000e2  GLIBC_2.4   open_wmemstream
00000000001209c0  w   DF .text      00000000000000ec  GLIBC_2.2.5 posix_openpt
0000000000069e50 g    DF .text      00000000000003fb  GLIBC_2.2.5 _IO_proc_open
00000000000dcf70 g    DF .text      0000000000000021  GLIBC_2.7   __open64_2
0000000000068a10 g    DF .text      00000000000000f5  GLIBC_2.2.5 fopencookie
000000000006a250 g    DF .text      000000000000009b  GLIBC_2.2.5 popen
00000000000d7b10  w   DF .text      0000000000000080  GLIBC_2.2.5 __open64
0000000000068850 g    DF .text      000000000000000a  GLIBC_2.2.5 _IO_fopen
00000000000d7e70  w   DF .text      0000000000000020  GLIBC_2.7   __openat64_2
00000000000e1ef0 g    DF .text      000000000000005b  GLIBC_2.2.5 openlog
00000000000d7b10  w   DF .text      0000000000000080  GLIBC_2.2.5 open64
0000000000370c10 g    DO .bss       0000000000000008  GLIBC_PRIVATE _dl_open_hook
0000000000031680 g    DF .text      0000000000000240  GLIBC_2.2.5 catopen
000000000006a250 g    DF .text      000000000000009b  GLIBC_2.2.5 _IO_popen
0000000000071af0 g    DF .text      000000000000026a  GLIBC_2.2.5 freopen64
00000000000723a0 g    DF .text      0000000000000183  GLIBC_2.2.5 fmemopen
00000000000a44f0  w   DF .text      0000000000000088  GLIBC_2.4   fdopendir
00000000000d7e70 g    DF .text      0000000000000020  GLIBC_2.7   __openat_2
00000000000a3d00  w   DF .text      0000000000000095  GLIBC_2.2.5 opendir
00000000000dcf40 g    DF .text      0000000000000021  GLIBC_2.7   __open_2
00000000000d7b10  w   DF .text      0000000000000080  GLIBC_2.2.5 __open
0000000000074370 g    DF .text      00000000000000d7  GLIBC_2.2.5 _IO_file_open
0000000000070b40 g    DF .text      00000000000000d2  GLIBC_2.2.5 open_memstream
0000000000070450 g    DF .text      0000000000000272  GLIBC_2.2.5 freopen
00000000000318c0 g    DF .text      00000000000008c4  GLIBC_PRIVATE __open_catalog
00000000000d7b10  w   DF .text      0000000000000080  GLIBC_2.2.5 open
0000000000067e80 g    DF .text      0000000000000332  GLIBC_2.2.5 fdopen
000000000001e9b0 g    DF .text      00000000000003f5  GLIBC_2.2.5 iconv_open
00000000000daca0 g    DF .text      000000000000067b  GLIBC_2.2.5 fts_open
00000000000d7d60  w   DF .text      0000000000000109  GLIBC_2.4   openat
0000000000068850  w   DF .text      000000000000000a  GLIBC_2.2.5 fopen64
00000000000d7d60  w   DF .text      0000000000000109  GLIBC_2.4   openat64
00000000000d6490 g    DF .text      00000000000000b6  GLIBC_2.2.5 posix_spawn_file_actions_addopen
0000000000121b80 g    DF .text      000000000000008a  GLIBC_PRIVATE __libc_dlopen_mode
0000000000067e80 g    DF .text      0000000000000332  GLIBC_2.2.5 _IO_fdopen

You may need to hook all of these for completeness - at the very least, the ones not prefixed with _ should be hooked. In particular, be sure to hook fopen seperately, as the libc-internal call from fopen() to open() is not hooked by a LD_PRELOAD library.

A similar caveat applies to strace - there is the 'openat' syscall as well, and depending on your architecture there may be other legacy syscalls as well. But not as many as with LD_PRELOAD hooks, so if you don't mind the performance hit, it may be an easier option.

这篇关于如何在Linux中检测文件访问?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆