【问题标题】:How to use popen() in a shared library?如何在共享库中使用 popen()?
【发布时间】:2016-12-23 19:05:41
【问题描述】:

当尝试在共享库中使用 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() 的情况下冻结系统。

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

【问题讨论】:

  • 我认为问题在于您的库在加载 libc 的其余部分之前已预加载,因此您无法在 init() 函数中调用这些函数。
  • @Barmar 如果他的 init() 函数链接到 libc,那么加载 libc 是否会成为预加载的一部分?
  • OP 我很确定你必须在 .c 文件之前加上 -shared -fPIC
  • 另外,您是否尝试过将init() 的内容替换为简单的printf,以便推断它可能不是popen() 破坏?
  • -shared -fPIC 之前没有更改输出。另外,是的,我已经尝试过printf 和其他 libc 函数,并且效果很好。这是我的一个更大项目的一部分,我在其中挂钩 libc 和其他共享库中的函数。孤立的这个popen 代码是有问题的(这不是我的项目引起的问题)。谢谢大家的帮助!

标签: c debian shared-libraries popen preload


【解决方案1】:

你不是在这里进行叉式轰炸吗? LD_PRELOAD 中的构造函数将导致 /usr/bin/id 永远执行自身(因为每个新实例都会预加载你的库),很可能会停止你的机器。你应该在弹出之前unsetenv

【讨论】:

  • 啊,伙计!谢谢!这就说得通了。我不知道我是怎么想的。几天来,我一直在努力解决这个问题。我觉得很傻。
  • 欢迎来到运行时检测世界;)
猜你喜欢
  • 2015-09-30
  • 2019-01-21
  • 1970-01-01
  • 2020-11-18
  • 2016-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-22
相关资源
最近更新 更多