...
In most cases, compilers warn about uninitialized variables, discussed in MSC00-C. Compile cleanly at high warning levels. In other cases, compilers will completely optimize out the uninitialized variables.
Noncompliant Code Example
...
Code Block | ||||
---|---|---|---|---|
| ||||
void f(const char *mbs) {
size_t len;
mbstate_t state;
memset(&state, 0, sizeof state);
len = mbrlen(mbs, strlen(mbs), &state);
/* ... */
}
|
Noncompliant Code Example
In this noncompliant code example, the process id, time of day, and uninitialized memory junk
is used to seed a random number generator. Although the unpredictable property of junk
is desired, the problem here is that some compilers will actually optimize out the uninitialized variable completely, resulting in a loss of desired entropy.
Code Block | ||||
---|---|---|---|---|
| ||||
struct timeval tv; unsigned long junk; gettimeofday(&tv, NULL); srandom((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk); |
While operating systems like OS X 10.6 keep the junk value, other systems like OS X 10.7 or 10.8 do not. The same code, when viewed in machine assembly, optimizes out the junk value leaving only the time and process id. In security protocols that rely on unpredictability like RSA encryption, a loss in entropy results in a less secure system.
Compliant Solution
This can be solved by using a more reliable source for random number generation. This compliant solution uses the CPU clock in addition to the Real-Time clock to seed the random number generator.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <time.h>
double cpu_time;
struct timeval tv;
unsigned long junk;
cpu_time = ((double) clock()) / CLOCKS_PER_SEC;
gettimeofday(&tv, NULL);
srandom((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk); |
Risk Assessment
Accessing uninitialized variables generally leads to unexpected program behavior. In some cases, these types of flaws may allow the execution of arbitrary code.
On the other hand, accessing uninitialized cases for the unexpected program behavior can backfire as well, since certain compilers can optimize uninitialized variables away. This type of flaw makes security procedures more predictable that may allow cracking of RSA keys.
Distributions derived from Debian, particularly VU#925211 in the OpenSSL package for Debian Linux, are said to reference uninitialized memory. One might say that uninitialized memory causes the vulnerability, but this is not entirely true. The original OpenSSL code uses uninitialized memory as an additional source of randomness to an already randomly generated key. This generates good keys, but also causes the code-auditing tools Valgrind and Purify to issue warnings. Debian tries to fix the warnings with two changes. One actually eliminates the uninitialized memory access, but the other weakens the randomness of the keys.
...
ISO/IEC 9899:2011 Section 6.7.9, "Initialization"
ISO/IEC TR 17961 (Draft) Referencing uninitialized memory [uninitref]
...
Bibliography
[Flake 2006]
[Mercy 2006]
[[Wang 2012] "More Randomness or Less"
[xorl 2009] "CVE-2009-1888: SAMBA ACLs Uninitialized Memory Read"
...