When multiple threads must access or make modifications to a common variable, they may also inadvertently access other variables in adjacent memory. This is an artifact of variables being stored compactly, with one 1 byte possibly holding multiple variables, and is a common optimization on word-addressed machines. Bit-fields are especially prone to this behavior because compilers are allowed to store multiple bit-fields in one 1 addressable byte or word. Consequently, data races may exist not just on a variable accessed by multiple threads but also on other variables sharing the same byte or word address.
...
The same code is compliant when run on a C11-compliant platform. Unlike C99, C11 explicitly defines a memory location , and provides the following note, in chapter section 3, section .14.2 [ISO/IEC 9899:2011]:
NOTE 1 Two threads of execution can update and access separate memory locations without interfering with each other.
...
Adjacent bit-fields may be stored in a single memory location. Consequently, and therefore modifying adjacent bit-fields in different threads is undefined behavior, even in C11.
Code Block | ||||
---|---|---|---|---|
| ||||
struct multi_threaded_flags { unsigned int flag1 : 2; unsigned int flag2 : 2; }; struct multi_threaded_flags flags; void thread1(void) { flags.flag1 = 1; } void thread2(void) { flags.flag2 = 2; } |
C11The C Standard, chapter section 3, section .14.3 [ISO/IEC 9899:2011], states:
NOTE 2 A bit-field and an adjacent non-bit-field member are in separate memory locations. The same applies to two bit-fields, if one is declared inside a nested structure declaration and the other is not, or if the two are separated by a zero-length bit-field declaration, or if they are separated by a non-bit-field member declaration. It is not safe to concurrently update two non-atomic bit-fields in the same structure if all members declared between them are also (non-zero-length) bit-fields, no matter what the sizes of those intervening bit-fields happen to be.
...
This compliant solution protects all accesses of the flags with a mutex, thereby preventing any data races. FinallyFinally, the flags are embedded in a union alongside a long
, and a static assertion guarantees that the flags do not occupy more space than the long
. This technique prevents any data not checked by the mutex from being accessed or modified with the bit-fields on platforms that do not comply with C11.
...
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
CON32-C | medium | probable | medium | P8 | L2 |
Automated Detection
Tool | Version | Checker | Description |
---|---|---|---|
Coverity | 6.5 | RACE_CONDITION | Fully Implementedimplemented |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
...
Bibliography
...
] | Section 3.14, "Memory Location" |
...
...