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_ext.h>
17 #include <errno.h>
18 #include <stdbool.h>
19 #include <stdint.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/wait.h>
24
25 #include "functionalext.h"
26
27 #define PIPE_FD 2
28 #define LEN_OF_POINTER 8
29 #define BASE_NUM 11
30 #define TEST_COUNTS 32
31
32 const char *LIB_NAME = "./libldso_randomization_dep.so";
33 const char *LIB_NAME_A = "./libldso_randomization_dep_a.so";
34 typedef void (*TEST_FUNC)(void);
35
36 int g_test = BASE_NUM;
test_f(void)37 extern void test_f(void)
38 {
39 ++g_test;
40 }
41
42 /**
43 * @tc.name : dlopen_randomization_0100
44 * @tc.desc : Call the dlopen interface to load a valid dynamic library
45 * @tc.level : Level0
46 */
dlopen_randomization_0100(void)47 static void dlopen_randomization_0100(void)
48 {
49 void *handle = dlopen(LIB_NAME, RTLD_NOW);
50 EXPECT_PTRNE(__FUNCTION__, handle, 0);
51 if (handle) {
52 EXPECT_EQ(__FUNCTION__, dlclose(handle), 0);
53 }
54 }
55
56 /**
57 * @tc.name : dlopen_randomization_0200
58 * @tc.desc : Call the dlopen interface to load NULL
59 * @tc.level : Level1
60 */
dlopen_randomization_0200(void)61 static void dlopen_randomization_0200(void)
62 {
63 void *handle = dlopen(NULL, RTLD_NOW);
64 EXPECT_PTRNE(__FUNCTION__, handle, 0);
65 if (!handle) {
66 return;
67 };
68 int *i = dlsym(handle, "g_test");
69 EXPECT_PTRNE(__FUNCTION__, i, 0);
70 if (!i) {
71 dlclose(handle);
72 return;
73 }
74 EXPECT_EQ(__FUNCTION__, BASE_NUM, *i);
75 TEST_FUNC test = (TEST_FUNC)dlsym(handle, "test_f");
76 EXPECT_PTRNE(__FUNCTION__, test, 0);
77 if (!test) {
78 dlclose(handle);
79 return;
80 }
81 test();
82 EXPECT_EQ(__FUNCTION__, BASE_NUM + 1, g_test);
83 g_test = BASE_NUM;
84 dlclose(handle);
85 }
86
87 /**
88 * @tc.name : dlopen_randomization_0300
89 * @tc.desc : Call the dlopen interface to load a invalid dynamic library
90 * @tc.level : Level2
91 */
dlopen_randomization_0300(void)92 static void dlopen_randomization_0300(void)
93 {
94 void *handle = dlopen("test_invaild.so", RTLD_NOW);
95 EXPECT_PTREQ(__FUNCTION__, handle, 0);
96 if (handle) {
97 dlclose(handle);
98 }
99 }
100
101 /**
102 * @tc.name : dlopen_randomization_0400
103 * @tc.desc : Repeatedly calling the dlopen interface to load the same dynamic library
104 * @tc.level : Level1
105 */
dlopen_randomization_0400(void)106 static void dlopen_randomization_0400(void)
107 {
108 void *ori_handle = dlopen(LIB_NAME, RTLD_NOW);
109 void *handle = 0;
110 EXPECT_PTRNE(__FUNCTION__, ori_handle, 0);
111 if (!ori_handle) {
112 return;
113 }
114 int i = TEST_COUNTS;
115 while (i--) {
116 handle = dlopen(LIB_NAME, RTLD_NOW);
117 EXPECT_PTREQ(__FUNCTION__, ori_handle, handle);
118 }
119 i = TEST_COUNTS + 1;
120 while (i--) {
121 dlclose(ori_handle);
122 }
123 }
124
125 /**
126 * @tc.name : dlopen_randomization_0600
127 * @tc.desc : Call the dlopen interface to load a invalid dynamic library,
128 * and call the dlsym interface to get symbol address
129 * @tc.level : Level1
130 */
dlopen_randomization_0600(void)131 static void dlopen_randomization_0600(void)
132 {
133 void *handle;
134 int *i;
135 TEST_FUNC test;
136 handle = dlopen(LIB_NAME, RTLD_NOW);
137 EXPECT_PTRNE(__FUNCTION__, handle, 0);
138 if (!handle) {
139 return;
140 }
141 i = dlsym(handle, "i");
142 EXPECT_PTRNE(__FUNCTION__, i, 0);
143 if (!i) {
144 dlclose(handle);
145 return;
146 }
147 EXPECT_EQ(__FUNCTION__, *i, 0);
148 test = (TEST_FUNC)dlsym(handle, "test");
149 EXPECT_PTRNE(__FUNCTION__, test, 0);
150 if (!test) {
151 dlclose(handle);
152 return;
153 }
154 test();
155 EXPECT_EQ(__FUNCTION__, *i, 1);
156 dlclose(handle);
157 }
158
159 /**
160 * @tc.name : dlopen_ext_randomization_0100
161 * @tc.desc : Call the dlopen_ext interface to load a valid dynamic library
162 * @tc.level : Level0
163 */
dlopen_ext_randomization_0100(void)164 static void dlopen_ext_randomization_0100(void)
165 {
166 dl_extinfo extinfo = {0};
167 void *handle = dlopen_ext(LIB_NAME_A, RTLD_NOW, &extinfo);
168 EXPECT_PTRNE(__FUNCTION__, handle, 0);
169 if (handle) {
170 EXPECT_EQ(__FUNCTION__, dlclose(handle), 0);
171 }
172 }
173
174 /**
175 * @tc.name : dlopen_ext_randomization_0200
176 * @tc.desc : Call the dlopen interface to load NULL
177 * @tc.level : Level1
178 */
dlopen_ext_randomization_0200(void)179 static void dlopen_ext_randomization_0200(void)
180 {
181 dl_extinfo extinfo = {0};
182 void *handle = dlopen_ext(NULL, RTLD_NOW, &extinfo);
183 EXPECT_PTRNE(__FUNCTION__, handle, 0);
184 if (!handle) {
185 return;
186 }
187 int *i = dlsym(handle, "g_test");
188 EXPECT_PTRNE(__FUNCTION__, i, 0);
189 if (!i) {
190 dlclose(handle);
191 return;
192 }
193 EXPECT_EQ(__FUNCTION__, BASE_NUM, *i);
194 TEST_FUNC test = (TEST_FUNC)dlsym(handle, "test_f");
195 EXPECT_PTRNE(__FUNCTION__, test, 0);
196 if (!test) {
197 dlclose(handle);
198 return;
199 }
200 test();
201 EXPECT_EQ(__FUNCTION__, BASE_NUM + 1, g_test);
202 g_test = BASE_NUM;
203 dlclose(handle);
204 }
205
206 /**
207 * @tc.name : dlopen_ext_randomization_0300
208 * @tc.desc : Call the dlopen interface to load a invalid dynamic library
209 * @tc.level : Level2
210 */
dlopen_ext_randomization_0300(void)211 static void dlopen_ext_randomization_0300(void)
212 {
213 dl_extinfo extinfo = {0};
214 void *handle = dlopen_ext("test_invaild.so", RTLD_NOW, &extinfo);
215 EXPECT_PTREQ(__FUNCTION__, handle, 0);
216 if (handle) {
217 dlclose(handle);
218 }
219 }
220
221 /**
222 * @tc.name : dlopen_ext_randomization_0400
223 * @tc.desc : Repeatedly calling the dlopen_ext interface to load the same dynamic library
224 * @tc.level : Level1
225 */
dlopen_ext_randomization_0400(void)226 static void dlopen_ext_randomization_0400(void)
227 {
228 dl_extinfo extinfo = {0};
229 void *ori_handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
230 void *handle = 0;
231 EXPECT_PTRNE(__FUNCTION__, ori_handle, 0);
232 if (!ori_handle) {
233 return;
234 }
235 int i = TEST_COUNTS;
236 while (i--) {
237 handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
238 EXPECT_PTREQ(__FUNCTION__, ori_handle, handle);
239 }
240 i = TEST_COUNTS + 1;
241 while (i--) {
242 dlclose(ori_handle);
243 }
244 }
245
246 /**
247 * @tc.name : dlopen_ext_randomization_0600
248 * @tc.desc : Call the dlopen_ext interface to load a invalid dynamic library,
249 * and call the dlsym interface to get symbol address
250 * @tc.level : Level1
251 */
dlopen_ext_randomization_0600(void)252 static void dlopen_ext_randomization_0600(void)
253 {
254 void *handle;
255 int *i;
256 TEST_FUNC test;
257 dl_extinfo extinfo = {0};
258 handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
259 EXPECT_PTRNE(__FUNCTION__, handle, 0);
260 if (!handle) {
261 return;
262 }
263 i = dlsym(handle, "i");
264 EXPECT_PTRNE(__FUNCTION__, i, 0);
265 if (!i) {
266 dlclose(handle);
267 return;
268 }
269 EXPECT_EQ(__FUNCTION__, *i, 0);
270 test = (TEST_FUNC)dlsym(handle, "test");
271 EXPECT_PTRNE(__FUNCTION__, test, 0);
272 if (!test) {
273 dlclose(handle);
274 return;
275 }
276 test();
277 EXPECT_EQ(__FUNCTION__, *i, 1);
278 dlclose(handle);
279 }
280
281 /**
282 * @tc.name : dlopen_ext_randomization_0800
283 * @tc.desc : The flag of dl_extinfo is set to DL_EXT_RESERVED_ADDRESS_RECURSIVE,
284 * call the dlopen_ext interface to load a valid dynamic library
285 * @tc.level : Level1
286 */
dlopen_ext_randomization_0800(void)287 static void dlopen_ext_randomization_0800(void)
288 {
289 dl_extinfo extinfo = {
290 .flag = DL_EXT_RESERVED_ADDRESS_RECURSIVE,
291 };
292 void *handle = dlopen_ext(NULL, RTLD_NOW, &extinfo);
293 EXPECT_PTRNE(__FUNCTION__, handle, 0);
294 if (!handle) {
295 return;
296 }
297 int *i = dlsym(handle, "g_test");
298 EXPECT_PTRNE(__FUNCTION__, i, 0);
299 if (!i) {
300 dlclose(handle);
301 return;
302 }
303 EXPECT_EQ(__FUNCTION__, BASE_NUM, *i);
304 TEST_FUNC test = (TEST_FUNC)dlsym(handle, "test_f");
305 EXPECT_PTRNE(__FUNCTION__, test, 0);
306 if (!test) {
307 dlclose(handle);
308 return;
309 }
310 test();
311 EXPECT_EQ(__FUNCTION__, BASE_NUM + 1, *i);
312 g_test = BASE_NUM;
313 dlclose(handle);
314 }
315
316 /**
317 * @tc.name : dlopen_ext_randomization_0900
318 * @tc.desc : Different processes call the dlopen_ext interface to load a dynamic library,
319 * the flag of dl_extinfo is set to DL_EXT_RESERVED_ADDRESS_RECURSIVE,
320 * and then call the dlsym interface to get symbol address
321 * @tc.level : Level1
322 */
dlopen_ext_randomization_0900(void)323 static void dlopen_ext_randomization_0900(void)
324 {
325 void *parent_handle = 0;
326 void *child_handle = 0;
327 void *parent_sym = 0;
328 void *child_sym = 0;
329 void *get_child_sym = 0;
330 int fd[PIPE_FD];
331 if (pipe(fd) < 0) {
332 EXPECT_FALSE(__FUNCTION__, true);
333 return;
334 }
335 dl_extinfo extinfo = {
336 .flag = DL_EXT_RESERVED_ADDRESS_RECURSIVE,
337 };
338 pid_t pid = fork();
339 if (pid == 0) {
340 child_handle = dlopen_ext(LIB_NAME_A, RTLD_NOW, &extinfo);
341 EXPECT_PTRNE(__FUNCTION__, child_handle, 0);
342 if (!child_handle) {
343 exit(-1);
344 }
345 child_sym = dlsym(child_handle, "test");
346 write(fd[1], &child_sym, sizeof(void *));
347 dlclose(child_handle);
348 exit(0);
349 }
350 parent_handle = dlopen_ext(LIB_NAME_A, RTLD_NOW, &extinfo);
351 EXPECT_PTRNE(__FUNCTION__, parent_handle, 0);
352 if (!parent_handle) {
353 return;
354 };
355 parent_sym = dlsym(parent_handle, "test");
356 dlclose(parent_handle);
357 int status;
358 waitpid(pid, &status, 0);
359 read(fd[0], &get_child_sym, sizeof(void *));
360 EXPECT_PTREQ(__FUNCTION__, parent_sym, get_child_sym);
361 close(fd[0]);
362 close(fd[1]);
363 }
364
365 /**
366 * @tc.name : dlopen_ns_randomization_0100
367 * @tc.desc : Call the dlopen_ns interface to load a valid dynamic library
368 * @tc.level : Level0
369 */
dlopen_ns_randomization_0100(void)370 static void dlopen_ns_randomization_0100(void)
371 {
372 Dl_namespace dlns;
373 dlns_init(&dlns, __FUNCTION__);
374 dlns_create(&dlns, "./");
375 void *handle = dlopen_ns(&dlns, LIB_NAME, RTLD_NOW);
376 EXPECT_PTRNE(__FUNCTION__, handle, 0);
377 if (handle) {
378 EXPECT_EQ(__FUNCTION__, dlclose(handle), 0);
379 }
380 }
381
382 /**
383 * @tc.name : dlopen_ns_randomization_0200
384 * @tc.desc : Call the dlopen_ns interface to load NULL
385 * @tc.level : Level1
386 */
dlopen_ns_randomization_0200(void)387 static void dlopen_ns_randomization_0200(void)
388 {
389 Dl_namespace dlns;
390 dlns_init(&dlns, __FUNCTION__);
391 dlns_create(&dlns, "./");
392 void *handle = dlopen_ns(&dlns, NULL, RTLD_NOW);
393 EXPECT_PTRNE(__FUNCTION__, handle, 0);
394 if (!handle) {
395 return;
396 }
397 int *i = dlsym(handle, "g_test");
398 EXPECT_PTRNE(__FUNCTION__, i, 0);
399 if (!i) {
400 dlclose(handle);
401 return;
402 }
403 EXPECT_EQ(__FUNCTION__, BASE_NUM, *i);
404 TEST_FUNC test = (TEST_FUNC)dlsym(handle, "test_f");
405 EXPECT_PTRNE(__FUNCTION__, test, 0);
406 if (!test) {
407 dlclose(handle);
408 return;
409 }
410 test();
411 EXPECT_EQ(__FUNCTION__, BASE_NUM + 1, g_test);
412 g_test = BASE_NUM;
413 dlclose(handle);
414 }
415
416 /**
417 * @tc.name : dlopen_ns_randomization_0300
418 * @tc.desc : Call the dlopen_ns interface to load a invalid dynamic library
419 * @tc.level : Level2
420 */
dlopen_ns_randomization_0300(void)421 static void dlopen_ns_randomization_0300(void)
422 {
423 Dl_namespace dlns;
424 dlns_init(&dlns, __FUNCTION__);
425 dlns_create(&dlns, "./");
426 void *handle = dlopen_ns(&dlns, "test_invaild.so", RTLD_NOW);
427 EXPECT_PTREQ(__FUNCTION__, handle, 0);
428 if (handle) {
429 dlclose(handle);
430 }
431 }
432
433 /**
434 * @tc.name : dlopen_ns_randomization_0400
435 * @tc.desc : Repeatedly calling the dlopen_ns interface to load the same dynamic library
436 * @tc.level : Level1
437 */
dlopen_ns_randomization_0400(void)438 static void dlopen_ns_randomization_0400(void)
439 {
440 Dl_namespace dlns;
441 dlns_init(&dlns, __FUNCTION__);
442 dlns_create(&dlns, "./");
443 void *ori_handle = dlopen_ns(&dlns, LIB_NAME, RTLD_NOW);
444 void *handle = 0;
445 EXPECT_PTRNE(__FUNCTION__, ori_handle, 0);
446 if (!ori_handle) {
447 return;
448 }
449 int i = TEST_COUNTS;
450 while (i--) {
451 handle = dlopen_ns(&dlns, LIB_NAME, RTLD_NOW);
452 EXPECT_PTREQ(__FUNCTION__, ori_handle, handle);
453 }
454 i = TEST_COUNTS + 1;
455 while (i--) {
456 dlclose(ori_handle);
457 }
458 }
459
460 /**
461 * @tc.name : dlopen_ns_randomization_0600
462 * @tc.desc : Call the dlopen_ns interface to load a invalid dynamic library,
463 * and call the dlsym interface to get symbol address
464 * @tc.level : Level1
465 */
dlopen_ns_randomization_0600(void)466 static void dlopen_ns_randomization_0600(void)
467 {
468 Dl_namespace dlns;
469 dlns_init(&dlns, __FUNCTION__);
470 dlns_create(&dlns, "./");
471 void *handle;
472 int *i;
473 TEST_FUNC test;
474 handle = dlopen_ns(&dlns, LIB_NAME, RTLD_NOW);
475 EXPECT_PTRNE(__FUNCTION__, handle, 0);
476 if (!handle) {
477 return;
478 }
479 i = dlsym(handle, "i");
480 EXPECT_PTRNE(__FUNCTION__, i, 0);
481 if (!i) {
482 dlclose(handle);
483 return;
484 }
485 EXPECT_EQ(__FUNCTION__, *i, 0);
486 test = (TEST_FUNC)dlsym(handle, "test");
487 EXPECT_PTRNE(__FUNCTION__, test, 0);
488 if (!test) {
489 dlclose(handle);
490 return;
491 }
492 test();
493 EXPECT_EQ(__FUNCTION__, *i, 1);
494 dlclose(handle);
495 }
496
497 /**
498 * @tc.name : dlsym_randomization_0300
499 * @tc.desc : Call the dlsym interface to get symbol address, handle is invalid
500 * @tc.level : Level2
501 */
dlsym_randomization_0300(void)502 static void dlsym_randomization_0300(void)
503 {
504 void *sym = dlsym((void *)0xFFFF, "invalid_function");
505 EXPECT_PTREQ(__FUNCTION__, sym, NULL);
506 }
507
508 /**
509 * @tc.name : dlsym_randomization_0400
510 * @tc.desc : Call the dlsym interface to get symbol address, handle is setted to RTLD_DEFAULT, and name is valid
511 * @tc.level : Level1
512 */
dlsym_randomization_0400(void)513 static void dlsym_randomization_0400(void)
514 {
515 void *sym = dlsym(RTLD_DEFAULT, "fopen");
516 EXPECT_PTRNE(__FUNCTION__, sym, NULL);
517 }
518
519 /**
520 * @tc.name : dlsym_randomization_0500
521 * @tc.desc : Call the dlsym interface to get symbol address, handle is setted to RTLD_DEFAULT, and name is invalid
522 * @tc.level : Level2
523 */
dlsym_randomization_0500(void)524 static void dlsym_randomization_0500(void)
525 {
526 void *sym = dlsym(RTLD_DEFAULT, "invalid_func");
527 EXPECT_PTREQ(__FUNCTION__, sym, NULL);
528 }
529
530
531 /**
532 * @tc.name : dlsym_randomization_0600
533 * @tc.desc : Call the dlsym interface to get symbol address, handle is setted to RTLD_NEXT, and name is valid
534 * @tc.level : Level1
535 */
dlsym_randomization_0600(void)536 static void dlsym_randomization_0600(void)
537 {
538 void *sym = dlsym(RTLD_NEXT, "fopen");
539 EXPECT_PTRNE(__FUNCTION__, sym, NULL);
540 }
541
542 /**
543 * @tc.name : dlsym_randomization_0700
544 * @tc.desc : Call the dlsym interface to get symbol address, handle is setted to RTLD_NEXT, and name is invalid
545 * @tc.level : Level2
546 */
dlsym_randomization_0700(void)547 static void dlsym_randomization_0700(void)
548 {
549 void *sym = dlsym(RTLD_NEXT, "invalid_func");
550 EXPECT_PTREQ(__FUNCTION__, sym, NULL);
551 }
552
553 /**
554 * @tc.name : dlclose_randomization_0100
555 * @tc.desc : Call the dlclose interface to unload dynamic library
556 * @tc.level : Level2
557 */
dlclose_randomization_0100(void)558 static void dlclose_randomization_0100(void)
559 {
560 int ret = dlclose(NULL);
561 EXPECT_EQ(__FUNCTION__, -1, ret);
562 }
563
564 /**
565 * @tc.name : dlopen_randomization_0800
566 * @tc.desc : Call the dlopen interface to load libc.so
567 * @tc.level : Level1
568 */
dlopen_randomization_0800(void)569 static void dlopen_randomization_0800(void)
570 {
571 if (sizeof(void *) == LEN_OF_POINTER) {
572 system("cp /system/lib64/libc.so .");
573 } else {
574 system("cp /system/lib/libc.so .");
575 }
576 void *handle = dlopen("./libc.so", RTLD_NOW);
577 EXPECT_PTRNE(__FUNCTION__, handle, 0);
578 system("rm ./libc.so");
579 }
580
581 /**
582 * @tc.name : dlopen_randomization_0900
583 * @tc.desc : Call the dlopen interface to load ld.so
584 * @tc.level : Level1
585 */
dlopen_randomization_0900(void)586 static void dlopen_randomization_0900(void)
587 {
588 void *handle = NULL;
589 if (sizeof(void *) == LEN_OF_POINTER) {
590 system("cp /system/lib/ld-musl-aarch64.so.1 .");
591 handle = dlopen("./ld-musl-aarch64.so.1", RTLD_NOW);
592 system("rm ld-musl-aarch64.so.1");
593 } else {
594 system("cp /system/lib/ld-musl-arm.so.1 .");
595 handle = dlopen("./ld-musl-arm.so.1", RTLD_NOW);
596 system("rm ./ld-musl-arm.so.1");
597 }
598 EXPECT_PTRNE(__FUNCTION__, handle, 0);
599 }
600
601 TEST_FUNC test_cases[] = {
602 dlopen_randomization_0100,
603 dlopen_randomization_0200,
604 dlopen_randomization_0300,
605 dlopen_randomization_0400,
606 dlopen_randomization_0600,
607 dlopen_ext_randomization_0100,
608 dlopen_ext_randomization_0200,
609 dlopen_ext_randomization_0300,
610 dlopen_ext_randomization_0400,
611 dlopen_ext_randomization_0600,
612 dlopen_ext_randomization_0800,
613 dlopen_ext_randomization_0900,
614 dlopen_ns_randomization_0100,
615 dlopen_ns_randomization_0200,
616 dlopen_ns_randomization_0300,
617 dlopen_ns_randomization_0400,
618 dlopen_ns_randomization_0600,
619 dlsym_randomization_0300,
620 dlsym_randomization_0400,
621 dlsym_randomization_0500,
622 dlsym_randomization_0600,
623 dlsym_randomization_0700,
624 dlclose_randomization_0100,
625 dlopen_randomization_0800,
626 dlopen_randomization_0900,
627 };
628
main(int argc,char * argv[])629 int main(int argc, char *argv[])
630 {
631 size_t case_counts = sizeof(test_cases) / sizeof(TEST_FUNC);
632 for (size_t case_num = 0; case_num < case_counts; case_num++) {
633 test_cases[case_num]();
634 }
635 return t_status;
636 }