While testing lang/sbcl, I noticed that something appears to go wrong
when linking a non-PIE executable which references environ. It looks
like the executable ends up with it's own copy of environ, different
from what libc uses.
The following program demonstrates this:
#include <stdio.h>
#include <unistd.h>
extern char **environ;
int
main()
{
char *cmd[] = {"/usr/bin/printenv", "USER", NULL};
char *fakeenv[] = {"USER=nonexistent", NULL};
environ = fakeenv;
execv(cmd[0], cmd);
return 1;
}
$ cc -o badenv-pie badenv.c && ./badenv-pie
nonexistent
$ cc -fno-pie -Wl,-nopie -o badenv-nopie badenv.c && ./badenv-nopie
joshe
It looks like what's happened is the linker has allocated a copy of
environ in the BSS, separate from what libc is using:
$ objdump -t badenv-pie | grep environ
0000000000000000 O *UND* 0000000000000008 environ
$ objdump -t badenv-nopie | grep environ
0000000000601000 w O .bss 0000000000000008 environ