You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: c/cert/src/rules/CON31-C/DoNotAllowAMutexToGoOutOfScopeWhileLocked.md
+157-2Lines changed: 157 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,9 +5,164 @@ This query implements the CERT-C rule CON31-C:
5
5
> Do not destroy a mutex while it is locked
6
6
7
7
8
-
## CERT
9
8
10
-
** REPLACE THIS BY RUNNING THE SCRIPT `scripts/help/cert-help-extraction.py`**
9
+
## Description
10
+
11
+
Mutexes are used to protect shared data structures being concurrently accessed. If a mutex is destroyed while a thread is blocked waiting for that mutex, [critical sections](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-criticalsections) and shared data are no longer protected.
12
+
13
+
The C Standard, 7.26.4.1, paragraph 2 \[[ISO/IEC 9899:2011](https://wiki.sei.cmu.edu/confluence/display/c/AA.+Bibliography#AA.Bibliography-ISO-IEC9899-2011)\], states
14
+
15
+
> The `mtx_destroy` function releases any resources used by the mutex pointed to by `mtx`. No threads can be blocked waiting for the mutex pointed to by `mtx`.
16
+
17
+
18
+
This statement implies that destroying a mutex while a thread is waiting on it is [undefined behavior](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-undefinedbehavior).
19
+
20
+
## Noncompliant Code Example
21
+
22
+
This noncompliant code example creates several threads that each invoke the `do_work()` function, passing a unique number as an ID. The `do_work()` function initializes the `lock` mutex if the argument is 0 and destroys the mutex if the argument is `max_threads - 1`. In all other cases, the `do_work()` function provides normal processing. Each thread, except the final cleanup thread, increments the atomic `completed` variable when it is finished.
23
+
24
+
Unfortunately, this code contains several race conditions, allowing the mutex to be destroyed before it is unlocked. Additionally, there is no guarantee that `lock` will be initialized before it is passed to `mtx_lock()`. Each of these behaviors is [undefined](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-undefinedbehavior).
25
+
26
+
```cpp
27
+
#include<stdatomic.h>
28
+
#include<stddef.h>
29
+
#include<threads.h>
30
+
31
+
mtx_t lock;
32
+
/* Atomic so multiple threads can modify safely */
if (thrd_success != thrd_create(&threads[i], do_work, &i)) {
64
+
/* Handle error */
65
+
}
66
+
}
67
+
for (size_t i = 0; i < max_threads; i++) {
68
+
if (thrd_success != thrd_join(threads[i], 0)) {
69
+
/* Handle error */
70
+
}
71
+
}
72
+
return 0;
73
+
}
74
+
75
+
```
76
+
77
+
## Compliant Solution
78
+
79
+
This compliant solution eliminates the race conditions by initializing the mutex in `main()` before creating the threads and by destroying the mutex in `main()` after joining the threads:
80
+
81
+
```cpp
82
+
#include <stdatomic.h>
83
+
#include <stddef.h>
84
+
#include <threads.h>
85
+
86
+
mtx_t lock;
87
+
/* Atomic so multiple threads can increment safely */
88
+
atomic_int completed = ATOMIC_VAR_INIT(0);
89
+
enum { max_threads = 5 };
90
+
91
+
int do_work(void *dummy) {
92
+
if (thrd_success != mtx_lock(&lock)) {
93
+
/* Handle error */
94
+
}
95
+
/* Access data protected by the lock */
96
+
atomic_fetch_add(&completed, 1);
97
+
if (thrd_success != mtx_unlock(&lock)) {
98
+
/* Handle error */
99
+
}
100
+
101
+
return 0;
102
+
}
103
+
104
+
int main(void) {
105
+
thrd_t threads[max_threads];
106
+
107
+
if (thrd_success != mtx_init(&lock, mtx_plain)) {
108
+
/* Handle error */
109
+
}
110
+
for (size_t i = 0; i < max_threads; i++) {
111
+
if (thrd_success != thrd_create(&threads[i], do_work, NULL)) {
112
+
/* Handle error */
113
+
}
114
+
}
115
+
for (size_t i = 0; i < max_threads; i++) {
116
+
if (thrd_success != thrd_join(threads[i], 0)) {
117
+
/* Handle error */
118
+
}
119
+
}
120
+
121
+
mtx_destroy(&lock);
122
+
return 0;
123
+
}
124
+
125
+
```
126
+
127
+
## Risk Assessment
128
+
129
+
Destroying a mutex while it is locked may result in invalid control flow and data corruption.
<table> <tbody> <tr> <th> Tool </th> <th> Version </th> <th> Checker </th> <th> Description </th> </tr> <tr> <td> <a> Astrée </a> </td> <td> 22.04 </td> <td> </td> <td> Supported, but no explicit checker </td> </tr> <tr> <td> <a> CodeSonar </a> </td> <td> 7.0p0 </td> <td> <strong>CONCURRENCY.LOCALARG</strong> </td> <td> Local Variable Passed to Thread </td> </tr> <tr> <td> <a> Helix QAC </a> </td> <td> 2022.2 </td> <td> <strong>C4961, C4962</strong> </td> <td> </td> </tr> <tr> <td> <a> PRQA QA-C </a> </td> <td> 9.7 </td> <td> <strong>4961, 4962 </strong> </td> <td> </td> </tr> <tr> <td> <a> Parasoft C/C++test </a> </td> <td> 2022.1 </td> <td> <strong>CERT_C-CON31-a</strong> <strong>CERT_C-CON31-b</strong> <strong>CERT_C-CON31-c</strong> </td> <td> Do not destroy another thread's mutex Do not use resources that have been freed Do not free resources using invalid pointers </td> </tr> <tr> <td> <a> Polyspace Bug Finder </a> </td> <td> R2022a </td> <td> <a> CERT C: Rule CON31-C </a> </td> <td> Checks for destruction of locked mutex (rule fully covered) </td> </tr> </tbody> </table>
137
+
138
+
139
+
## Related Vulnerabilities
140
+
141
+
Search for [vulnerabilities](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-vulnerability) resulting from the violation of this rule on the [CERT website](https://www.kb.cert.org/vulnotes/bymetric?searchview&query=FIELD+KEYWORDS+contains+CON31-C).
142
+
143
+
## Related Guidelines
144
+
145
+
[Key here](https://wiki.sei.cmu.edu/confluence/display/c/How+this+Coding+Standard+is+Organized#HowthisCodingStandardisOrganized-RelatedGuidelines) (explains table format and definitions)
[Key here](https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=87152408#HowthisCodingStandardisOrganized-CERT-CWEMappingNotes) for mapping notes
153
+
154
+
**CWE-667 and CON31-C/POS48-C**
155
+
156
+
Intersection( CON31-C, POS48-C) = Ø
157
+
158
+
CWE-667 = Union, CON31-C, POS48-C, list) where list =
159
+
160
+
* Locking & Unlocking issues besides unlocking another thread’s C mutex or pthread mutex.
Copy file name to clipboardExpand all lines: c/cert/src/rules/CON31-C/DoNotDestroyAMutexWhileItIsLocked.md
+157-2Lines changed: 157 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,9 +5,164 @@ This query implements the CERT-C rule CON31-C:
5
5
> Do not destroy a mutex while it is locked
6
6
7
7
8
-
## CERT
9
8
10
-
** REPLACE THIS BY RUNNING THE SCRIPT `scripts/help/cert-help-extraction.py`**
9
+
## Description
10
+
11
+
Mutexes are used to protect shared data structures being concurrently accessed. If a mutex is destroyed while a thread is blocked waiting for that mutex, [critical sections](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-criticalsections) and shared data are no longer protected.
12
+
13
+
The C Standard, 7.26.4.1, paragraph 2 \[[ISO/IEC 9899:2011](https://wiki.sei.cmu.edu/confluence/display/c/AA.+Bibliography#AA.Bibliography-ISO-IEC9899-2011)\], states
14
+
15
+
> The `mtx_destroy` function releases any resources used by the mutex pointed to by `mtx`. No threads can be blocked waiting for the mutex pointed to by `mtx`.
16
+
17
+
18
+
This statement implies that destroying a mutex while a thread is waiting on it is [undefined behavior](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-undefinedbehavior).
19
+
20
+
## Noncompliant Code Example
21
+
22
+
This noncompliant code example creates several threads that each invoke the `do_work()` function, passing a unique number as an ID. The `do_work()` function initializes the `lock` mutex if the argument is 0 and destroys the mutex if the argument is `max_threads - 1`. In all other cases, the `do_work()` function provides normal processing. Each thread, except the final cleanup thread, increments the atomic `completed` variable when it is finished.
23
+
24
+
Unfortunately, this code contains several race conditions, allowing the mutex to be destroyed before it is unlocked. Additionally, there is no guarantee that `lock` will be initialized before it is passed to `mtx_lock()`. Each of these behaviors is [undefined](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-undefinedbehavior).
25
+
26
+
```cpp
27
+
#include<stdatomic.h>
28
+
#include<stddef.h>
29
+
#include<threads.h>
30
+
31
+
mtx_t lock;
32
+
/* Atomic so multiple threads can modify safely */
if (thrd_success != thrd_create(&threads[i], do_work, &i)) {
64
+
/* Handle error */
65
+
}
66
+
}
67
+
for (size_t i = 0; i < max_threads; i++) {
68
+
if (thrd_success != thrd_join(threads[i], 0)) {
69
+
/* Handle error */
70
+
}
71
+
}
72
+
return 0;
73
+
}
74
+
75
+
```
76
+
77
+
## Compliant Solution
78
+
79
+
This compliant solution eliminates the race conditions by initializing the mutex in `main()` before creating the threads and by destroying the mutex in `main()` after joining the threads:
80
+
81
+
```cpp
82
+
#include <stdatomic.h>
83
+
#include <stddef.h>
84
+
#include <threads.h>
85
+
86
+
mtx_t lock;
87
+
/* Atomic so multiple threads can increment safely */
88
+
atomic_int completed = ATOMIC_VAR_INIT(0);
89
+
enum { max_threads = 5 };
90
+
91
+
int do_work(void *dummy) {
92
+
if (thrd_success != mtx_lock(&lock)) {
93
+
/* Handle error */
94
+
}
95
+
/* Access data protected by the lock */
96
+
atomic_fetch_add(&completed, 1);
97
+
if (thrd_success != mtx_unlock(&lock)) {
98
+
/* Handle error */
99
+
}
100
+
101
+
return 0;
102
+
}
103
+
104
+
int main(void) {
105
+
thrd_t threads[max_threads];
106
+
107
+
if (thrd_success != mtx_init(&lock, mtx_plain)) {
108
+
/* Handle error */
109
+
}
110
+
for (size_t i = 0; i < max_threads; i++) {
111
+
if (thrd_success != thrd_create(&threads[i], do_work, NULL)) {
112
+
/* Handle error */
113
+
}
114
+
}
115
+
for (size_t i = 0; i < max_threads; i++) {
116
+
if (thrd_success != thrd_join(threads[i], 0)) {
117
+
/* Handle error */
118
+
}
119
+
}
120
+
121
+
mtx_destroy(&lock);
122
+
return 0;
123
+
}
124
+
125
+
```
126
+
127
+
## Risk Assessment
128
+
129
+
Destroying a mutex while it is locked may result in invalid control flow and data corruption.
<table> <tbody> <tr> <th> Tool </th> <th> Version </th> <th> Checker </th> <th> Description </th> </tr> <tr> <td> <a> Astrée </a> </td> <td> 22.04 </td> <td> </td> <td> Supported, but no explicit checker </td> </tr> <tr> <td> <a> CodeSonar </a> </td> <td> 7.0p0 </td> <td> <strong>CONCURRENCY.LOCALARG</strong> </td> <td> Local Variable Passed to Thread </td> </tr> <tr> <td> <a> Helix QAC </a> </td> <td> 2022.2 </td> <td> <strong>C4961, C4962</strong> </td> <td> </td> </tr> <tr> <td> <a> PRQA QA-C </a> </td> <td> 9.7 </td> <td> <strong>4961, 4962 </strong> </td> <td> </td> </tr> <tr> <td> <a> Parasoft C/C++test </a> </td> <td> 2022.1 </td> <td> <strong>CERT_C-CON31-a</strong> <strong>CERT_C-CON31-b</strong> <strong>CERT_C-CON31-c</strong> </td> <td> Do not destroy another thread's mutex Do not use resources that have been freed Do not free resources using invalid pointers </td> </tr> <tr> <td> <a> Polyspace Bug Finder </a> </td> <td> R2022a </td> <td> <a> CERT C: Rule CON31-C </a> </td> <td> Checks for destruction of locked mutex (rule fully covered) </td> </tr> </tbody> </table>
137
+
138
+
139
+
## Related Vulnerabilities
140
+
141
+
Search for [vulnerabilities](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-vulnerability) resulting from the violation of this rule on the [CERT website](https://www.kb.cert.org/vulnotes/bymetric?searchview&query=FIELD+KEYWORDS+contains+CON31-C).
142
+
143
+
## Related Guidelines
144
+
145
+
[Key here](https://wiki.sei.cmu.edu/confluence/display/c/How+this+Coding+Standard+is+Organized#HowthisCodingStandardisOrganized-RelatedGuidelines) (explains table format and definitions)
[Key here](https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=87152408#HowthisCodingStandardisOrganized-CERT-CWEMappingNotes) for mapping notes
153
+
154
+
**CWE-667 and CON31-C/POS48-C**
155
+
156
+
Intersection( CON31-C, POS48-C) = Ø
157
+
158
+
CWE-667 = Union, CON31-C, POS48-C, list) where list =
159
+
160
+
* Locking & Unlocking issues besides unlocking another thread’s C mutex or pthread mutex.
0 commit comments