如何在共享库中使用 popen()?
How to use popen() in a shared library?
当尝试在共享库中使用 popen() 并通过 LD_PRELOAD 或 /etc/ld.so.preload 预加载它时,进程陷入无限循环并出现错误消息说无法预加载共享库,或者系统只是冻结并需要重新启动,具体取决于代码。
请注意,不作为共享库 (gcc test.c; ./a.out
) 编译将不会出现错误。
如果有帮助,我是 运行 在 VirtualBox 上全新安装 Debian:
Linux debian 3.16.0-4-586 #1 Debian 3.16.36-1+deb8u2 (2016-10-19) i686
GNU/Linux
好的,所以这个代码:
#define _GNU_SOURCE
#include <stdio.h>
__attribute__((constructor, visibility("hidden")))
void init()
{
FILE *fp = popen("/usr/bin/id", "r");
pclose(fp);
}
第一种情况的结果:
root@debian:/mnt/group/hcfrk# gcc test.c -o test.so -std=c99 -shared -fPIC
root@debian:/mnt/group/hcfrk# LD_PRELOAD=./test.so whoami
ERROR: ld.so: object './test.so' from LD_PRELOAD cannot be preloaded (cannot open shared object file): ignored.
ERROR: ld.so: object './test.so' from LD_PRELOAD cannot be preloaded (cannot open shared object file): ignored.
ERROR: ld.so: object './test.so' from LD_PRELOAD cannot be preloaded (cannot open shared object file): ignored.
ERROR: ld.so: object './test.so' from LD_PRELOAD cannot be preloaded (cannot open shared object file): ignored.
# For eternity.
此代码:
...
#include <limits.h>
...
{
FILE *fp = popen("/usr/bin/id", "r");
if(!fp)
puts("Error.\n");
char buf[PATH_MAX];
while(fgets(buf, sizeof buf, fp))
printf("%s\n", buf);
pclose(fp); // Never gets here: VM just freezes.
}
第二种情况的结果(系统卡顿)。我怀疑这是因为 while 循环没有结束并导致 pclose() 没有被调用,因为第一个代码示例也会在没有 pclose() 的情况下冻结系统。
如有任何帮助,我们将不胜感激。谢谢!
你不是在这里炸叉吗? LD_PRELOAD
中的构造函数将导致 /usr/bin/id
永远执行自身(因为每个新实例都会预加载您的库),很可能会停止您的机器。你可能应该 unsetenv
在 popening 之前。
当尝试在共享库中使用 popen() 并通过 LD_PRELOAD 或 /etc/ld.so.preload 预加载它时,进程陷入无限循环并出现错误消息说无法预加载共享库,或者系统只是冻结并需要重新启动,具体取决于代码。
请注意,不作为共享库 (gcc test.c; ./a.out
) 编译将不会出现错误。
如果有帮助,我是 运行 在 VirtualBox 上全新安装 Debian:
Linux debian 3.16.0-4-586 #1 Debian 3.16.36-1+deb8u2 (2016-10-19) i686 GNU/Linux
好的,所以这个代码:
#define _GNU_SOURCE
#include <stdio.h>
__attribute__((constructor, visibility("hidden")))
void init()
{
FILE *fp = popen("/usr/bin/id", "r");
pclose(fp);
}
第一种情况的结果:
root@debian:/mnt/group/hcfrk# gcc test.c -o test.so -std=c99 -shared -fPIC
root@debian:/mnt/group/hcfrk# LD_PRELOAD=./test.so whoami
ERROR: ld.so: object './test.so' from LD_PRELOAD cannot be preloaded (cannot open shared object file): ignored.
ERROR: ld.so: object './test.so' from LD_PRELOAD cannot be preloaded (cannot open shared object file): ignored.
ERROR: ld.so: object './test.so' from LD_PRELOAD cannot be preloaded (cannot open shared object file): ignored.
ERROR: ld.so: object './test.so' from LD_PRELOAD cannot be preloaded (cannot open shared object file): ignored.
# For eternity.
此代码:
...
#include <limits.h>
...
{
FILE *fp = popen("/usr/bin/id", "r");
if(!fp)
puts("Error.\n");
char buf[PATH_MAX];
while(fgets(buf, sizeof buf, fp))
printf("%s\n", buf);
pclose(fp); // Never gets here: VM just freezes.
}
第二种情况的结果(系统卡顿)。我怀疑这是因为 while 循环没有结束并导致 pclose() 没有被调用,因为第一个代码示例也会在没有 pclose() 的情况下冻结系统。
如有任何帮助,我们将不胜感激。谢谢!
你不是在这里炸叉吗? LD_PRELOAD
中的构造函数将导致 /usr/bin/id
永远执行自身(因为每个新实例都会预加载您的库),很可能会停止您的机器。你可能应该 unsetenv
在 popening 之前。