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.