【问题标题】:Intercepting file operations on Linux在 Linux 上拦截文件操作
【发布时间】:2016-10-20 18:06:27
【问题描述】:

我正在开发用于渲染视觉效果和动画的云平台。我们接受各种格式的场景描述渲染它们,并将图像输出返回给用户。处理后端是Linux。有时我们会收到在 Windows 上生成的场景描述,因此我们会得到类似于“C:\path\to\file.mb”的路径。我编写了一个 Linux 共享库来拦截各种文件系统调用并将路径更改为 Linux 可以理解的“/C/path/to/file”。我使用 LD_PRELOAD 机制将我的函数插入到“真实”函数之前,并且效果很好……除非它没有。

例如这个命令:

LD_PRELOAD=/home/robert/path_fix.so 渲染 -s 1 -e 1 C:\path\to\test_scene_03_vray.ma

不会找到 test_scene_03_vray.ma。这也不起作用:

LD_PRELOAD=/home/robert/path_fix.so echo test > C:\path\to\test.txt

我一直在使用 ltrace 来确定哪些函数是通过引用路径名来调用的,但是这些示例没有显示在我的跟踪中:

ltrace -f -C -S -o ltrace.out 渲染 C:\path\to\test_scene_03_vray.ma

是否有除 ltrace 之外的工具可以让我查看调用了哪些函数调用?

这是我已经覆盖的列表:

  • 打开
  • 免费开放
  • 打开目录
  • 打开
  • 创建
  • 打开
  • 统计
  • lstat
  • fstatat
  • __lxstat
  • __xstat
  • mkdir
  • mkdirat
  • 取消链接
  • 取消链接
  • 访问
  • faccessat
  • 重命名
  • 重命名
  • 重命名2
  • chmod
  • fchmodat
  • chown
  • lchown
  • fchownat
  • 链接
  • 链接
  • name_to_handle_at
  • 阅读链接
  • readlinkat
  • 符号链接
  • 符号链接
  • rmdir
  • chdir

这里还有更多我缺少的功能吗?我试图实现所有需要

const char *文件路径

作为论据。

附带问题:这似乎已经是一个已解决的问题......是否有将 Windows 路径转换为 ​​unix 友好路径的库或其他方法?请记住,渲染应用程序是第 3 方专有二进制文件,因此我无法修改它们。

感谢您的任何建议!

【问题讨论】:

  • 名称中的\t 序列是否会导致问题?如果将名称用单引号括起来会怎样?
  • 你可能不需要像fopen()那样修改stdio函数。他们最终会调用 Unix 函数 open(),所以他们会自动调用替换函数。

标签: c linux ld-preload


【解决方案1】:

是的,还有其他功能,例如 64 位功能open64()。还有__open()等功能。

在 64 位 Centos 7 服务器上,只需 open 我得到:

nm -D /lib64/libc.so.6  | grep open
0000000000033d70 T catopen
00000000003c0b80 B _dl_open_hook
000000000006b140 T fdopen
00000000000ba4c0 W fdopendir
00000000000755d0 T fmemopen
000000000006ba00 T fopen
000000000006ba00 W fopen64
000000000006bb60 T fopencookie
0000000000073700 T freopen
0000000000074b60 T freopen64
00000000000eb7a0 T fts_open
0000000000022220 T iconv_open
000000000006b140 T _IO_fdopen
0000000000077230 T _IO_file_fopen
0000000000077180 T _IO_file_open
000000000006ba00 T _IO_fopen
000000000006d1d0 T _IO_popen
000000000006cee0 T _IO_proc_open
0000000000131580 T __libc_dlopen_mode
00000000000e82a0 W open
00000000000e82a0 W __open
00000000000ed0f0 T __open_2
00000000000e82a0 W open64
00000000000e82a0 W __open64
00000000000ed110 T __open64_2
00000000000e8330 W openat
00000000000e8410 T __openat_2
00000000000e8330 W openat64
00000000000e8410 W __openat64_2
00000000000f7860 T open_by_handle_at
00000000000340b0 T __open_catalog
00000000000b9f70 W opendir
00000000000f12b0 T openlog
0000000000073ea0 T open_memstream
00000000000731c0 T open_wmemstream
000000000006d1d0 T popen
0000000000130630 W posix_openpt
00000000000e6ec0 T posix_spawn_file_actions_addopen

例如,在 Linux 上,这段 C 代码很可能运行良好:

int fd = __open( path, O_RDONLY );

您也不会直接捕获静态链接的进程,或那些发出系统调用(例如open)的进程。

【讨论】:

    【解决方案2】:

    您可以在技术上使用 kprobes 来拦截调用,但如果文件数量不是太多或动态生成,我建议创建符号链接。它更安全、更简单。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-02
      • 2016-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-13
      • 2018-03-31
      • 2013-11-21
      相关资源
      最近更新 更多