Some functions in the C standard library are not guaranteed to be reentrant with respect to threads. Some functions return a pointer to the result stored in memory allocated by the function on a per-process basis(such as strtok() and asctime()) while some functions store state information in memory allocated by the function on a per-process basis(such as rand()). Multiple threads invoking the same function can cause concurrency problems. Concurrency problems can often result in abnormal behavior, but it is possible for them to result in more serious vulnerabilities such as abnormal termination, denial of service attack and data integrity violation.
As per the N1401-C1X document, the following library functions are not required to avoid data races:
- rand()
- getenv()
- strtok()
- strerror()
- asctime()
- ctime()
Non Compliant Code Example
Consider a multithreaded application which encounters an error while calling a system function. The strerror()
function returns a human-readable error string given an error number. According to C99, Section 7.22.6.2 specifically states that strerror()
is not required to avoid data races. Conventionally it could rely on a static array that maps error numbers to error strings, and said array might be accessible and modifiable by other threads.
FILE* fd = fopen( filename, "r"); if (fd == NULL) { char* errmsg = strerror(errno); printf("Could not open file because of %s\n", errmsg); }
Compliant Solution
The compliant solution uses strerror_r()
, which has the same functionality as strerror()
but guarantees thread-safety.
FILE* fd = fopen( filename, "r"); if (fd == NULL) { char errmsg[BUFSIZ]; if (strerror_r( errno, errmsg, BUFSIZ) == -1) { /* handle error */ } printf("Could not open file because of %s\n", errmsg); }
Risk Assessment
Race conditions caused by multiple threads invoking the same library function can lead to abnormal termination of the application, data integrity violations or denial of service attack.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
POS40-C |
medium |
probable |
High |
P4 |
L3 |
Automated Detection
A module can be written in Compass/ROSE to detect violations of this rule.
References
[N1401-C1X Draft] Section 7.21.2.1 rand() function, Section 7.21.4.6 getenv() function, Section 7.22.5.8 strtok() function, Section 7.22.6.2 strerror() function, Section 7.25.3.1 asctime() function, Section 7.25.3.2 ctime() function
[POSIX.1 Thread Safety]