1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <pthread.h>
17 #include <semaphore.h>
18 #include <stdio.h>
19 #include <errno.h>
20 #include <string.h>
21 #include "test.h"
22 #include <signal.h>
23 #include <sys/wait.h>
24 #include <sigchain.h>
25 #include "fortify_test.h"
26 #include "functionalext.h"
27
28 #define T(f) if ((r=(f))) t_error(#f " failed: %s\n", strerror(r))
29 #define E(f) if (f) t_error(#f " failed: %s\n", strerror(errno))
30
pthread_mutex_lock_after_destroyed(void * arg)31 static void *pthread_mutex_lock_after_destroyed(void *arg)
32 {
33 void **a = arg;
34
35 *(int*)a[1] = pthread_mutex_lock(a[0]);
36 return 0;
37 }
38
test_pthread_mutex_lock_after_destroyed(int mtype)39 static int test_pthread_mutex_lock_after_destroyed(int mtype)
40 {
41 pthread_t t;
42 pthread_mutex_t m;
43 pthread_mutexattr_t ma;
44 int i;
45 int r;
46 void *p;
47 void *a[] = {&m, &i};
48 T(pthread_mutexattr_init(&ma));
49 T(pthread_mutexattr_settype(&ma, mtype));
50 T(pthread_mutex_init(a[0], &ma));
51 T(pthread_mutexattr_destroy(&ma));
52 T(pthread_create(&t, 0, pthread_mutex_lock_after_destroyed, a));
53 T(pthread_mutex_destroy(a[0]));
54 T(pthread_join(t, &p));
55 return i;
56 }
57
pthread_mutex_unlock_after_destroyed(void * arg)58 static void *pthread_mutex_unlock_after_destroyed(void *arg)
59 {
60 void **a = arg;
61
62 *(int*)a[1] = pthread_mutex_unlock(a[0]);
63 return 0;
64 }
65
test_pthread_mutex_unlock_after_destroyed(int mtype)66 static int test_pthread_mutex_unlock_after_destroyed(int mtype)
67 {
68 pthread_t t;
69 pthread_mutex_t m;
70 pthread_mutexattr_t ma;
71 int i;
72 int r;
73 void *p;
74 void *a[] = {&m, &i};
75 T(pthread_mutexattr_init(&ma));
76 T(pthread_mutexattr_settype(&ma, mtype));
77 T(pthread_mutex_init(a[0], &ma));
78 T(pthread_mutexattr_destroy(&ma));
79 T(pthread_create(&t, 0, pthread_mutex_unlock_after_destroyed, a));
80 T(pthread_mutex_destroy(a[0]));
81 T(pthread_join(t, &p));
82 return i;
83 }
84
pthread_mutex_timedlock_after_destroyed(void * arg)85 static void *pthread_mutex_timedlock_after_destroyed(void *arg)
86 {
87 void **a = arg;
88 struct timespec ts;
89 clock_gettime(CLOCK_REALTIME, &ts);
90 ts.tv_sec += 1;
91 *(int*)a[1] = pthread_mutex_timedlock(a[0], &ts);
92 return 0;
93 }
94
test_pthread_mutex_timedlock_after_destroyed(int mtype)95 static int test_pthread_mutex_timedlock_after_destroyed(int mtype)
96 {
97 pthread_t t;
98 pthread_mutex_t m;
99 pthread_mutexattr_t ma;
100 int i;
101 int r;
102 void *p;
103 void *a[] = {&m, &i};
104 T(pthread_mutexattr_init(&ma));
105 T(pthread_mutexattr_settype(&ma, mtype));
106 T(pthread_mutex_init(a[0], &ma));
107 T(pthread_mutexattr_destroy(&ma));
108 T(pthread_create(&t, 0, pthread_mutex_timedlock_after_destroyed, a));
109 T(pthread_mutex_destroy(a[0]));
110 T(pthread_join(t, &p));
111 return i;
112 }
113
pthread_mutex_trylock_after_destroyed(void * arg)114 static void *pthread_mutex_trylock_after_destroyed(void *arg)
115 {
116 void **a = arg;
117
118 *(int*)a[1] = pthread_mutex_trylock(a[0]);
119 return 0;
120 }
121
test_pthread_mutex_trylock_after_destroyed(int mtype)122 static int test_pthread_mutex_trylock_after_destroyed(int mtype)
123 {
124 pthread_t t;
125 pthread_mutex_t m;
126 pthread_mutexattr_t ma;
127 int i;
128 int r;
129 void *p;
130 void *a[] = {&m, &i};
131 T(pthread_mutexattr_init(&ma));
132 T(pthread_mutexattr_settype(&ma, mtype));
133 T(pthread_mutex_init(a[0], &ma));
134 T(pthread_mutexattr_destroy(&ma));
135 T(pthread_create(&t, 0, pthread_mutex_trylock_after_destroyed, a));
136 T(pthread_mutex_destroy(a[0]));
137 T(pthread_join(t, &p));
138 return i;
139 }
140
main(int argc,char * argv[])141 int main(int argc, char *argv[])
142 {
143 int i;
144
145 i = test_pthread_mutex_lock_after_destroyed(PTHREAD_MUTEX_NORMAL);
146 if (i != 0) {
147 t_error("PTHREAD_MUTEX_NORMAL lock failed after destroyed, got %s\n", strerror(i));
148 }
149 i = test_pthread_mutex_lock_after_destroyed(PTHREAD_MUTEX_ERRORCHECK);
150 if (i != 0) {
151 t_error("PTHREAD_MUTEX_ERRORCHECK lock failed after destroyed, got %s\n", strerror(i));
152 }
153 i = test_pthread_mutex_lock_after_destroyed(PTHREAD_MUTEX_RECURSIVE);
154 if (i != 0) {
155 t_error("PTHREAD_MUTEX_RECURSIVE lock failed after destroyed, got %s\n", strerror(i));
156 }
157 i = test_pthread_mutex_unlock_after_destroyed(PTHREAD_MUTEX_ERRORCHECK);
158 if (i == 0) {
159 t_error("PTHREAD_MUTEX_ERRORCHECK unlock failed after destroyed, got %s\n", strerror(i));
160 }
161 i = test_pthread_mutex_unlock_after_destroyed(PTHREAD_MUTEX_RECURSIVE);
162 if (i == 0) {
163 t_error("PTHREAD_MUTEX_RECURSIVE unlock failed after destroyed, got %s\n", strerror(i));
164 }
165 i = test_pthread_mutex_timedlock_after_destroyed(PTHREAD_MUTEX_NORMAL);
166 if (i != 0) {
167 t_error("PTHREAD_MUTEX_NORMAL timedlock failed after destroyed, got %s\n", strerror(i));
168 }
169 i = test_pthread_mutex_timedlock_after_destroyed(PTHREAD_MUTEX_ERRORCHECK);
170 if (i != 0) {
171 t_error("PTHREAD_MUTEX_ERRORCHECK timedlock failed after destroyed, got %s\n", strerror(i));
172 }
173 i = test_pthread_mutex_timedlock_after_destroyed(PTHREAD_MUTEX_RECURSIVE);
174 if (i != 0) {
175 t_error("PTHREAD_MUTEX_RECURSIVE timedlock failed after destroyed, got %s\n", strerror(i));
176 }
177 i = test_pthread_mutex_trylock_after_destroyed(PTHREAD_MUTEX_ERRORCHECK);
178 if (i != 0) {
179 t_error("PTHREAD_MUTEX_NORMAL trylock failed after destroyed, got %s\n", strerror(i));
180 }
181 i = test_pthread_mutex_trylock_after_destroyed(PTHREAD_MUTEX_ERRORCHECK);
182 if (i != 0) {
183 t_error("PTHREAD_MUTEX_ERRORCHECK trylock failed after destroyed, got %s\n", strerror(i));
184 }
185 i = test_pthread_mutex_trylock_after_destroyed(PTHREAD_MUTEX_RECURSIVE);
186 if (i != 0) {
187 t_error("PTHREAD_MUTEX_RECURSIVE trylock failed after destroyed, got %s\n", strerror(i));
188 }
189 return t_status;
190 }