• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }