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

Compare with Current View Page History

« Previous Version 77 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 an argument; rather, it inserts a pointer to the string into the environment array. If a pointer to a buffer of automatic storage duration is supplied as an argument to putenv(), the memory allocated for that buffer 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.

The actual problem occurs when passing a pointer to an automatic variable to putenv(). An automatic pointer to a static buffer would work as intended.

Non-Compliant Code Example

In this non-compliant code example, a pointer to a buffer of automatic storage duration is used as an argument to putenv() [[Dowd 06]]. 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. Declare objects with appropriate storage durations.

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

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

  return putenv(env);
}

Compliant Solution (putenv())

This compliant solution uses putenv().

int func(char const *var) {
  static char *oldenv;
  char const *env_format = "TEST=%s";
  size_t const len = strlen(var) + strlen(env_format);
  char *env = (char *) malloc(len);
  if (env == NULL) {
    return -1;
  }
  int rc = snprintf(env, len, env_format, var);
  if (rc < 0 || (size_t)rc >= len) {
    /* Handle Error */
  }
  if (putenv(env) != 0) {
    free(env);
    return -1;
  }
  if (oldenv != NULL)
    free(oldenv); /* avoid memory leak */
  oldenv = env;
  return 0;
}

The POSIX setenv() function is preferred over this function [[Open Group 04]].

Compliant Solution (setenv())

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

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

Using setenv() is easier, and consequently less error prone, than using (putenv()).

Risk Assessment

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

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

POS34-C

high

unlikely

medium

P6

L2

Automated Detection

Fortify SCA Version 5.0 with CERT C Rule Pack is able to detect violations of this rule.

Compass/ROSE can detect violations of this rule.

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

References

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


POS33-C. Do not use vfork()      50. POSIX (POS)      

  • No labels