如何在共享库中使用popen()?

时间:2016-12-23 19:05:41

标签: c debian shared-libraries popen preload

当尝试在共享库中使用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()。

任何帮助将不胜感激。谢谢!

1 个答案:

答案 0 :(得分:3)

你在这里做叉子炸弹吗? LD_PRELOAD中的构造函数将导致/usr/bin/id永久执行(因为每个新实例都会预先加载您的库),很可能会停止您的计算机。在开始教育之前你应该unsetenv