为什么LD_PRELOAD不能用于Python?

使用Python的open()函数中断在第一次调用之后似乎不起作用。 我怀疑Python正在做一些初始化,或者暂时绕过我的function。

open招募显然很受欢迎:

 $ cat a hi $ LD_PRELOAD=./libinterpose_python.so cat a sandbox_init() open() hi 

这在Python初始化过程中会发生一次:

 $ LD_PRELOAD=./libinterpose_python.so python sandbox_init() Python 2.7.2 (default, Jun 12 2011, 20:20:34) [GCC 4.6.1] on linux2 Type "help", "copyright", "credits" or "license" for more information. open() >>> sandbox_fini() 

在这里它根本不会发生,并且没有错误指出文件句柄被删除了写权限:

 $ LD_PRELOAD=./libinterpose_python.so python3 -c 'b = open("a", "w"); b.write("hi\n"); b.flush()' sandbox_init() sandbox_fini() 

代码在这里 。 使用make -f Makefile.interpose_python构build。

这里给出一个完整的解决scheme。

有open()和open64()函数,你可能需要重新定义两者。

你应该能够找到你的python进程实际上是通过在strace下运行它(可能没有你的预加载)。

我的python3.1(在AMD64上)似乎使用open

 axa@ares:~$ strace python3.1 -c 'open("a","r+")' ... open("a", O_RDWR) = -1 ENOENT (No such file or directory) 

原来有一个open64()函数:

 $ objdump -T /lib32/libc.so.6 | grep '\bopen' 00064f10 g DF .text 000000fc GLIBC_2.4 open_wmemstream 000cc010 g DF .text 0000007b GLIBC_2.0 openlog 000bf6d0 w DF .text 000000b6 GLIBC_2.1 open64 00094460 w DF .text 00000055 GLIBC_2.0 opendir 0005f9b0 g DF .text 000000d9 GLIBC_2.0 open_memstream 000bf650 w DF .text 0000007a GLIBC_2.0 open 000bf980 w DF .text 00000081 GLIBC_2.4 openat 000bfb90 w DF .text 00000081 GLIBC_2.4 openat64 

open64()函数是大文件扩展名的一部分,相当于用O_LARGEFILE标志调用open()。

运行示例代码与open64部分取消注释给出:

 $ LD_PRELOAD=./libinterpose_python.so python3 -c 'b = open("a", "w"); b.write("hi\n"); b.flush()' sandbox_init() open64() open64() open64() Traceback (most recent call last): File "<string>", line 1, in <module> open64() open64() open64() open64() open64() open64() open64() IOError: [Errno 9] Bad file descriptor sandbox_fini() 

这清楚地显示了Python的所有open调用,以及由于写入标志被从调用中剥离而导致的几个传播错误。