1 /**
2 * Copyright (c) 2022 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 <dlfcn.h>
17 #include <link.h>
18 #include <stdlib.h>
19 #include <pthread.h>
20 #include <sys/wait.h>
21 #include "functionalext.h"
22 #include "test.h"
23
24 #define SAME_NAME_COUT_1 1
25 #define SAME_NAME_COUT_2 2
26 #define OOM_FILL 50000
27
28 void* handle_globle = NULL;
29 static pthread_mutex_t lock1;
30 static pthread_mutex_t lock2;
31
header_handler(struct dl_phdr_info * info,size_t size,void * data)32 static int header_handler(struct dl_phdr_info *info, size_t size, void *data)
33 {
34 void *addrhead = (void *)(info->dlpi_addr + info->dlpi_phdr[0].p_vaddr);
35 if ((strcmp(info->dlpi_name, "/data/libtest.so") == 0) && (addrhead != NULL)) {
36 return 1;
37 }
38 return 0;
39 }
40
41 static int same_name_count = 0;
42
same_name_count_handler(struct dl_phdr_info * info,size_t size,void * data)43 static int same_name_count_handler(struct dl_phdr_info *info, size_t size, void *data)
44 {
45 void *addrhead = (void *)(info->dlpi_addr + info->dlpi_phdr[0].p_vaddr);
46 if ((strcmp(info->dlpi_name, "/data/libtest.so") == 0) && (addrhead != NULL)) {
47 same_name_count++;
48 }
49 return 0;
50 }
51
lock_recursive_handler(struct dl_phdr_info * info,size_t size,void * data)52 static int lock_recursive_handler(struct dl_phdr_info *info, size_t size, void *data)
53 {
54 if (dl_iterate_phdr(header_handler, NULL)) {
55 return 0;
56 }
57 return 1;
58 }
59
sync_handler(struct dl_phdr_info * info,size_t size,void * data)60 static int sync_handler(struct dl_phdr_info *info, size_t size, void *data)
61 {
62 // Step 1:call dl_iterate_phdr and lock dlclose_lock, then call fork
63 pthread_mutex_unlock(&lock1);
64 pthread_mutex_lock(&lock2);
65 // Step 3:after call fork, unlock dlclose_lock and wait child process return
66 return 1;
67 }
68
nothing_handler(struct dl_phdr_info * info,size_t size,void * data)69 static int nothing_handler(struct dl_phdr_info *info, size_t size, void *data)
70 {
71 return 1;
72 }
73
call_dl_iterate_phdr(void * ptr)74 void *call_dl_iterate_phdr(void *ptr)
75 {
76 dl_iterate_phdr(sync_handler, NULL);
77 return NULL;
78 }
79
child_func(void)80 void child_func(void)
81 {
82 dlclose(handle_globle);
83 }
84
85 /**
86 * @tc.name : dl_iterate_phdr_0100
87 * @tc.desc : The parameter is valid, get the starting address of the dynamic library loaded in the memory.
88 * @tc.level : Level 0
89 */
dl_iterate_phdr_0100(void)90 void dl_iterate_phdr_0100(void)
91 {
92 void *handle = dlopen("/data/libtest.so", RTLD_NOW);
93 int ret = 0;
94 ret = dl_iterate_phdr(header_handler, NULL);
95 EXPECT_EQ("dl_iterate_phdr_0100", (int)ret, 1);
96
97 dlclose(handle);
98 ret = dl_iterate_phdr(header_handler, NULL);
99 EXPECT_EQ("dl_iterate_phdr_0100", (int)ret, 0);
100 }
101
102 /**
103 * @tc.name : dl_iterate_phdr_0200
104 * @tc.desc : Call dlopen twice, dlclose twice, the target so cannot find when second dlclose call.
105 * @tc.level : Level 0
106 */
dl_iterate_phdr_0200(void)107 void dl_iterate_phdr_0200(void)
108 {
109 void *handle = dlopen("/data/libtest.so", RTLD_NOW);
110 int ret = 0;
111 ret = dl_iterate_phdr(header_handler, NULL);
112 EXPECT_EQ("dl_iterate_phdr_0200", (int)ret, 1);
113
114 handle = dlopen("/data/libtest.so", RTLD_NOW);
115 ret = dl_iterate_phdr(header_handler, NULL);
116 EXPECT_EQ("dl_iterate_phdr_0200", (int)ret, 1);
117
118 dlclose(handle);
119 ret = dl_iterate_phdr(header_handler, NULL);
120 EXPECT_EQ("dl_iterate_phdr_0200", (int)ret, 1);
121
122 dlclose(handle);
123 ret = dl_iterate_phdr(header_handler, NULL);
124 EXPECT_EQ("dl_iterate_phdr_0200", (int)ret, 0);
125 }
126
127 /**
128 * @tc.name : dl_iterate_phdr_0300
129 * @tc.desc : Call dlopen twice, dlclose twice, so file use the same name but it is two different files.
130 * @tc.level : Level 0
131 */
dl_iterate_phdr_0300(void)132 void dl_iterate_phdr_0300(void)
133 {
134 void *handle1 = dlopen("/data/libtest.so", RTLD_NOW);
135 int ret = 0;
136 same_name_count = 0;
137 ret = dl_iterate_phdr(same_name_count_handler, NULL);
138 EXPECT_EQ("dl_iterate_phdr_0300", same_name_count, SAME_NAME_COUT_1);
139
140 system("rm -rf /data/libtest.so");
141 system("cp /data/local/tmp/lib_for_dlopen.so /data/libtest.so");
142 system("cp /data/tests/libc-test/src/lib_for_dlopen.so /data/libtest.so");
143
144 void *handle2 = dlopen("/data/libtest.so", RTLD_NOW);
145 same_name_count = 0;
146 ret = dl_iterate_phdr(same_name_count_handler, NULL);
147 EXPECT_EQ("dl_iterate_phdr_0300", same_name_count, SAME_NAME_COUT_2);
148
149 dlclose(handle1);
150 same_name_count = 0;
151 ret = dl_iterate_phdr(same_name_count_handler, NULL);
152 EXPECT_EQ("dl_iterate_phdr_0300", same_name_count, SAME_NAME_COUT_1);
153
154 dlclose(handle2);
155 same_name_count = 0;
156 ret = dl_iterate_phdr(same_name_count_handler, NULL);
157 EXPECT_EQ("dl_iterate_phdr_0300", same_name_count, 0);
158 }
159
160 /**
161 * @tc.name : dl_iterate_phdr_0400
162 * @tc.desc : Test lock is RECURSIVE when call dl_iterate_phdr
163 * @tc.level : Level 0
164 */
dl_iterate_phdr_0400(void)165 void dl_iterate_phdr_0400(void)
166 {
167 void *handle = dlopen("/data/libtest.so", RTLD_NOW);
168 int ret = 0;
169 ret = dl_iterate_phdr(lock_recursive_handler, NULL);
170 EXPECT_EQ("dl_iterate_phdr_0400", (int)ret, 0);
171
172 dlclose(handle);
173 }
174
175 /**
176 * @tc.name : dl_iterate_phdr_0500
177 * @tc.desc : Call dl_iterate_phdr when OOM happen.
178 * @tc.level : Level 0
179 */
dl_iterate_phdr_0500(void)180 void dl_iterate_phdr_0500(void)
181 {
182 void *handle = dlopen("/data/libtest.so", RTLD_NOW);
183 int ret = 0;
184 ret = dl_iterate_phdr(header_handler, NULL);
185 EXPECT_EQ("dl_iterate_phdr_0500", (int)ret, 1);
186 // create oom start
187 if (t_memfill() < 0) {
188 EXPECT_TRUE("dl_iterate_phdr_0500", false);
189 }
190 errno = 0;
191 if (malloc(OOM_FILL)) {
192 EXPECT_TRUE("dl_iterate_phdr_0500", false);
193 }
194 if (errno != ENOMEM) {
195 EXPECT_TRUE("dl_iterate_phdr_0500", false);
196 }
197 // create oom end
198 ret = dl_iterate_phdr(header_handler, NULL);
199 EXPECT_EQ("dl_iterate_phdr_0500", (int)ret, 1);
200 dlclose(handle);
201 }
202
203 /**
204 * @tc.name : dl_iterate_phdr_0600
205 * @tc.desc : Call dl_iterate_phdr when fork happen.
206 * @tc.level : Level 0
207 */
dl_iterate_phdr_0600(void)208 void dl_iterate_phdr_0600(void)
209 {
210 pthread_t thread1;
211 pid_t pid;
212 int status;
213 int ret;
214 // This test case must be executed in sequence:Step1 -> Step2 -> Step3(Parent process)
215 handle_globle = dlopen("/data/libtest.so", RTLD_NOW);
216 pthread_mutex_lock(&lock1);
217 pthread_mutex_lock(&lock2);
218 ret = pthread_create(&thread1, NULL, call_dl_iterate_phdr, NULL);
219 if (ret != 0) {
220 EXPECT_TRUE("dl_iterate_phdr_0600", false);
221 return;
222 }
223 pthread_atfork(NULL, NULL, child_func);
224 pthread_mutex_lock(&lock1);
225 // Step 2:after call dl_iterate_phdr, call fork, then dl_iterate_phdr can return
226 pid = fork();
227 pthread_mutex_unlock(&lock2);
228 if (pid < 0) {
229 return; // If fork failed, skip test dl_iterate_phdr_0600
230 } else if (pid == 0) {
231 // Child process, if can run here, dlclose_lock reset success
232 exit(EXIT_SUCCESS);
233 return;
234 } else {
235 // Parent process
236 dl_iterate_phdr(nothing_handler, NULL); // Test call dl_iterate_phdr success
237 pthread_join(thread1, NULL);
238 if (waitpid(pid, &status, 0) != pid) {
239 EXPECT_TRUE("dl_iterate_phdr_0600", false);
240 return;
241 }
242 if (!WIFEXITED(status)) {
243 EXPECT_TRUE("dl_iterate_phdr_0600", false);
244 return;
245 }
246 if (WEXITSTATUS(status) != 0) {
247 EXPECT_TRUE("dl_iterate_phdr_0600", false);
248 return;
249 }
250 EXPECT_TRUE("dl_iterate_phdr_0600", true);
251 dlclose(handle_globle);
252 return;
253 }
254 }
255
main(int argc,char * argv[])256 int main(int argc, char *argv[])
257 {
258 system("cp /data/local/tmp/lib_for_dlopen.so /data/libtest.so");
259 system("cp /data/tests/libc-test/src/lib_for_dlopen.so /data/libtest.so");
260 dl_iterate_phdr_0100();
261 dl_iterate_phdr_0200();
262 dl_iterate_phdr_0300();
263 dl_iterate_phdr_0600();
264 system("rm -rf /data/libtest.so");
265 exit(EXIT_SUCCESS);
266 return t_status;
267 }