You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 46 Next »

The POSIX function putenv() is used to set environment variable values. The putenv() function does not create a copy of the string supplied to it as a parameter, rather it inserts a pointer to the string into the environment array. If an automatic variable is supplied as a parameter to putenv(), the memory allocated for that variable may be overwritten when the containing function returns and stack memory is recycled. This behavior is noted in the Open Group Base Specifications Issue 6 [[Open Group 04]]:

A potential error is to call putenv() with an automatic variable as the argument, then return from the calling function while string is still part of the environment.

Non-Compliant Code Example

In this example taken from Dowd, an automatic variable is used as an argument to putenv(). The TEST environment variable may take on an unintended value if it is accessed once func() has returned and the stack frame containing env has been recycled.

Note that this example also violates rule [[DCL30-C]].

int func(char *var) {
  char env[1024];

  if (snprintf(env, sizeof(env),"TEST=%s", var) < 0) {
    /* Handle Error */
  }

  return putenv(env);
}

Implementation Details

The putenv() function is not required to be reentrant, and the one in libc4, libc5 and glibc2.0 is not, but the glibc2.1 version is.

Description for libc4, libc5, glibc: If the argument string is of the form name, and does not contain an `=' character, then the variable name is removed from the environment. If putenv() has to allocate a new array environ, and the previous array was also allocated by putenv(), then it will be freed. In no case will the old storage associated to the environment variable itself be freed.

The libc4 and libc5 and glibc 2.1.2 versions conform to SUSv2: the pointer string given to putenv() is used. In particular, this string becomes part of the environment; changing it later will change the environment. (Thus, it is an error is to call putenv() with an automatic variable as the argument, then return from the calling function while string is still part of the environment.) However, glibc 2.0-2.1.1 differs: a copy of the string is used. On the one hand this causes a memory leak, and on the other hand it violates SUSv2. This has been fixed in glibc2.1.2.

The BSD4.4 version, like glibc 2.0, uses a copy.

SUSv2 removes the `const' from the prototype, and so does glibc 2.1.3.

The FreeBSD implementation of putenv() copies the value of the provided string and that old values remain accessible indefinitely. As a result, successive calls to putenv() assigning a differently sized value to the same name results in a memory leak.

Compliant Solution

The setenv() function allocates heap memory for environment variables. This eliminates the possibility of accessing volatile, stack memory.

int func(char *var) {
  return setenv("TEST",var,1);
}

Risk Assessment

Using an automatic variable as an argument to putenv() may cause that variable to take on an unintended value. Depending on how and when that variable is used, this can cause unexpected program behavior, or possibly allow an attacker to run arbitrary code.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

ENV34-C

3 (high)

1 (unlikely)

1 (high)

P3

L3

Examples of vulnerabilities resulting from the violation of this rule can be found on the CERT website.

References

[[Open Group 04]] The putenv() function
[[ISO/IEC 9899-1999]] Section 6.2.4, "Storage durations of objects," and Section 7.20.3, "Memory management functions"
[[Dowd]] Chapter 10, "UNIX Processes" (Confusing putenv() and setenv())
[[DCL30-C]]

  • No labels