edit: , поэтому проблема / вопрос на самом деле заключались в следующем: почему вы не можете надежно сбросить LD_PRELOAD
, используя предварительно загруженный main_init()
из bash
.
Причина в том, что execve
, который вызывается после того, как вы popen
, отбирает у окружения (вероятно)
extern char **environ;
, которая является некоторой глобальной переменной состояния, которая указывает на вашу среду. unsetenv()
обычно изменяет вашу среду и, следовательно, влияет на содержимое **environ
.
Если 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
или 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
1048 * что и требовалось доказать *