即使在 unsetenv("LD_PRELOAD") 之后,LD_PRELOAD 也会影响新的子进程

2023-11-26

我的代码如下:preload.c,内容如下:

#include <stdio.h>
#include <stdlib.h>

int  __attribute__((constructor))  main_init(void)
{
    printf("Unsetting LD_PRELOAD: %x\n",unsetenv("LD_PRELOAD"));
    FILE *fp = popen("ls", "r");
    pclose(fp);
}

然后在 shell 中(小心执行第二个命令!!):

    gcc preload.c -shared -Wl,-soname,mylib -o mylib.so -fPIC
    LD_PRELOAD=./mylib.so bash

!!!请小心最后一个命令,它会导致分叉“sh -c ls”的无限循环。 2 秒后用 ^C 停止它(或者更好的 ^Z 然后看 ps)。

更多信息

  1. 这个问题在某种程度上与 bash 有关;作为用户运行的命令,或者作为 popen 执行的 bash。
  2. 其他关键因素:1)从预加载的库执行popen,2)可能需要在库的初始化部分执行popen。
  3. 如果你使用:

    LD_DEBUG=all LD_DEBUG_OUTPUT=/tmp/ld-debug LD_PRELOAD=./mylib.so bash
    

    您将获得许多名为 /tmp/ld-debug.* 的 ld-debug 文件,而不是最后一个命令。每个分叉进程一个。在所有这些文件中,您将看到符号首先在 mylib.so 中搜索,即使 LD_PRELOAD 已从环境中删除。


edit:所以问题实际上是:你怎么不能取消设置LD_PRELOAD可靠地使用预加载main_init()从内部bash.

原因是execve,以您的名字命名popen,从(可能)获取环境

extern char **environ;

这是指向您的环境的一些全局状态变量。unsetenv()通常会修改您的环境,因此会对内容产生影响**environ.

If bash尝试对环境做一些特殊的事情(嗯......会吗?成为一个外壳?)那么你可能会遇到麻烦。

显然,bash超载unsetenv()甚至之前main_init()。将示例代码更改为:

extern char**environ;

int  __attribute__((constructor))  main_init(void)
{
int i;
printf("Unsetting LD_PRELOAD: %x\n",unsetenv("LD_PRELOAD"));
printf("LD_PRELOAD: \"%s\"\n",getenv("LD_PRELOAD"));
printf("Environ: %lx\n",environ);
printf("unsetenv: %lx\n",unsetenv);
for (i=0;environ[i];i++ ) printf("env: %s\n",environ[i]);
fflush(stdout);
FILE *fp = popen("ls", "r");
pclose(fp);
}

显示了问题。正常运行时(运行cat, ls等)我得到这个版本的 unsetenv:

unsetenv: 7f4c78fd5290
unsetenv: 7f1127317290
unsetenv: 7f1ab63a2290

然而,运行bash or sh:

unsetenv: 46d170

所以你有它。bash你被骗了;-)

所以只需使用你自己的就地修改环境unsetenv, 作用于**environ:

for (i=0;environ[i];i++ )
{
    if ( strstr(environ[i],"LD_PRELOAD=") )
    {
         printf("hacking out LD_PRELOAD from environ[%d]\n",i);
         environ[i][0] = 'D';
    }
}

可以看出它在工作strace:

execve("/bin/sh", ["sh", "-c", "ls"], [... "DD_PRELOAD=mylib.so" ...]) = 0

Q.E.D.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

即使在 unsetenv("LD_PRELOAD") 之后,LD_PRELOAD 也会影响新的子进程 的相关文章

随机推荐

  • 背景页面/脚本和弹出页面有什么区别?

    背景页面和弹出页面有什么区别 什么是内容脚本 Chrome 扩展程序有许多看起来相似的不同术语 我将尽力澄清这些术语 背景页面 脚本 基本上是在应用程序后台运行的页面 ManifestV2 或服务工作线程 ManifestV3 不显示任何内
  • 如何在 preg_split() 的结果中包含分割分隔符?

    我有一个简单的模式 可以将文本分成句点 text preg split text 但我想包括 or 在数组项的末尾 也就是说 现在是 好消息 大家好 我有 array good news everyone 但我想要 array good n
  • 包装器、过滤器和 Servlet

    由于我是 Servlet 编程新手 因此我可能会问一个基本问题 我正在编写一个应用程序 其中过滤器从 servlet 获取响应 并用它进行一些计算 我发现我需要一个包装类来捕获响应 我现在的问题是为什么需要包装器 提前致谢 1 让我们首先了
  • ESP在汇编中是什么意思? [复制]

    这个问题在这里已经有答案了 ESP stack pointer 什么是E站在这里 UPDATE 64 位的 RSP 什么是R意思是这里 E代表Extended 随着32位80386处理器的出现 16位通用寄存器 基址寄存器 索引寄存器 指令
  • OpenCSV 将 csv 转换为嵌套 bean

    我们正在使用 OpenCSV csv 如下 id fname lname address line1 address line2 这些豆子是 Person String id String lname String fname Addres
  • Android 上 Assets 文件夹中的 InputStream 返回空

    我没有遇到任何例外 但是当我跑步时 InputStream deckFile context getAssets open cards txt 然后 deckFile read 返回 1 该文件位于正确的文件夹中 并且不为空 这应该是世界上
  • R list.files(my_working_directory) 显示没有文件,但我知道它们在那里。怎么修?

    我正在尝试使用外部硬盘驱动器中的目录作为工作目录来使用 R 我可以将工作目录设置到我想要的位置 但是当我使用list filesR什么也看不到 我也无法使用read delim加载文件 例如 gt rm list ls gt WD lt V
  • Python 2 __getattr__ 最大递归深度

    例如我使用这个代码 class A object def init self self dict1 A 3 B self A def getattr self key if key in self dict1 return self dic
  • from __future__ 导入注释

    Python 文档 future 在 python 文档中关于 future 下面有一张表显示 注释 3 7 0b1 中 可选 和 4 0 中 强制 但我仍然可以在 3 8 2 中使用注释 而无需导入注释 那它有什么用呢 gt gt gt
  • 循环平铺。如何选择块大小?

    我正在尝试学习循环优化 我发现循环平铺有助于使数组循环更快 我尝试使用下面给出的两个代码块 有和没有循环阻塞 并测量两者所花费的时间 大多数时候我没有发现显着差异 我测试了不同的块大小 但我不确定如何选择块大小 如果我的方向错误 请帮助我
  • TFS:查找更改集之间受影响的文件

    我们正在使用 Team Foundation Server 2012 我们有一个人于 2016 年 8 月 9 日在变更集 13646 中提交了 97 个文件 不包括设计器和资源文件 十 10 天后 即 2016 年 8 月 18 日 他将
  • 如何在不赋值​​的情况下声明静态可变变量?

    我尝试了以下方法 struct mbuf cacheline mut u64 great amount of rows follows below static mut arr mbuf 32 Q1 my main aim somethin
  • 如何在单个结果集中列出 SQL Server 中所有数据库中的所有表?

    我正在寻找 T SQL 代码来列出 SQL Server 中所有数据库中的所有表 至少在 SS2005 和 SS2008 中 如果也适用于 SS2000 就好了 然而 问题是我想要一个单一结果集 这排除了其他方面的优秀答案皮纳尔 戴夫 sp
  • Vuex 和 Websocket

    目前我正在使用 VueJS 2 而且我对它还很陌生 现在我得到了其他一些人的帮助 但我仍然陷入困境 这是我想要实现的目标 示例 与我想要的紧密相关 我有一个监听 WebSocket 的 NodeJS 应用程序 应用程序通过 WebSocke
  • 从前端 javascript 打印?

    是否可以在浏览器中使用带有javascript的打印机打印一些东西 我想打印收据号 所以如果可能的话 最快的打印机是什么 这样当用户单击按钮时它就会打印出来 例如 小纸上写着 1234 Thanks 您无法直接从 Javascript 访问
  • mupdf 库的 Proguard 问题

    在我尝试构建发行版本之前 我的应用程序运行良好 我收到以下错误消息 java lang NoSuchFieldError 没有名称 globals 签名 J 的字段 在 Lcom artifex mupdfdemo MuPDFCore 类中
  • SendKeys 到非活动应用程序

    我试图弄清楚如何使我的 C 应用程序将密钥发送到另一个应用程序窗口 而不需要关注它 我有一个单词列表和 3 个记事本文件 想象一下 我按顺序打开了所有 3 个记事本窗口 我的程序将获取列表框中的第一个单词并将其写入第一个记事本窗口中 第二个
  • AngularJS 查询生成器类似于 http://redquerybuilder.appspot.com/ [关闭]

    Closed 这个问题需要多问focused 目前不接受答案 我正在尝试仅使用 AngularJS 创建一个完整的查询生成器 我见过http redquerybuilder appspot com 这很棒 但不适用于 AngularJS 我
  • Scala 中缀类型的现实示例

    我发现了一种有趣的语法东西 它被称为Infix type Example class M T U new Int M String 现在我正在从一些流行的框架或库中寻找这种类型的示例 我在哪里可以找到它们 有什么建议么 无形图书馆 有一堆
  • 即使在 unsetenv("LD_PRELOAD") 之后,LD_PRELOAD 也会影响新的子进程

    我的代码如下 preload c 内容如下 include