...
Wiki Markup |
---|
According to C99 \[[ISO/IEC 9899-1999|AA. C References#ISO/IEC 9899-1999]\]: |
Wiki Markup |
---|
In a hosted environment, the main function receives a third argument, {{char \*envp\[\]}}, that points to a |
NULL null-terminated array of pointers to {{char}}, each of which points to a string that provides information about the environment for this execution of the program. |
However, modifying the environment by using the setenv()
or putenv()
functions, or by any other means, may cause the environment memory to be reallocated, with the result that envp
now references an incorrect location. For example, when compiled with gcc-3.4.6 and run on Andrew Linux-2.6.16.29, the following code:
Code Block |
---|
extern char **environ;
int main(int argc, char *argv[], char *envp[]) {
printf("environ: %p\n", environ);
printf("envp: %p\n", envp);
setenv("MY_NEW_VAR", "new_value", 1);
puts("--Added MY_NEW_VAR--");
printf("environ: %p\n", environ);
printf("envp: %p\n", envp);
}
|
Yields:
Code Block |
---|
% ./envp-environ
environ: 0xbf8656ec
envp: 0xbf8656ec
--Added MY_NEW_VAR--
environ: 0x804a008
envp: 0xbf8656ec
|
...
Code Block |
---|
|
int main(int argc, char *argv[], char *envp[]) {
setenv("MY_NEW_VAR", "new_value", 1);
if (envp != NULL) {
for (size_t i = 0; envp[i] != NULL; i++) {
puts(envp[i]);
}
}
return 0;
}
|
Because envp
no longer points to the current environment, this program has undefined behavior.
...
Code Block |
---|
|
extern char **environ;
int main(int argc, char *argv[]) {
setenv("MY_NEW_VAR", "new_value", 1);
if (environ != NULL) {
for (size_t i = 0; environ[i] != NULL; i++) {
puts(environ[i]);
}
}
return 0;
}
|
Note: if you have a great deal of unsafe envp
code, you could save time in your remediation by aliasing. Change:
...
Code Block |
---|
extern char **environ;
#define envp environ
main(int argc, char *argv[])
|
...