• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #define _GNU_SOURCE
2 #define SYSCALL_NO_TLS 1
3 
4 #include "dynlink.h"
5 
6 #include <stdbool.h>
7 #include <stdlib.h>
8 #include <stdarg.h>
9 #include <stddef.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <stdint.h>
13 #include <elf.h>
14 #include <sys/mman.h>
15 #include <limits.h>
16 #include <fcntl.h>
17 #include <sys/stat.h>
18 #include <errno.h>
19 #include <link.h>
20 #include <setjmp.h>
21 #include <pthread.h>
22 #include <ctype.h>
23 #include <dlfcn.h>
24 #include <semaphore.h>
25 #include <sys/membarrier.h>
26 #include <sys/time.h>
27 #include <time.h>
28 #include <sys/prctl.h>
29 #include <sys/queue.h>
30 
31 #include "cfi.h"
32 #include "dlfcn_ext.h"
33 #include "dynlink_rand.h"
34 #include "ld_log.h"
35 #include "libc.h"
36 #include "musl_fdsan.h"
37 #include "namespace.h"
38 #include "ns_config.h"
39 #include "pthread_impl.h"
40 #include "fork_impl.h"
41 #include "strops.h"
42 #include "trace/trace_marker.h"
43 
44 #ifdef OHOS_ENABLE_PARAMETER
45 #include "sys_param.h"
46 #endif
47 #ifdef LOAD_ORDER_RANDOMIZATION
48 #include "zip_archive.h"
49 #endif
50 
51 #define malloc __libc_malloc
52 #define calloc __libc_calloc
53 #define realloc __libc_realloc
54 #define free __libc_free
55 
56 static void error(const char *, ...);
57 
58 #define MAXP2(a,b) (-(-(a)&-(b)))
59 #define ALIGN(x,y) ((x)+(y)-1 & -(y))
60 #define GNU_HASH_FILTER(ght, ghm, gho)                \
61 	const size_t *bloomwords = (const void *)(ght+4); \
62 	size_t f = bloomwords[gho & (ght[2]-1)];          \
63 	if (!(f & ghm)) continue;                         \
64 	f >>= (gh >> ght[3]) % (8 * sizeof f);            \
65 	if (!(f & 1)) continue;
66 
67 #define container_of(p,t,m) ((t*)((char *)(p)-offsetof(t,m)))
68 #define countof(a) ((sizeof (a))/(sizeof (a)[0]))
69 #define DSO_FLAGS_NODELETE 0x1
70 
71 #ifdef HANDLE_RANDOMIZATION
72 #define NEXT_DYNAMIC_INDEX 2
73 #define MIN_DEPS_COUNT 2
74 #define NAME_INDEX_ZERO 0
75 #define NAME_INDEX_ONE 1
76 #define NAME_INDEX_TWO 2
77 #define NAME_INDEX_THREE 3
78 #define TLS_CNT_INCREASE 3
79 #define INVALID_FD_INHIBIT_FURTHER_SEARCH (-2)
80 #endif
81 
82 #define PARENTS_BASE_CAPACITY 8
83 #define RELOC_CAN_SEARCH_DSO_BASE_CAPACITY 32
84 #define ANON_NAME_MAX_LEN 70
85 
86 #define KPMD_SIZE (1UL << 21)
87 #define HUGEPAGES_SUPPORTED_STR_SIZE (32)
88 
89 #ifdef UNIT_TEST_STATIC
90     #define UT_STATIC
91 #else
92     #define UT_STATIC static
93 #endif
94 
95 /* Used for dlclose */
96 #define UNLOAD_NR_DLOPEN_CHECK 1
97 #define UNLOAD_COMMON_CHECK 2
98 #define UNLOAD_ALL_CHECK 3
99 struct dso_entry {
100 	struct dso *dso;
101 	TAILQ_ENTRY(dso_entry) entries;
102 };
103 
104 struct debug {
105 	int ver;
106 	void *head;
107 	void (*bp)(void);
108 	int state;
109 	void *base;
110 };
111 
112 struct reserved_address_params {
113 	void* start_addr;
114 	size_t reserved_size;
115 	bool must_use_reserved;
116 	bool reserved_address_recursive;
117 #ifdef LOAD_ORDER_RANDOMIZATION
118 	struct dso *target;
119 #endif
120 };
121 
122 typedef void (*stage3_func)(size_t *, size_t *, size_t *);
123 
124 static struct builtin_tls {
125 	char c[8];
126 	struct pthread pt;
127 	void *space[16];
128 } builtin_tls[1];
129 #define MIN_TLS_ALIGN offsetof(struct builtin_tls, pt)
130 
131 #define ADDEND_LIMIT 4096
132 static size_t *saved_addends, *apply_addends_to;
133 static bool g_is_asan;
134 static struct dso ldso;
135 static struct dso *head, *tail, *fini_head, *syms_tail, *lazy_head;
136 static struct dso_debug_info *debug_tail = NULL;
137 static char *env_path, *sys_path;
138 static unsigned long long gencnt;
139 static int runtime;
140 static int ldd_mode;
141 static int ldso_fail;
142 static int noload;
143 static int shutting_down;
144 static jmp_buf *rtld_fail;
145 static pthread_rwlock_t lock;
146 static struct debug debug;
147 static struct tls_module *tls_tail;
148 static size_t tls_cnt, tls_offset, tls_align = MIN_TLS_ALIGN;
149 static size_t static_tls_cnt;
150 static pthread_mutex_t init_fini_lock;
151 static pthread_cond_t ctor_cond;
152 static struct dso *builtin_deps[2];
153 static struct dso *const no_deps[1];
154 static struct dso *builtin_ctor_queue[4];
155 static struct dso **main_ctor_queue;
156 static struct fdpic_loadmap *app_loadmap;
157 static struct fdpic_dummy_loadmap app_dummy_loadmap;
158 
159 struct debug *_dl_debug_addr = &debug;
160 
161 extern hidden int __malloc_replaced;
162 
163 hidden void (*const __init_array_start)(void)=0, (*const __fini_array_start)(void)=0;
164 
165 extern hidden void (*const __init_array_end)(void), (*const __fini_array_end)(void);
166 
167 #ifdef USE_GWP_ASAN
168 extern bool init_gwp_asan_by_libc(bool force_init);
169 #endif
170 
171 weak_alias(__init_array_start, __init_array_end);
172 weak_alias(__fini_array_start, __fini_array_end);
173 #ifdef DFX_SIGNAL_LIBC
__InstallSignalHandler()174 UT_STATIC void __InstallSignalHandler()
175 {
176 }
177 weak_alias(__InstallSignalHandler, DFX_InstallSignalHandler);
178 #endif
179 
180 #ifdef HANDLE_RANDOMIZATION
181 static int do_dlclose(struct dso *p);
182 #endif
183 
184 #ifdef LOAD_ORDER_RANDOMIZATION
185 static bool map_library_header(struct loadtask *task);
186 static bool task_map_library(struct loadtask *task, struct reserved_address_params *reserved_params);
187 static bool resolve_fd_to_realpath(struct loadtask *task);
188 static bool load_library_header(struct loadtask *task);
189 static void task_load_library(struct loadtask *task, struct reserved_address_params *reserved_params);
190 static void preload_direct_deps(struct dso *p, ns_t *namespace, struct loadtasks *tasks);
191 static void unmap_preloaded_sections(struct loadtasks *tasks);
192 static void preload_deps(struct dso *p, struct loadtasks *tasks);
193 static void run_loadtasks(struct loadtasks *tasks, struct reserved_address_params *reserved_params);
194 UT_STATIC void assign_tls(struct dso *p);
195 UT_STATIC void load_preload(char *s, ns_t *ns, struct loadtasks *tasks);
196 static void open_library_by_path(const char *name, const char *s, struct loadtask *task, struct zip_info *z_info);
197 static void handle_asan_path_open_by_task(int fd, const char *name, ns_t *namespace, struct loadtask *task, struct zip_info *z_info);
198 #endif
199 
200 extern int __close(int fd);
201 
202 /* Sharing relro */
203 static void handle_relro_sharing(struct dso *p, const dl_extinfo *extinfo, ssize_t *relro_fd_offset);
204 
205 /* asan path open */
206 int handle_asan_path_open(int fd, const char *name, ns_t *namespace, char *buf, size_t buf_size);
207 
208 static void set_bss_vma_name(char *path_name, void *addr, size_t zeromap_size);
209 
210 static void find_and_set_bss_name(struct dso *p);
211 
212 /* lldb debug function */
213 static void sync_with_debugger();
214 static void notify_addition_to_debugger(struct dso *p);
215 static void notify_remove_to_debugger(struct dso *p);
216 static void add_dso_info_to_debug_map(struct dso *p);
217 static void remove_dso_info_from_debug_map(struct dso *p);
218 
219 /* add namespace function */
220 static void get_sys_path(ns_configor *conf);
221 static void dlclose_ns(struct dso *p);
get_app_path(char * path,size_t size)222 static bool get_app_path(char *path, size_t size)
223 {
224 	int l = 0;
225 	l = readlink("/proc/self/exe", path, size);
226 	if (l < 0 || l >= size) {
227 		LD_LOGD("get_app_path readlink failed!");
228 		return false;
229 	}
230 	path[l] = 0;
231 	LD_LOGD("get_app_path path:%{public}s.", path);
232 	return true;
233 }
234 
init_default_namespace(struct dso * app)235 static void init_default_namespace(struct dso *app)
236 {
237 	ns_t *default_ns = get_default_ns();
238 	memset(default_ns, 0, sizeof *default_ns);
239 	ns_set_name(default_ns, NS_DEFAULT_NAME);
240 	if (env_path) ns_set_env_paths(default_ns, env_path);
241 	ns_set_lib_paths(default_ns, sys_path);
242 	ns_set_separated(default_ns, false);
243 	app->namespace = default_ns;
244 	ns_add_dso(default_ns, app);
245 	LD_LOGD("init_default_namespace default_namespace:"
246 			"nsname: default ,"
247 			"lib_paths:%{public}s ,"
248 			"env_path:%{public}s ,"
249 			"separated: false.",
250 			sys_path, env_path);
251 	return;
252 }
253 
set_ns_attrs(ns_t * ns,ns_configor * conf)254 UT_STATIC void set_ns_attrs(ns_t *ns, ns_configor *conf)
255 {
256 	if(!ns || !conf) {
257 		return;
258 	}
259 
260 	char *lib_paths, *asan_lib_paths, *permitted_paths, *asan_permitted_paths, *allowed_libs;
261 
262 	ns_set_separated(ns, conf->get_separated(ns->ns_name));
263 
264 	lib_paths = conf->get_lib_paths(ns->ns_name);
265 	if (lib_paths) ns_set_lib_paths(ns, lib_paths);
266 
267 	asan_lib_paths = conf->get_asan_lib_paths(ns->ns_name);
268 	if (asan_lib_paths) ns_set_asan_lib_paths(ns, asan_lib_paths);
269 
270 	permitted_paths = conf->get_permitted_paths(ns->ns_name);
271 	if (permitted_paths) ns_set_permitted_paths(ns, permitted_paths);
272 
273 	asan_permitted_paths = conf->get_asan_permitted_paths(ns->ns_name);
274 	if (asan_permitted_paths) ns_set_asan_permitted_paths(ns, asan_permitted_paths);
275 
276 	allowed_libs = conf->get_allowed_libs(ns->ns_name);
277 	if (allowed_libs) ns_set_allowed_libs(ns, allowed_libs);
278 
279 	LD_LOGD("set_ns_attrs :"
280 			"ns_name: %{public}s ,"
281 			"separated:%{public}d ,"
282 			"lib_paths:%{public}s ,"
283 			"asan_lib_paths:%{public}s ,"
284 			"permitted_paths:%{public}s ,"
285 			"asan_permitted_paths:%{public}s ,"
286 			"allowed_libs: %{public}s .",
287 			ns->ns_name, ns->separated, ns->lib_paths, ns->asan_lib_paths, permitted_paths,
288 			asan_permitted_paths, allowed_libs);
289 }
290 
set_ns_inherits(ns_t * ns,ns_configor * conf)291 UT_STATIC void set_ns_inherits(ns_t *ns, ns_configor *conf)
292 {
293 	if(!ns || !conf) {
294 		return;
295 	}
296 
297 	strlist *inherits = conf->get_inherits(ns->ns_name);
298 	if (inherits) {
299 		for (size_t i=0; i<inherits->num; i++) {
300 			ns_t *inherited_ns = find_ns_by_name(inherits->strs[i]);
301 			if (inherited_ns) {
302 				char *shared_libs = conf->get_inherit_shared_libs(ns->ns_name, inherited_ns->ns_name);
303 				ns_add_inherit(ns, inherited_ns, shared_libs);
304 				LD_LOGD("set_ns_inherits :"
305 						"ns_name: %{public}s ,"
306 						"separated:%{public}d ,"
307 						"lib_paths:%{public}s ,"
308 						"asan_lib_paths:%{public}s ,",
309 						inherited_ns->ns_name, inherited_ns->separated, inherited_ns->lib_paths,
310 						inherited_ns->asan_lib_paths);
311 			}
312 		}
313 		strlist_free(inherits);
314 	} else {
315 		LD_LOGD("set_ns_inherits inherits is NULL!");
316 	}
317 }
318 
init_namespace(struct dso * app)319 static void init_namespace(struct dso *app)
320 {
321 	char app_path[PATH_MAX+1];
322 	if (!get_app_path(app_path, sizeof app_path)) {
323 		strcpy(app_path, app->name);
324 	}
325 	char *t = strrchr(app_path, '/');
326 	if (t) {
327 		*t = 0;
328 	} else {
329 		app_path[0] = '.';
330 		app_path[1] = 0;
331 	}
332 
333 	nslist *nsl = nslist_init();
334 	ns_configor *conf = configor_init();
335 	char file_path[sizeof "/etc/ld-musl-namespace-" + sizeof (LDSO_ARCH) + sizeof ".ini" + 1] = {0};
336 	(void)snprintf(file_path, sizeof file_path, "/etc/ld-musl-namespace-%s.ini", LDSO_ARCH);
337 	LD_LOGI("init_namespace file_path:%{public}s", file_path);
338 	trace_marker_reset();
339 	trace_marker_begin(HITRACE_TAG_MUSL, "parse linker config", file_path);
340 	int ret = conf->parse(file_path, app_path);
341 	if (ret < 0) {
342 		LD_LOGE("init_namespace ini file parse failed!");
343 		/* Init_default_namespace is required even if the ini file parsing fails */
344 		if (!sys_path) get_sys_path(conf);
345 		init_default_namespace(app);
346 		configor_free();
347 		trace_marker_end(HITRACE_TAG_MUSL);
348 		return;
349 	}
350 
351 	/* sys_path needs to be parsed through ini file */
352 	if (!sys_path) get_sys_path(conf);
353 	init_default_namespace(app);
354 
355 	/* Init default namespace */
356 	ns_t *d_ns = get_default_ns();
357 	set_ns_attrs(d_ns, conf);
358 
359 	/* Init other namespace */
360 	if (!nsl) {
361 		LD_LOGE("init nslist fail!");
362 		configor_free();
363 		trace_marker_end(HITRACE_TAG_MUSL);
364 		return;
365 	}
366 	strlist *s_ns = conf->get_namespaces();
367 	if (s_ns) {
368 		for (size_t i=0; i<s_ns->num; i++) {
369 			ns_t *ns = ns_alloc();
370 			ns_set_name(ns, s_ns->strs[i]);
371 			set_ns_attrs(ns, conf);
372 			ns_add_dso(ns, app);
373 			nslist_add_ns(ns);
374 		}
375 		strlist_free(s_ns);
376 	}
377 	/* Set inherited namespace */
378 	set_ns_inherits(d_ns, conf);
379 	for (size_t i = 0; i < nsl->num; i++) {
380 		set_ns_inherits(nsl->nss[i], conf);
381 	}
382 	configor_free();
383 	trace_marker_end(HITRACE_TAG_MUSL);
384 	return;
385 }
386 
387 /* Compute load address for a virtual address in a given dso. */
388 #if DL_FDPIC
laddr(const struct dso * p,size_t v)389 void *laddr(const struct dso *p, size_t v)
390 {
391 	size_t j=0;
392 	if (!p->loadmap) return p->base + v;
393 	for (j=0; v-p->loadmap->segs[j].p_vaddr >= p->loadmap->segs[j].p_memsz; j++);
394 	return (void *)(v - p->loadmap->segs[j].p_vaddr + p->loadmap->segs[j].addr);
395 }
laddr_pg(const struct dso * p,size_t v)396 static void *laddr_pg(const struct dso *p, size_t v)
397 {
398 	size_t j=0;
399 	size_t pgsz = PAGE_SIZE;
400 	if (!p->loadmap) return p->base + v;
401 	for (j=0; ; j++) {
402 		size_t a = p->loadmap->segs[j].p_vaddr;
403 		size_t b = a + p->loadmap->segs[j].p_memsz;
404 		a &= -pgsz;
405 		b += pgsz-1;
406 		b &= -pgsz;
407 		if (v-a<b-a) break;
408 	}
409 	return (void *)(v - p->loadmap->segs[j].p_vaddr + p->loadmap->segs[j].addr);
410 }
fdbarrier(void * p)411 static void (*fdbarrier(void *p))()
412 {
413 	void (*fd)();
414 	__asm__("" : "=r"(fd) : "0"(p));
415 	return fd;
416 }
417 #define fpaddr(p, v) fdbarrier((&(struct funcdesc){ \
418 	laddr(p, v), (p)->got }))
419 #else
420 #define laddr(p, v) (void *)((p)->base + (v))
421 #define laddr_pg(p, v) laddr(p, v)
422 #define fpaddr(p, v) ((void (*)())laddr(p, v))
423 #endif
424 
decode_vec(size_t * v,size_t * a,size_t cnt)425 static void decode_vec(size_t *v, size_t *a, size_t cnt)
426 {
427 	size_t i;
428 	for (i=0; i<cnt; i++) a[i] = 0;
429 	for (; v[0]; v+=2) if (v[0]-1<cnt-1) {
430 		if (v[0] < 8*sizeof(long)) {
431 			a[0] |= 1UL<<v[0];
432 		}
433 		a[v[0]] = v[1];
434 	}
435 }
436 
search_vec(size_t * v,size_t * r,size_t key)437 static int search_vec(size_t *v, size_t *r, size_t key)
438 {
439 	for (; v[0]!=key; v+=2)
440 		if (!v[0]) return 0;
441 	*r = v[1];
442 	return 1;
443 }
444 
check_vna_hash(Verdef * def,int16_t vsym,uint32_t vna_hash)445 UT_STATIC int check_vna_hash(Verdef *def, int16_t vsym, uint32_t vna_hash)
446 {
447 	int matched = 0;
448 
449 	vsym &= 0x7fff;
450 	Verdef *verdef = def;
451 	for(;;) {
452 		if ((verdef->vd_ndx & 0x7fff) == vsym) {
453 			if (vna_hash == verdef->vd_hash) {
454 				matched = 1;
455 			}
456 			break;
457 		}
458 		if (matched) {
459 			break;
460 		}
461 		if (verdef->vd_next == 0) {
462 			break;
463 		}
464 		verdef = (Verdef *)((char *)verdef + verdef->vd_next);
465 	}
466 #if (LD_LOG_LEVEL & LD_LOG_DEBUG)
467 	if (!matched) {
468 		LD_LOGD("check_vna_hash no matched found. vsym=%{public}d vna_hash=%{public}x", vsym, vna_hash);
469 	}
470 #endif
471 	return matched;
472 }
473 
check_verinfo(Verdef * def,int16_t * versym,uint32_t index,struct verinfo * verinfo,char * strings)474 UT_STATIC int check_verinfo(Verdef *def, int16_t *versym, uint32_t index, struct verinfo *verinfo, char *strings)
475 {
476 	/* if the versym and verinfo is null , then not need version. */
477 	if (!versym || !def) {
478 		if (strlen(verinfo->v) == 0) {
479 			return 1;
480 		} else {
481 			LD_LOGD("check_verinfo versym or def is null and verinfo->v exist, s:%{public}s v:%{public}s.",
482 				verinfo->s, verinfo->v);
483 			return 0;
484 		}
485 	}
486 
487 	int16_t vsym = versym[index];
488 
489 	/* find the verneed symbol. */
490 	if (verinfo->use_vna_hash) {
491 		if (vsym != VER_NDX_LOCAL && versym != VER_NDX_GLOBAL) {
492 			return check_vna_hash(def, vsym, verinfo->vna_hash);
493 		}
494 	}
495 
496 	/* if the version length is zero and vsym not less than zero, then library hava default version symbol. */
497 	if (strlen(verinfo->v) == 0) {
498 		if (vsym >= 0) {
499 			return 1;
500 		} else {
501 			LD_LOGD("check_verinfo not default version. vsym:%{public}d s:%{public}s", vsym, verinfo->s);
502 			return 0;
503 		}
504 	}
505 
506 	/* find the version of symbol. */
507 	vsym &= 0x7fff;
508 	for (;;) {
509 		if (!(def->vd_flags & VER_FLG_BASE) && (def->vd_ndx & 0x7fff) == vsym) {
510 			break;
511 		}
512 		if (def->vd_next == 0) {
513 			return 0;
514 		}
515 		def = (Verdef *)((char *)def + def->vd_next);
516 	}
517 
518 	Verdaux *aux = (Verdaux *)((char *)def + def->vd_aux);
519 
520 	int ret = !strcmp(verinfo->v, strings + aux->vda_name);
521 #if (LD_LOG_LEVEL & LD_LOG_DEBUG)
522 	if (!ret) {
523 		LD_LOGD("check_verinfo version not match. s=%{public}s v=%{public}s vsym=%{public}d vda_name=%{public}s",
524 			verinfo->s, verinfo->v, vsym, strings + aux->vda_name);
525 	}
526 #endif
527 	return ret;
528 }
529 
sysv_hash(const char * s0)530 static struct sym_info_pair sysv_hash(const char *s0)
531 {
532 	struct sym_info_pair s_info_p;
533 	const unsigned char *s = (void *)s0;
534 	uint_fast32_t h = 0;
535 	while (*s) {
536 		h = 16*h + *s++;
537 		h ^= h>>24 & 0xf0;
538 	}
539 	s_info_p.sym_h = h & 0xfffffff;
540 	s_info_p.sym_l = (char *)s - s0;
541 	return s_info_p;
542 }
543 
gnu_hash(const char * s0)544 struct sym_info_pair gnu_hash(const char *s0)
545 {
546 	struct sym_info_pair s_info_p;
547 	const unsigned char *s = (void *)s0;
548 	uint_fast32_t h = 5381;
549 	for (; *s; s++)
550 		h += h*32 + *s;
551 	s_info_p.sym_h = h;
552 	s_info_p.sym_l = (char *)s - s0;
553 	return s_info_p;
554 }
555 
sysv_lookup(struct verinfo * verinfo,struct sym_info_pair s_info_p,struct dso * dso)556 static Sym *sysv_lookup(struct verinfo *verinfo,  struct sym_info_pair s_info_p, struct dso *dso)
557 {
558 	size_t i;
559 	uint32_t h = s_info_p.sym_h;
560 	Sym *syms = dso->syms;
561 	Elf_Symndx *hashtab = dso->hashtab;
562 	char *strings = dso->strings;
563 	for (i=hashtab[2+h%hashtab[0]]; i; i=hashtab[2+hashtab[0]+i]) {
564 		if ((!dso->versym || (dso->versym[i] & 0x7fff) >= 0)
565 			&& (!memcmp(verinfo->s, strings+syms[i].st_name, s_info_p.sym_l))) {
566 			if (!check_verinfo(dso->verdef, dso->versym, i, verinfo, dso->strings)) {
567 				continue;
568 			}
569 
570 			return syms+i;
571 		}
572 
573 	}
574 	LD_LOGD("sysv_lookup not find the symbol, "
575 		"so:%{public}s s:%{public}s v:%{public}s use_vna_hash:%{public}d vna_hash:%{public}x",
576 		dso->name, verinfo->s, verinfo->v, verinfo->use_vna_hash, verinfo->vna_hash);
577 	return 0;
578 }
579 
gnu_lookup(struct sym_info_pair s_info_p,uint32_t * hashtab,struct dso * dso,struct verinfo * verinfo)580 static Sym *gnu_lookup(struct sym_info_pair s_info_p, uint32_t *hashtab, struct dso *dso, struct verinfo *verinfo)
581 {
582 	uint32_t h1 = s_info_p.sym_h;
583 	uint32_t nbuckets = hashtab[0];
584 	uint32_t *buckets = hashtab + 4 + hashtab[2]*(sizeof(size_t)/4);
585 	uint32_t i = buckets[h1 % nbuckets];
586 
587 	if (!i) {
588 		LD_LOGD("gnu_lookup symbol not found (bloom filter), so:%{public}s s:%{public}s", dso->name, verinfo->s);
589 		return 0;
590 	}
591 
592 	uint32_t *hashval = buckets + nbuckets + (i - hashtab[1]);
593 
594 	for (h1 |= 1; ; i++) {
595 		uint32_t h2 = *hashval++;
596 		if ((h1 == (h2|1)) && (!dso->versym || (dso->versym[i] & 0x7fff) >= 0)
597 			&& !memcmp(verinfo->s, dso->strings + dso->syms[i].st_name, s_info_p.sym_l)) {
598 			if (!check_verinfo(dso->verdef, dso->versym, i, verinfo, dso->strings)) {
599 				continue;
600 			}
601 
602 			return dso->syms+i;
603 		}
604 
605 		if (h2 & 1) break;
606 	}
607 
608 	LD_LOGD("gnu_lookup symbol not found, "
609 		"so:%{public}s s:%{public}s v:%{public}s use_vna_hash:%{public}d vna_hash:%{public}x",
610 		dso->name, verinfo->s, verinfo->v, verinfo->use_vna_hash, verinfo->vna_hash);
611 	return 0;
612 }
613 
check_sym_accessible(struct dso * dso,ns_t * ns)614 static bool check_sym_accessible(struct dso *dso, ns_t *ns)
615 {
616 	if (!dso || !dso->namespace || !ns) {
617 		LD_LOGD("check_sym_accessible invalid parameter!");
618 		return false;
619 	}
620 	if (dso->namespace == ns) {
621 		return true;
622 	}
623 	for (int i = 0; i < dso->parents_count; i++) {
624 		if (dso->parents[i]->namespace == ns) {
625 			return true;
626 		}
627 	}
628 	LD_LOGD(
629 		"check_sym_accessible dso name [%{public}s] ns_name [%{public}s] not accessible!", dso->name, ns->ns_name);
630 	return false;
631 }
632 
is_dso_accessible(struct dso * dso,ns_t * ns)633 static inline bool is_dso_accessible(struct dso *dso, ns_t *ns)
634 {
635 	if (dso->namespace == ns) {
636 		return true;
637 	}
638 	for (int i = 0; i < dso->parents_count; i++) {
639 		if (dso->parents[i]->namespace == ns) {
640 			return true;
641 		}
642 	}
643 	LD_LOGD(
644 		"check_sym_accessible dso name [%{public}s] ns_name [%{public}s] not accessible!", dso->name, ns->ns_name);
645 	return false;
646 }
647 
find_dso_parent(struct dso * p,struct dso * target)648 static int find_dso_parent(struct dso *p, struct dso *target)
649 {
650 	int index = -1;
651 	for (int i = 0; i < p->parents_count; i++) {
652 		if (p->parents[i] == target) {
653 			index = i;
654 			break;
655 		}
656 	}
657 	return index;
658 }
659 
add_dso_parent(struct dso * p,struct dso * parent)660 static void add_dso_parent(struct dso *p, struct dso *parent)
661 {
662 	int index = find_dso_parent(p, parent);
663 	if (index != -1) {
664 		return;
665 	}
666 	if (p->parents_count + 1 > p->parents_capacity) {
667 		if (p->parents_capacity == 0) {
668 			p->parents = (struct dso **)malloc(sizeof(struct dso *) * PARENTS_BASE_CAPACITY);
669 			if (!p->parents) {
670 				return;
671 			}
672 			p->parents_capacity = PARENTS_BASE_CAPACITY;
673 		} else {
674 			struct dso ** realloced = (struct dso **)realloc(
675 				p->parents, sizeof(struct dso *) * (p->parents_capacity + PARENTS_BASE_CAPACITY));
676 			if (!realloced) {
677 				return;
678 			}
679 			p->parents = realloced;
680 			p->parents_capacity += PARENTS_BASE_CAPACITY;
681 		}
682 	}
683 	p->parents[p->parents_count] = parent;
684 	p->parents_count++;
685 }
686 
remove_dso_parent(struct dso * p,struct dso * parent)687 static void remove_dso_parent(struct dso *p, struct dso *parent)
688 {
689 	int index = find_dso_parent(p, parent);
690 	if (index == -1) {
691 		return;
692 	}
693 	int i;
694 	for (i = 0; i < index; i++) {
695 		p->parents[i] = p->parents[i];
696 	}
697 	for (i = index; i < p->parents_count - 1; i++) {
698 		p->parents[i] = p->parents[i + 1];
699 	}
700 	p->parents_count--;
701 }
702 
add_reloc_can_search_dso(struct dso * p,struct dso * can_search_so)703 static void add_reloc_can_search_dso(struct dso *p, struct dso *can_search_so)
704 {
705 	if (p->reloc_can_search_dso_count + 1 > p->reloc_can_search_dso_capacity) {
706 		if (p->reloc_can_search_dso_capacity == 0) {
707 			p->reloc_can_search_dso_list =
708 				(struct dso **)malloc(sizeof(struct dso *) * RELOC_CAN_SEARCH_DSO_BASE_CAPACITY);
709 			if (!p->reloc_can_search_dso_list) {
710 				return;
711 			}
712 			p->reloc_can_search_dso_capacity = RELOC_CAN_SEARCH_DSO_BASE_CAPACITY;
713 		} else {
714 			struct dso ** realloced = (struct dso **)realloc(
715 				p->reloc_can_search_dso_list,
716 				sizeof(struct dso *) * (p->reloc_can_search_dso_capacity + RELOC_CAN_SEARCH_DSO_BASE_CAPACITY));
717 			if (!realloced) {
718 				return;
719 			}
720 			p->reloc_can_search_dso_list = realloced;
721 			p->reloc_can_search_dso_capacity += RELOC_CAN_SEARCH_DSO_BASE_CAPACITY;
722 		}
723 	}
724 	p->reloc_can_search_dso_list[p->reloc_can_search_dso_count] = can_search_so;
725 	p->reloc_can_search_dso_count++;
726 }
727 
free_reloc_can_search_dso(struct dso * p)728 static void free_reloc_can_search_dso(struct dso *p)
729 {
730 	if (p->reloc_can_search_dso_list) {
731 		free(p->reloc_can_search_dso_list);
732 		p->reloc_can_search_dso_list = NULL;
733 		p->reloc_can_search_dso_count = 0;
734 		p->reloc_can_search_dso_capacity = 0;
735 	}
736 }
737 
738 /* The list of so that can be accessed during relocation include:
739  * - The is_global flag of the so is true which means accessible by default.
740  *   Global so includes exe, ld preload so and ldso.
741  * - We only check whether ns is accessible for the so if is_reloc_head_so_dep is true.
742  *
743  *   How to set is_reloc_head_so_dep:
744  *   When dlopen A, we set is_reloc_head_so_dep to true for
745  *   all direct and indirect dependent sos of A, including A itself. */
add_can_search_so_list_in_dso(struct dso * dso_relocating,struct dso * start_check_dso)746 static void add_can_search_so_list_in_dso(struct dso *dso_relocating, struct dso *start_check_dso) {
747 	struct dso *p = start_check_dso;
748 	for (; p; p = p->syms_next) {
749 		if (p->is_global) {
750 			add_reloc_can_search_dso(dso_relocating, p);
751 			continue;
752 		}
753 
754 		if (p->is_reloc_head_so_dep) {
755 			if (dso_relocating->namespace && check_sym_accessible(p, dso_relocating->namespace)) {
756 				add_reloc_can_search_dso(dso_relocating, p);
757 			}
758 		}
759 	}
760 
761 	return;
762 }
763 
764 #define OK_TYPES (1<<STT_NOTYPE | 1<<STT_OBJECT | 1<<STT_FUNC | 1<<STT_COMMON | 1<<STT_TLS)
765 #define OK_BINDS (1<<STB_GLOBAL | 1<<STB_WEAK | 1<<STB_GNU_UNIQUE)
766 
767 #ifndef ARCH_SYM_REJECT_UND
768 #define ARCH_SYM_REJECT_UND(s) 0
769 #endif
770 
771 #if defined(__GNUC__)
772 __attribute__((always_inline))
773 #endif
774 
find_sym_impl(struct dso * dso,struct verinfo * verinfo,struct sym_info_pair s_info_g,int need_def,ns_t * ns)775 struct symdef find_sym_impl(
776 	struct dso *dso, struct verinfo *verinfo, struct sym_info_pair s_info_g, int need_def, ns_t *ns)
777 {
778 	Sym *sym;
779 	struct sym_info_pair s_info_s = {0, 0};
780 	uint32_t *ght;
781 	uint32_t gh = s_info_g.sym_h;
782 	uint32_t gho = gh / (8 * sizeof(size_t));
783 	size_t ghm = 1ul << gh % (8 * sizeof(size_t));
784 	struct symdef def = {0};
785 	if (ns && !check_sym_accessible(dso, ns))
786 		return def;
787 
788 	if ((ght = dso->ghashtab)) {
789 		const size_t *bloomwords = (const void *)(ght + 4);
790 		size_t f = bloomwords[gho & (ght[2] - 1)];
791 		if (!(f & ghm))
792 			return def;
793 
794 		f >>= (gh >> ght[3]) % (8 * sizeof f);
795 		if (!(f & 1))
796 			return def;
797 
798 		sym = gnu_lookup(s_info_g, ght, dso, verinfo);
799 	} else {
800 		if (!s_info_s.sym_h)
801 			s_info_s = sysv_hash(verinfo->s);
802 
803 		sym = sysv_lookup(verinfo, s_info_s, dso);
804 	}
805 
806 	if (!sym)
807 		return def;
808 
809 	if (!sym->st_shndx)
810 		if (need_def || (sym->st_info & 0xf) == STT_TLS || ARCH_SYM_REJECT_UND(sym))
811 			return def;
812 
813 	if (!sym->st_value)
814 		if ((sym->st_info & 0xf) != STT_TLS)
815 			return def;
816 
817 	if (!(1 << (sym->st_info & 0xf) & OK_TYPES))
818 		return def;
819 
820 	if (!(1 << (sym->st_info >> 4) & OK_BINDS))
821 		return def;
822 
823 	def.sym = sym;
824 	def.dso = dso;
825 	return def;
826 }
827 
find_sym2(struct dso * dso,struct verinfo * verinfo,int need_def,int use_deps,ns_t * ns)828 static inline struct symdef find_sym2(struct dso *dso, struct verinfo *verinfo, int need_def, int use_deps, ns_t *ns)
829 {
830 	struct sym_info_pair s_info_g = gnu_hash(verinfo->s);
831 	struct sym_info_pair s_info_s = {0, 0};
832 	uint32_t gh = s_info_g.sym_h, gho = gh / (8*sizeof(size_t)), *ght;
833 	size_t ghm = 1ul << gh % (8*sizeof(size_t));
834 	struct symdef def = {0};
835 	struct dso **deps = use_deps ? dso->deps : 0;
836 	for (; dso; dso=use_deps ? *deps++ : dso->syms_next) {
837 		Sym *sym;
838 		if (ns && !check_sym_accessible(dso, ns)) {
839 			continue;
840 		}
841 		if ((ght = dso->ghashtab)) {
842 			GNU_HASH_FILTER(ght, ghm, gho)
843 			sym = gnu_lookup(s_info_g, ght, dso, verinfo);
844 		} else {
845 			if (!s_info_s.sym_h) s_info_s = sysv_hash(verinfo->s);
846 			sym = sysv_lookup(verinfo, s_info_s, dso);
847 		}
848 
849 		if (!sym) continue;
850 		if (!sym->st_shndx)
851 			if (need_def || (sym->st_info&0xf) == STT_TLS
852 				|| ARCH_SYM_REJECT_UND(sym))
853 				continue;
854 		if (!sym->st_value)
855 			if ((sym->st_info&0xf) != STT_TLS)
856 				continue;
857 		if (!(1<<(sym->st_info&0xf) & OK_TYPES)) continue;
858 		if (!(1<<(sym->st_info>>4) & OK_BINDS)) continue;
859 		def.sym = sym;
860 		def.dso = dso;
861 		break;
862 	}
863 	return def;
864 }
865 
find_sym_by_deps(struct dso * dso,struct verinfo * verinfo,int need_def,ns_t * ns)866 static inline struct symdef find_sym_by_deps(struct dso *dso, struct verinfo *verinfo, int need_def, ns_t *ns)
867 {
868 	struct sym_info_pair s_info_g = gnu_hash(verinfo->s);
869 	struct sym_info_pair s_info_s = {0, 0};
870 	uint32_t h = 0, gh = s_info_g.sym_h, gho = gh / (8*sizeof(size_t)), *ght;
871 	size_t ghm = 1ul << gh % (8*sizeof(size_t));
872 	struct symdef def = {0};
873 	struct dso **deps = dso->deps;
874 	for (; dso; dso=*deps++) {
875 		Sym *sym;
876 		if (!is_dso_accessible(dso, ns)) {
877 			continue;
878 		}
879 		if ((ght = dso->ghashtab)) {
880 			GNU_HASH_FILTER(ght, ghm, gho)
881 			sym = gnu_lookup(s_info_g, ght, dso, verinfo);
882 		} else {
883 			if (!s_info_s.sym_h) s_info_s = sysv_hash(verinfo->s);
884 			sym = sysv_lookup(verinfo, s_info_s, dso);
885 		}
886 
887 		if (!sym) continue;
888 		if (!sym->st_shndx)
889 			if (need_def || (sym->st_info&0xf) == STT_TLS
890 				|| ARCH_SYM_REJECT_UND(sym))
891 				continue;
892 		if (!sym->st_value)
893 			if ((sym->st_info&0xf) != STT_TLS)
894 				continue;
895 		if (!(1<<(sym->st_info&0xf) & OK_TYPES)) continue;
896 		if (!(1<<(sym->st_info>>4) & OK_BINDS)) continue;
897 		def.sym = sym;
898 		def.dso = dso;
899 		break;
900 	}
901 	return def;
902 }
903 
find_sym_by_saved_so_list(int sym_type,struct dso * dso,struct verinfo * verinfo,int need_def,struct dso * dso_relocating)904 static inline struct symdef find_sym_by_saved_so_list(
905 	int sym_type, struct dso *dso, struct verinfo *verinfo, int need_def, struct dso *dso_relocating)
906 {
907 	struct sym_info_pair s_info_g = gnu_hash(verinfo->s);
908 	struct sym_info_pair s_info_s = {0, 0};
909 	uint32_t gh = s_info_g.sym_h, gho = gh / (8 * sizeof(size_t)), *ght;
910 	size_t ghm = 1ul << gh % (8 * sizeof(size_t));
911 	struct symdef def = {0};
912 	// skip head dso.
913 	int start_search_index = sym_type==REL_COPY ? 1 : 0;
914 	struct dso *dso_searching = 0;
915 	for (int i = start_search_index; i < dso_relocating->reloc_can_search_dso_count; i++) {
916 		dso_searching = dso_relocating->reloc_can_search_dso_list[i];
917 		Sym *sym;
918 		if ((ght = dso_searching->ghashtab)) {
919 			GNU_HASH_FILTER(ght, ghm, gho)
920 			sym = gnu_lookup(s_info_g, ght, dso_searching, verinfo);
921 		} else {
922 			if (!s_info_s.sym_h) s_info_s = sysv_hash(verinfo->s);
923 			sym = sysv_lookup(verinfo, s_info_s, dso_searching);
924 		}
925 		if (!sym) continue;
926 		if (!sym->st_shndx)
927 			if (need_def || (sym->st_info&0xf) == STT_TLS
928 				|| ARCH_SYM_REJECT_UND(sym))
929 				continue;
930 		if (!sym->st_value)
931 			if ((sym->st_info&0xf) != STT_TLS)
932 				continue;
933 		if (!(1<<(sym->st_info&0xf) & OK_TYPES)) continue;
934 		if (!(1<<(sym->st_info>>4) & OK_BINDS)) continue;
935 		def.sym = sym;
936 		def.dso = dso_searching;
937 		break;
938 	}
939 	return def;
940 }
941 
find_sym(struct dso * dso,const char * s,int need_def)942 static struct symdef find_sym(struct dso *dso, const char *s, int need_def)
943 {
944 	struct verinfo verinfo = { .s = s, .v = "", .use_vna_hash = false };
945 	return find_sym2(dso, &verinfo, need_def, 0, NULL);
946 }
947 
get_vna_hash(struct dso * dso,int sym_index,uint32_t * vna_hash)948 static bool get_vna_hash(struct dso *dso, int sym_index, uint32_t *vna_hash)
949 {
950 	if (!dso->versym || !dso->verneed) {
951 		return false;
952 	}
953 
954 	uint16_t vsym = dso->versym[sym_index];
955 	if (vsym == VER_NDX_LOCAL || vsym == VER_NDX_GLOBAL) {
956 		return false;
957 	}
958 
959 	bool result = false;
960 	Verneed *verneed = dso->verneed;
961 	Vernaux *vernaux;
962 	vsym &= 0x7fff;
963 
964 	for(;;) {
965 		vernaux = (Vernaux *)((char *)verneed + verneed->vn_aux);
966 
967 		for (size_t cnt = 0; cnt < verneed->vn_cnt; cnt++) {
968 			if ((vernaux->vna_other & 0x7fff) == vsym) {
969 				result = true;
970 				*vna_hash = vernaux->vna_hash;
971 				break;
972 			}
973 
974 			vernaux = (Vernaux *)((char *)vernaux + vernaux->vna_next);
975 		}
976 
977 		if (result) {
978 			break;
979 		}
980 
981 		if (verneed->vn_next == 0) {
982 			break;
983 		}
984 
985 		verneed = (Verneed *)((char *)verneed + verneed->vn_next);
986 	}
987 	return result;
988 }
989 
get_verinfo(struct dso * dso,int sym_index,struct verinfo * vinfo)990 static void get_verinfo(struct dso *dso, int sym_index, struct verinfo *vinfo)
991 {
992 	char *strings = dso->strings;
993 	// try to get version number from .gnu.version
994 	int16_t vsym = dso->versym[sym_index];
995 	Verdef *verdef = dso->verdef;
996 	vsym &= 0x7fff;
997 	if (!verdef) {
998 		return;
999 	}
1000 	int version_found = 0;
1001 	for (;;) {
1002 		if (!verdef) {
1003 			break;
1004 		}
1005 		if (!(verdef->vd_flags & VER_FLG_BASE) && (verdef->vd_ndx & 0x7fff) == vsym) {
1006 			version_found = 1;
1007 			break;
1008 		}
1009 		if (verdef->vd_next == 0) {
1010 			break;
1011 		}
1012 		verdef = (Verdef *)((char *)verdef + verdef->vd_next);
1013 	}
1014 	if (version_found) {
1015 		Verdaux *aux = (Verdaux *)((char *)verdef + verdef->vd_aux);
1016 		if (aux && aux->vda_name && strings && (dso->strings + aux->vda_name)) {
1017 			vinfo->v = dso->strings + aux->vda_name;
1018 		}
1019 	}
1020 }
1021 
do_relocs(struct dso * dso,size_t * rel,size_t rel_size,size_t stride)1022 static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stride)
1023 {
1024 	unsigned char *base = dso->base;
1025 	Sym *syms = dso->syms;
1026 	char *strings = dso->strings;
1027 	Sym *sym;
1028 	const char *name;
1029 	void *ctx;
1030 	int type;
1031 	int sym_index;
1032 	struct symdef def;
1033 	size_t *reloc_addr;
1034 	size_t sym_val;
1035 	size_t tls_val;
1036 	size_t addend;
1037 	int skip_relative = 0, reuse_addends = 0, save_slot = 0;
1038 
1039 	if (dso == &ldso) {
1040 		/* Only ldso's REL table needs addend saving/reuse. */
1041 		if (rel == apply_addends_to)
1042 			reuse_addends = 1;
1043 		skip_relative = 1;
1044 	}
1045 
1046 	for (; rel_size; rel+=stride, rel_size-=stride*sizeof(size_t)) {
1047 		if (skip_relative && IS_RELATIVE(rel[1], dso->syms)) continue;
1048 		type = R_TYPE(rel[1]);
1049 		if (type == REL_NONE) continue;
1050 		reloc_addr = laddr(dso, rel[0]);
1051 
1052 		if (stride > 2) {
1053 			addend = rel[2];
1054 		} else if (type==REL_GOT || type==REL_PLT|| type==REL_COPY) {
1055 			addend = 0;
1056 		} else if (reuse_addends) {
1057 			/* Save original addend in stage 2 where the dso
1058 			 * chain consists of just ldso; otherwise read back
1059 			 * saved addend since the inline one was clobbered. */
1060 			if (head==&ldso)
1061 				saved_addends[save_slot] = *reloc_addr;
1062 			addend = saved_addends[save_slot++];
1063 		} else {
1064 			addend = *reloc_addr;
1065 		}
1066 
1067 		sym_index = R_SYM(rel[1]);
1068 		if (sym_index) {
1069 			sym = syms + sym_index;
1070 			name = strings + sym->st_name;
1071 			ctx = type==REL_COPY ? head->syms_next : head;
1072 			struct verinfo vinfo = { .s = name, .v = ""};
1073 
1074 			vinfo.use_vna_hash = get_vna_hash(dso, sym_index, &vinfo.vna_hash);
1075 			if (!vinfo.use_vna_hash && dso->versym && (dso->versym[sym_index] & 0x7fff) >= 0) {
1076 				get_verinfo(dso, sym_index, &vinfo);
1077 			}
1078 			if (dso->cache_sym_index == sym_index) {
1079 				def = (struct symdef){ .dso = dso->cache_dso, .sym = dso->cache_sym };
1080 			} else {
1081 				def = (sym->st_info>>4) == STB_LOCAL
1082 					? (struct symdef){ .dso = dso, .sym = sym }
1083 					: dso != &ldso ? find_sym_by_saved_so_list(type, ctx, &vinfo, type==REL_PLT, dso)
1084 					: find_sym2(ctx, &vinfo, type==REL_PLT, 0, dso->namespace);
1085 				dso->cache_sym_index = sym_index;
1086 				dso->cache_dso = def.dso;
1087 				dso->cache_sym = def.sym;
1088 			}
1089 
1090 			if (!def.sym && (sym->st_shndx != SHN_UNDEF
1091 				|| sym->st_info>>4 != STB_WEAK)) {
1092 				if (dso->lazy && (type==REL_PLT || type==REL_GOT)) {
1093 					dso->lazy[3*dso->lazy_cnt+0] = rel[0];
1094 					dso->lazy[3*dso->lazy_cnt+1] = rel[1];
1095 					dso->lazy[3*dso->lazy_cnt+2] = addend;
1096 					dso->lazy_cnt++;
1097 					continue;
1098 				}
1099 				LD_LOGE("relocating failed: symbol not found. "
1100 					"dso=%{public}s s=%{public}s use_vna_hash=%{public}d van_hash=%{public}x",
1101 					dso->name, name, vinfo.use_vna_hash, vinfo.vna_hash);
1102 				error("Error relocating %s: %s: symbol not found",
1103 					dso->name, name);
1104 				if (runtime) longjmp(*rtld_fail, 1);
1105 				continue;
1106 			}
1107 		} else {
1108 			sym = 0;
1109 			def.sym = 0;
1110 			def.dso = dso;
1111 		}
1112 
1113 		sym_val = def.sym ? (size_t)laddr(def.dso, def.sym->st_value) : 0;
1114 		tls_val = def.sym ? def.sym->st_value : 0;
1115 
1116 		if ((type == REL_TPOFF || type == REL_TPOFF_NEG)
1117 			&& def.dso->tls_id > static_tls_cnt) {
1118 			error("Error relocating %s: %s: initial-exec TLS "
1119 				"resolves to dynamic definition in %s",
1120 				dso->name, name, def.dso->name);
1121 			longjmp(*rtld_fail, 1);
1122 		}
1123 
1124 		switch(type) {
1125 		case REL_OFFSET:
1126 			addend -= (size_t)reloc_addr;
1127 		case REL_SYMBOLIC:
1128 		case REL_GOT:
1129 		case REL_PLT:
1130 			*reloc_addr = sym_val + addend;
1131 			break;
1132 		case REL_USYMBOLIC:
1133 			memcpy(reloc_addr, &(size_t){sym_val + addend}, sizeof(size_t));
1134 			break;
1135 		case REL_RELATIVE:
1136 			*reloc_addr = (size_t)base + addend;
1137 			break;
1138 		case REL_SYM_OR_REL:
1139 			if (sym) *reloc_addr = sym_val + addend;
1140 			else *reloc_addr = (size_t)base + addend;
1141 			break;
1142 		case REL_COPY:
1143 			memcpy(reloc_addr, (void *)sym_val, sym->st_size);
1144 			break;
1145 		case REL_OFFSET32:
1146 			*(uint32_t *)reloc_addr = sym_val + addend
1147 				- (size_t)reloc_addr;
1148 			break;
1149 		case REL_FUNCDESC:
1150 			*reloc_addr = def.sym ? (size_t)(def.dso->funcdescs
1151 				+ (def.sym - def.dso->syms)) : 0;
1152 			break;
1153 		case REL_FUNCDESC_VAL:
1154 			if ((sym->st_info&0xf) == STT_SECTION) *reloc_addr += sym_val;
1155 			else *reloc_addr = sym_val;
1156 			reloc_addr[1] = def.sym ? (size_t)def.dso->got : 0;
1157 			break;
1158 		case REL_DTPMOD:
1159 			*reloc_addr = def.dso->tls_id;
1160 			break;
1161 		case REL_DTPOFF:
1162 			*reloc_addr = tls_val + addend - DTP_OFFSET;
1163 			break;
1164 #ifdef TLS_ABOVE_TP
1165 		case REL_TPOFF:
1166 			*reloc_addr = tls_val + def.dso->tls.offset + TPOFF_K + addend;
1167 			break;
1168 #else
1169 		case REL_TPOFF:
1170 			*reloc_addr = tls_val - def.dso->tls.offset + addend;
1171 			break;
1172 		case REL_TPOFF_NEG:
1173 			*reloc_addr = def.dso->tls.offset - tls_val + addend;
1174 			break;
1175 #endif
1176 		case REL_TLSDESC:
1177 			if (stride<3) addend = reloc_addr[1];
1178 			if (def.dso->tls_id > static_tls_cnt) {
1179 				struct td_index *new = malloc(sizeof *new);
1180 				if (!new) {
1181 					error(
1182 					"Error relocating %s: cannot allocate TLSDESC for %s",
1183 					dso->name, sym ? name : "(local)" );
1184 					longjmp(*rtld_fail, 1);
1185 				}
1186 				new->next = dso->td_index;
1187 				dso->td_index = new;
1188 				new->args[0] = def.dso->tls_id;
1189 				new->args[1] = tls_val + addend - DTP_OFFSET;
1190 				reloc_addr[0] = (size_t)__tlsdesc_dynamic;
1191 				reloc_addr[1] = (size_t)new;
1192 			} else {
1193 				reloc_addr[0] = (size_t)__tlsdesc_static;
1194 #ifdef TLS_ABOVE_TP
1195 				reloc_addr[1] = tls_val + def.dso->tls.offset
1196 					+ TPOFF_K + addend;
1197 #else
1198 				reloc_addr[1] = tls_val - def.dso->tls.offset
1199 					+ addend;
1200 #endif
1201 			}
1202 #ifdef TLSDESC_BACKWARDS
1203 			/* Some archs (32-bit ARM at least) invert the order of
1204 			 * the descriptor members. Fix them up here. */
1205 			size_t tmp = reloc_addr[0];
1206 			reloc_addr[0] = reloc_addr[1];
1207 			reloc_addr[1] = tmp;
1208 #endif
1209 			break;
1210 		default:
1211 			error("Error relocating %s: unsupported relocation type %d",
1212 				dso->name, type);
1213 			if (runtime) longjmp(*rtld_fail, 1);
1214 			continue;
1215 		}
1216 	}
1217 }
1218 
redo_lazy_relocs()1219 static void redo_lazy_relocs()
1220 {
1221 	struct dso *p = lazy_head, *next;
1222 	lazy_head = 0;
1223 	for (; p; p=next) {
1224 		next = p->lazy_next;
1225 		size_t size = p->lazy_cnt*3*sizeof(size_t);
1226 		p->lazy_cnt = 0;
1227 		do_relocs(p, p->lazy, size, 3);
1228 		if (p->lazy_cnt) {
1229 			p->lazy_next = lazy_head;
1230 			lazy_head = p;
1231 		} else {
1232 			free(p->lazy);
1233 			p->lazy = 0;
1234 			p->lazy_next = 0;
1235 		}
1236 	}
1237 }
1238 
1239 /* A huge hack: to make up for the wastefulness of shared libraries
1240  * needing at least a page of dirty memory even if they have no global
1241  * data, we reclaim the gaps at the beginning and end of writable maps
1242  * and "donate" them to the heap. */
1243 
reclaim(struct dso * dso,size_t start,size_t end)1244 static void reclaim(struct dso *dso, size_t start, size_t end)
1245 {
1246 	if (start >= dso->relro_start && start < dso->relro_end) start = dso->relro_end;
1247 	if (end   >= dso->relro_start && end   < dso->relro_end) end = dso->relro_start;
1248 	if (start >= end) return;
1249 	char *base = laddr_pg(dso, start);
1250 	__malloc_donate(base, base+(end-start));
1251 }
1252 
reclaim_gaps(struct dso * dso)1253 static void reclaim_gaps(struct dso *dso)
1254 {
1255 	Phdr *ph = dso->phdr;
1256 	size_t phcnt = dso->phnum;
1257 
1258 	for (; phcnt--; ph=(void *)((char *)ph+dso->phentsize)) {
1259 		if (ph->p_type!=PT_LOAD) continue;
1260 		if ((ph->p_flags&(PF_R|PF_W))!=(PF_R|PF_W)) continue;
1261 		reclaim(dso, ph->p_vaddr & -PAGE_SIZE, ph->p_vaddr);
1262 		reclaim(dso, ph->p_vaddr+ph->p_memsz,
1263 			ph->p_vaddr+ph->p_memsz+PAGE_SIZE-1 & -PAGE_SIZE);
1264 	}
1265 }
1266 
read_loop(int fd,void * p,size_t n)1267 static ssize_t read_loop(int fd, void *p, size_t n)
1268 {
1269 	for (size_t i=0; i<n; ) {
1270 		ssize_t l = read(fd, (char *)p+i, n-i);
1271 		if (l<0) {
1272 			if (errno==EINTR) continue;
1273 			else return -1;
1274 		}
1275 		if (l==0) return i;
1276 		i += l;
1277 	}
1278 	return n;
1279 }
1280 
mmap_fixed(void * p,size_t n,int prot,int flags,int fd,off_t off)1281 UT_STATIC void *mmap_fixed(void *p, size_t n, int prot, int flags, int fd, off_t off)
1282 {
1283 	static int no_map_fixed;
1284 	char *q;
1285 	if (!n) return p;
1286 	if (!no_map_fixed) {
1287 		q = mmap(p, n, prot, flags|MAP_FIXED, fd, off);
1288 		if (!DL_NOMMU_SUPPORT || q != MAP_FAILED || errno != EINVAL)
1289 			return q;
1290 		no_map_fixed = 1;
1291 	}
1292 	/* Fallbacks for MAP_FIXED failure on NOMMU kernels. */
1293 	if (flags & MAP_ANONYMOUS) {
1294 		memset(p, 0, n);
1295 		return p;
1296 	}
1297 	ssize_t r;
1298 	if (lseek(fd, off, SEEK_SET) < 0) return MAP_FAILED;
1299 	for (q=p; n; q+=r, off+=r, n-=r) {
1300 		r = read(fd, q, n);
1301 		if (r < 0 && errno != EINTR) return MAP_FAILED;
1302 		if (!r) {
1303 			memset(q, 0, n);
1304 			break;
1305 		}
1306 	}
1307 	return p;
1308 }
1309 
unmap_library(struct dso * dso)1310 UT_STATIC void unmap_library(struct dso *dso)
1311 {
1312 	if (dso->loadmap) {
1313 		size_t i;
1314 		for (i=0; i<dso->loadmap->nsegs; i++) {
1315 			if (!dso->loadmap->segs[i].p_memsz)
1316 				continue;
1317 			if (!is_dlclose_debug_enable()) {
1318 				munmap((void *)dso->loadmap->segs[i].addr,
1319 					dso->loadmap->segs[i].p_memsz);
1320 			} else {
1321 				(void)mprotect((void *)dso->loadmap->segs[i].addr,
1322 					dso->loadmap->segs[i].p_memsz, PROT_NONE);
1323 			}
1324 		}
1325 		free(dso->loadmap);
1326 	} else if (dso->map && dso->map_len) {
1327 		if (!is_dlclose_debug_enable()) {
1328 			munmap(dso->map, dso->map_len);
1329 		} else {
1330 			mprotect(dso->map, dso->map_len, PROT_NONE);
1331 		}
1332 	}
1333 }
1334 
get_random(void * buf,size_t buflen)1335 UT_STATIC bool get_random(void *buf, size_t buflen)
1336 {
1337 	int ret;
1338 	int fd = open("/dev/urandom", O_RDONLY);
1339 	if (fd < 0) {
1340 		return false;
1341 	}
1342 
1343 	ret = read(fd, buf, buflen);
1344 	if (ret < 0) {
1345 		close(fd);
1346 		return false;
1347 	}
1348 
1349 	close(fd);
1350 	return true;
1351 }
1352 
fill_random_data(void * buf,size_t buflen)1353 UT_STATIC void fill_random_data(void *buf, size_t buflen)
1354 {
1355 	uint64_t x;
1356 	int i;
1357 	int pos = 0;
1358 	struct timespec ts;
1359 	/* Try to use urandom to get the random number first */
1360 	if (!get_random(buf, buflen)) {
1361 		/* Can't get random number from /dev/urandom, generate from addr based on ASLR and time */
1362 		for (i = 1; i <= (buflen / sizeof(x)); i++) {
1363 			(void)clock_gettime(CLOCK_REALTIME, &ts);
1364 			x = (((uint64_t)get_random) << 32) ^ (uint64_t)fill_random_data ^ ts.tv_nsec;
1365 			memcpy((char *)buf + pos, &x, sizeof(x));
1366 			pos += sizeof(x);
1367 		}
1368 	}
1369 	return;
1370 }
1371 
get_transparent_hugepages_supported(void)1372 static bool get_transparent_hugepages_supported(void)
1373 {
1374 	int fd = -1;
1375 	ssize_t read_size = 0;
1376 	bool enable = false;
1377 	char buf[HUGEPAGES_SUPPORTED_STR_SIZE] = {'0'};
1378 
1379 	fd = open("/sys/kernel/mm/transparent_hugepage/enabled", O_RDONLY);
1380 	if (fd < 0)
1381 		goto done;
1382 
1383 	read_size = read(fd, buf, HUGEPAGES_SUPPORTED_STR_SIZE - 1);
1384 	if (read_size < 0)
1385 		goto close_fd;
1386 
1387 	buf[HUGEPAGES_SUPPORTED_STR_SIZE - 1] = '\0';
1388 	if (strstr(buf, "[never]") == NULL)
1389 		enable = true;
1390 
1391 close_fd:
1392 	close(fd);
1393 done:
1394 	return enable;
1395 }
1396 
phdr_table_get_maxinum_alignment(Phdr * phdr_table,size_t phdr_count)1397 static size_t phdr_table_get_maxinum_alignment(Phdr *phdr_table, size_t phdr_count)
1398 {
1399 #if defined(__LP64__)
1400 	size_t maxinum_alignment = PAGE_SIZE;
1401 	size_t i = 0;
1402 
1403 	for (i = 0; i < phdr_count; ++i) {
1404 		const Phdr *phdr = &phdr_table[i];
1405 
1406 		/* p_align must be 0, 1, or a positive, integral power of two */
1407 		if ((phdr->p_type != PT_LOAD) || ((phdr->p_align & (phdr->p_align - 1)) != 0))
1408 			continue;
1409 
1410 		if (phdr->p_align > maxinum_alignment)
1411 			maxinum_alignment = phdr->p_align;
1412 	}
1413 
1414 	return maxinum_alignment;
1415 #else
1416 	return PAGE_SIZE;
1417 #endif
1418 }
1419 
map_library(int fd,struct dso * dso,struct reserved_address_params * reserved_params)1420 UT_STATIC void *map_library(int fd, struct dso *dso, struct reserved_address_params *reserved_params)
1421 {
1422 	Ehdr buf[(896+sizeof(Ehdr))/sizeof(Ehdr)];
1423 	void *allocated_buf=0;
1424 	size_t phsize;
1425 	size_t addr_min=SIZE_MAX, addr_max=0, map_len;
1426 	size_t this_min, this_max;
1427 	size_t nsegs = 0;
1428 	off_t off_start;
1429 	Ehdr *eh;
1430 	Phdr *ph, *ph0;
1431 	unsigned prot;
1432 	unsigned char *map=MAP_FAILED, *base;
1433 	size_t dyn=0;
1434 	size_t tls_image=0;
1435 	size_t i;
1436 	int map_flags = MAP_PRIVATE;
1437 	size_t start_addr;
1438 	size_t start_alignment = PAGE_SIZE;
1439 	bool hugepage_enabled = false;
1440 
1441 	ssize_t l = read(fd, buf, sizeof buf);
1442 	eh = buf;
1443 	if (l<0) return 0;
1444 	if (l<sizeof *eh || (eh->e_type != ET_DYN && eh->e_type != ET_EXEC))
1445 		goto noexec;
1446 	phsize = eh->e_phentsize * eh->e_phnum;
1447 	if (phsize > sizeof buf - sizeof *eh) {
1448 		allocated_buf = malloc(phsize);
1449 		if (!allocated_buf) return 0;
1450 		l = pread(fd, allocated_buf, phsize, eh->e_phoff);
1451 		if (l < 0) goto error;
1452 		if (l != phsize) goto noexec;
1453 		ph = ph0 = allocated_buf;
1454 	} else if (eh->e_phoff + phsize > l) {
1455 		l = pread(fd, buf+1, phsize, eh->e_phoff);
1456 		if (l < 0) goto error;
1457 		if (l != phsize) goto noexec;
1458 		ph = ph0 = (void *)(buf + 1);
1459 	} else {
1460 		ph = ph0 = (void *)((char *)buf + eh->e_phoff);
1461 	}
1462 	for (i=eh->e_phnum; i; i--, ph=(void *)((char *)ph+eh->e_phentsize)) {
1463 		if (ph->p_type == PT_DYNAMIC) {
1464 			dyn = ph->p_vaddr;
1465 		} else if (ph->p_type == PT_TLS) {
1466 			tls_image = ph->p_vaddr;
1467 			dso->tls.align = ph->p_align;
1468 			dso->tls.len = ph->p_filesz;
1469 			dso->tls.size = ph->p_memsz;
1470 		} else if (ph->p_type == PT_GNU_RELRO) {
1471 			dso->relro_start = ph->p_vaddr & -PAGE_SIZE;
1472 			dso->relro_end = (ph->p_vaddr + ph->p_memsz) & -PAGE_SIZE;
1473 		} else if (ph->p_type == PT_GNU_STACK) {
1474 			if (!runtime && ph->p_memsz > __default_stacksize) {
1475 				__default_stacksize =
1476 					ph->p_memsz < DEFAULT_STACK_MAX ?
1477 					ph->p_memsz : DEFAULT_STACK_MAX;
1478 			}
1479 		}
1480 		if (ph->p_type != PT_LOAD) continue;
1481 		nsegs++;
1482 		if (ph->p_vaddr < addr_min) {
1483 			addr_min = ph->p_vaddr;
1484 			off_start = ph->p_offset;
1485 			prot = (((ph->p_flags&PF_R) ? PROT_READ : 0) |
1486 				((ph->p_flags&PF_W) ? PROT_WRITE: 0) |
1487 				((ph->p_flags&PF_X) ? PROT_EXEC : 0));
1488 		}
1489 		if (ph->p_vaddr+ph->p_memsz > addr_max) {
1490 			addr_max = ph->p_vaddr+ph->p_memsz;
1491 		}
1492 	}
1493 	if (!dyn) goto noexec;
1494 	if (DL_FDPIC && !(eh->e_flags & FDPIC_CONSTDISP_FLAG)) {
1495 		dso->loadmap = calloc(1, sizeof *dso->loadmap
1496 			+ nsegs * sizeof *dso->loadmap->segs);
1497 		if (!dso->loadmap) goto error;
1498 		dso->loadmap->nsegs = nsegs;
1499 		for (ph=ph0, i=0; i<nsegs; ph=(void *)((char *)ph+eh->e_phentsize)) {
1500 			if (ph->p_type != PT_LOAD) continue;
1501 			prot = (((ph->p_flags&PF_R) ? PROT_READ : 0) |
1502 				((ph->p_flags&PF_W) ? PROT_WRITE: 0) |
1503 				((ph->p_flags&PF_X) ? PROT_EXEC : 0));
1504 			map = mmap(0, ph->p_memsz + (ph->p_vaddr & PAGE_SIZE-1),
1505 				prot, MAP_PRIVATE,
1506 				fd, ph->p_offset & -PAGE_SIZE);
1507 			if (map == MAP_FAILED) {
1508 				unmap_library(dso);
1509 				goto error;
1510 			}
1511 			dso->loadmap->segs[i].addr = (size_t)map +
1512 				(ph->p_vaddr & PAGE_SIZE-1);
1513 			dso->loadmap->segs[i].p_vaddr = ph->p_vaddr;
1514 			dso->loadmap->segs[i].p_memsz = ph->p_memsz;
1515 			i++;
1516 			if (prot & PROT_WRITE) {
1517 				size_t brk = (ph->p_vaddr & PAGE_SIZE-1)
1518 					+ ph->p_filesz;
1519 				size_t pgbrk = brk + PAGE_SIZE-1 & -PAGE_SIZE;
1520 				size_t pgend = brk + ph->p_memsz - ph->p_filesz
1521 					+ PAGE_SIZE-1 & -PAGE_SIZE;
1522 				if (pgend > pgbrk && mmap_fixed(map+pgbrk,
1523 					pgend-pgbrk, prot,
1524 					MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS,
1525 					-1, off_start) == MAP_FAILED)
1526 					goto error;
1527 				memset(map + brk, 0, pgbrk-brk);
1528 			}
1529 		}
1530 		map = (void *)dso->loadmap->segs[0].addr;
1531 		map_len = 0;
1532 		goto done_mapping;
1533 	}
1534 	addr_max += PAGE_SIZE-1;
1535 	addr_max &= -PAGE_SIZE;
1536 	addr_min &= -PAGE_SIZE;
1537 	off_start &= -PAGE_SIZE;
1538 	map_len = addr_max - addr_min + off_start;
1539 	start_addr = addr_min;
1540 
1541 	hugepage_enabled = get_transparent_hugepages_supported();
1542 	if (hugepage_enabled) {
1543 		size_t maxinum_alignment = phdr_table_get_maxinum_alignment(ph0, eh->e_phnum);
1544 
1545 		start_alignment = maxinum_alignment == KPMD_SIZE ? KPMD_SIZE : PAGE_SIZE;
1546 	}
1547 
1548 	if (reserved_params) {
1549 		if (map_len > reserved_params->reserved_size) {
1550 			if (reserved_params->must_use_reserved) {
1551 				goto error;
1552 			}
1553 		} else {
1554 			start_addr = ((size_t)reserved_params->start_addr - 1 + PAGE_SIZE) & -PAGE_SIZE;
1555 			map_flags |= MAP_FIXED;
1556 		}
1557 	}
1558 
1559 	/* we will find a mapping_align aligned address as the start of dso
1560 	 * so we need a tmp_map_len as map_len + mapping_align to make sure
1561 	 * we have enough space to shift the dso to the correct location. */
1562 	size_t mapping_align = start_alignment > LIBRARY_ALIGNMENT ? start_alignment : LIBRARY_ALIGNMENT;
1563 	size_t tmp_map_len = ALIGN(map_len, mapping_align) + mapping_align - PAGE_SIZE;
1564 
1565 	/* if reserved_params exists, we should use start_addr as prefered result to do the mmap operation */
1566 	if (reserved_params) {
1567 		map = DL_NOMMU_SUPPORT
1568 			? mmap((void *)start_addr, map_len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)
1569 			: mmap((void *)start_addr, map_len, prot, map_flags, fd, off_start);
1570 		if (map == MAP_FAILED) {
1571 			goto error;
1572 		}
1573 		if (reserved_params && map_len < reserved_params->reserved_size) {
1574 			reserved_params->reserved_size -= (map_len + (start_addr - (size_t)reserved_params->start_addr));
1575 			reserved_params->start_addr = (void *)((uint8_t *)map + map_len);
1576 		}
1577 	/* if reserved_params does not exist, we should use real_map as prefered result to do the mmap operation */
1578 	} else {
1579 		/* use tmp_map_len to mmap enough space for the dso with anonymous mapping */
1580 		unsigned char *temp_map = mmap((void *)NULL, tmp_map_len, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
1581 		if (temp_map == MAP_FAILED) {
1582 			goto error;
1583 		}
1584 
1585 		/* find the mapping_align aligned address */
1586 		unsigned char *real_map = (unsigned char*)ALIGN((uintptr_t)temp_map, mapping_align);
1587 
1588 		/* mummap the space we mmap before so that we can mmap correct space again */
1589 		munmap(temp_map, tmp_map_len);
1590 
1591 		map = DL_NOMMU_SUPPORT
1592 			? mmap(real_map, map_len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)
1593 			/* use map_len to mmap correct space for the dso with file mapping */
1594 			: mmap(real_map, map_len, prot, map_flags, fd, off_start);
1595 		if (map == MAP_FAILED) {
1596 			goto error;
1597 		}
1598 	}
1599 	dso->map = map;
1600 	dso->map_len = map_len;
1601 	/* If the loaded file is not relocatable and the requested address is
1602 	 * not available, then the load operation must fail. */
1603 	if (eh->e_type != ET_DYN && addr_min && map!=(void *)addr_min) {
1604 		errno = EBUSY;
1605 		goto error;
1606 	}
1607 	base = map - addr_min;
1608 	dso->phdr = 0;
1609 	dso->phnum = 0;
1610 	for (ph=ph0, i=eh->e_phnum; i; i--, ph=(void *)((char *)ph+eh->e_phentsize)) {
1611 		if (ph->p_type == PT_OHOS_RANDOMDATA) {
1612 			fill_random_data((void *)(ph->p_vaddr + base), ph->p_memsz);
1613 			continue;
1614 		}
1615 		if (ph->p_type != PT_LOAD) continue;
1616 		/* Check if the programs headers are in this load segment, and
1617 		 * if so, record the address for use by dl_iterate_phdr. */
1618 		if (!dso->phdr && eh->e_phoff >= ph->p_offset
1619 			&& eh->e_phoff+phsize <= ph->p_offset+ph->p_filesz) {
1620 			dso->phdr = (void *)(base + ph->p_vaddr
1621 				+ (eh->e_phoff-ph->p_offset));
1622 			dso->phnum = eh->e_phnum;
1623 			dso->phentsize = eh->e_phentsize;
1624 		}
1625 		this_min = ph->p_vaddr & -PAGE_SIZE;
1626 		this_max = ph->p_vaddr+ph->p_memsz+PAGE_SIZE-1 & -PAGE_SIZE;
1627 		off_start = ph->p_offset & -PAGE_SIZE;
1628 		prot = (((ph->p_flags&PF_R) ? PROT_READ : 0) |
1629 			((ph->p_flags&PF_W) ? PROT_WRITE: 0) |
1630 			((ph->p_flags&PF_X) ? PROT_EXEC : 0));
1631 		/* Reuse the existing mapping for the lowest-address LOAD */
1632 		if ((ph->p_vaddr & -PAGE_SIZE) != addr_min || DL_NOMMU_SUPPORT)
1633 			if (mmap_fixed(base+this_min, this_max-this_min, prot, MAP_PRIVATE|MAP_FIXED, fd, off_start) == MAP_FAILED)
1634 				goto error;
1635 		if ((ph->p_flags & PF_X) && (ph->p_align == KPMD_SIZE) && hugepage_enabled)
1636 			madvise(base + this_min, this_max - this_min, MADV_HUGEPAGE);
1637 		if (ph->p_memsz > ph->p_filesz && (ph->p_flags&PF_W)) {
1638 			size_t brk = (size_t)base+ph->p_vaddr+ph->p_filesz;
1639 			size_t pgbrk = brk+PAGE_SIZE-1 & -PAGE_SIZE;
1640 			size_t zeromap_size = (size_t)base+this_max-pgbrk;
1641 			memset((void *)brk, 0, pgbrk-brk & PAGE_SIZE-1);
1642 			if (pgbrk-(size_t)base < this_max && mmap_fixed((void *)pgbrk, zeromap_size, prot, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) == MAP_FAILED)
1643 				goto error;
1644 			set_bss_vma_name(dso->name, (void *)pgbrk, zeromap_size);
1645 		}
1646 	}
1647 	for (i=0; ((size_t *)(base+dyn))[i]; i+=2)
1648 		if (((size_t *)(base+dyn))[i]==DT_TEXTREL) {
1649 			if (mprotect(map, map_len, PROT_READ|PROT_WRITE|PROT_EXEC)
1650 				&& errno != ENOSYS)
1651 				goto error;
1652 			break;
1653 		}
1654 done_mapping:
1655 	dso->base = base;
1656 	dso->dynv = laddr(dso, dyn);
1657 	if (dso->tls.size) dso->tls.image = laddr(dso, tls_image);
1658 	free(allocated_buf);
1659 	return map;
1660 noexec:
1661 	errno = ENOEXEC;
1662 error:
1663 	if (map!=MAP_FAILED) unmap_library(dso);
1664 	free(allocated_buf);
1665 	return 0;
1666 }
1667 
path_open(const char * name,const char * s,char * buf,size_t buf_size)1668 static int path_open(const char *name, const char *s, char *buf, size_t buf_size)
1669 {
1670 	size_t l;
1671 	int fd;
1672 	for (;;) {
1673 		s += strspn(s, ":\n");
1674 		l = strcspn(s, ":\n");
1675 		if (l-1 >= INT_MAX) return -1;
1676 		if (snprintf(buf, buf_size, "%.*s/%s", (int)l, s, name) < buf_size) {
1677 			if ((fd = open(buf, O_RDONLY|O_CLOEXEC))>=0) return fd;
1678 			switch (errno) {
1679 			case ENOENT:
1680 			case ENOTDIR:
1681 			case EACCES:
1682 			case ENAMETOOLONG:
1683 				break;
1684 			default:
1685 				/* Any negative value but -1 will inhibit
1686 				 * futher path search. */
1687 				return -2;
1688 			}
1689 		}
1690 		s += l;
1691 	}
1692 }
1693 
fixup_rpath(struct dso * p,char * buf,size_t buf_size)1694 UT_STATIC int fixup_rpath(struct dso *p, char *buf, size_t buf_size)
1695 {
1696 	size_t n, l;
1697 	const char *s, *t, *origin;
1698 	char *d;
1699 	if (p->rpath || !p->rpath_orig) return 0;
1700 	if (!strchr(p->rpath_orig, '$')) {
1701 		p->rpath = p->rpath_orig;
1702 		return 0;
1703 	}
1704 	n = 0;
1705 	s = p->rpath_orig;
1706 	while ((t=strchr(s, '$'))) {
1707 		if (strncmp(t, "$ORIGIN", 7) && strncmp(t, "${ORIGIN}", 9))
1708 			return 0;
1709 		s = t+1;
1710 		n++;
1711 	}
1712 	if (n > SSIZE_MAX/PATH_MAX) return 0;
1713 
1714 	if (p->kernel_mapped) {
1715 		/* $ORIGIN searches cannot be performed for the main program
1716 		 * when it is suid/sgid/AT_SECURE. This is because the
1717 		 * pathname is under the control of the caller of execve.
1718 		 * For libraries, however, $ORIGIN can be processed safely
1719 		 * since the library's pathname came from a trusted source
1720 		 * (either system paths or a call to dlopen). */
1721 		if (libc.secure)
1722 			return 0;
1723 		l = readlink("/proc/self/exe", buf, buf_size);
1724 		if (l == -1) switch (errno) {
1725 		case ENOENT:
1726 		case ENOTDIR:
1727 		case EACCES:
1728 			break;
1729 		default:
1730 			return -1;
1731 		}
1732 		if (l >= buf_size)
1733 			return 0;
1734 		buf[l] = 0;
1735 		origin = buf;
1736 	} else {
1737 		origin = p->name;
1738 	}
1739 	t = strrchr(origin, '/');
1740 	if (t) {
1741 		l = t-origin;
1742 	} else {
1743 		/* Normally p->name will always be an absolute or relative
1744 		 * pathname containing at least one '/' character, but in the
1745 		 * case where ldso was invoked as a command to execute a
1746 		 * program in the working directory, app.name may not. Fix. */
1747 		origin = ".";
1748 		l = 1;
1749 	}
1750 	/* Disallow non-absolute origins for suid/sgid/AT_SECURE. */
1751 	if (libc.secure && *origin != '/')
1752 		return 0;
1753 	p->rpath = malloc(strlen(p->rpath_orig) + n*l + 1);
1754 	if (!p->rpath) return -1;
1755 
1756 	d = p->rpath;
1757 	s = p->rpath_orig;
1758 	while ((t=strchr(s, '$'))) {
1759 		memcpy(d, s, t-s);
1760 		d += t-s;
1761 		memcpy(d, origin, l);
1762 		d += l;
1763 		/* It was determined previously that the '$' is followed
1764 		 * either by "ORIGIN" or "{ORIGIN}". */
1765 		s = t + 7 + 2*(t[1]=='{');
1766 	}
1767 	strcpy(d, s);
1768 	return 0;
1769 }
1770 
decode_dyn(struct dso * p)1771 static void decode_dyn(struct dso *p)
1772 {
1773 	size_t dyn[DYN_CNT];
1774 	size_t flags1 = 0;
1775 	decode_vec(p->dynv, dyn, DYN_CNT);
1776 	search_vec(p->dynv, &flags1, DT_FLAGS_1);
1777 	if (flags1 & DF_1_GLOBAL) {
1778 		LD_LOGI("Add DF_1_GLOBAL for %{public}s", p->name);
1779 		p->is_global = true;
1780 	}
1781 	if (flags1 & DF_1_NODELETE) {
1782 		p->flags |= DSO_FLAGS_NODELETE;
1783 	}
1784 	p->syms = laddr(p, dyn[DT_SYMTAB]);
1785 	p->strings = laddr(p, dyn[DT_STRTAB]);
1786 	if (dyn[0]&(1<<DT_HASH))
1787 		p->hashtab = laddr(p, dyn[DT_HASH]);
1788 	if (dyn[0]&(1<<DT_RPATH))
1789 		p->rpath_orig = p->strings + dyn[DT_RPATH];
1790 	if (dyn[0]&(1<<DT_RUNPATH))
1791 		p->rpath_orig = p->strings + dyn[DT_RUNPATH];
1792 	if (dyn[0]&(1<<DT_PLTGOT))
1793 		p->got = laddr(p, dyn[DT_PLTGOT]);
1794 	if (search_vec(p->dynv, dyn, DT_GNU_HASH))
1795 		p->ghashtab = laddr(p, *dyn);
1796 	if (search_vec(p->dynv, dyn, DT_VERSYM))
1797 		p->versym = laddr(p, *dyn);
1798 	if (search_vec(p->dynv, dyn, DT_VERDEF))
1799 		p->verdef = laddr(p, *dyn);
1800 	if (search_vec(p->dynv, dyn, DT_VERNEED))
1801 		p->verneed = laddr(p, *dyn);
1802 }
1803 
count_syms(struct dso * p)1804 UT_STATIC size_t count_syms(struct dso *p)
1805 {
1806 	if (p->hashtab) return p->hashtab[1];
1807 
1808 	size_t nsym, i;
1809 	uint32_t *buckets = p->ghashtab + 4 + (p->ghashtab[2]*sizeof(size_t)/4);
1810 	uint32_t *hashval;
1811 	for (i = nsym = 0; i < p->ghashtab[0]; i++) {
1812 		if (buckets[i] > nsym)
1813 			nsym = buckets[i];
1814 	}
1815 	if (nsym) {
1816 		hashval = buckets + p->ghashtab[0] + (nsym - p->ghashtab[1]);
1817 		do nsym++;
1818 		while (!(*hashval++ & 1));
1819 	}
1820 	return nsym;
1821 }
1822 
dl_mmap(size_t n)1823 static void *dl_mmap(size_t n)
1824 {
1825 	void *p;
1826 	int prot = PROT_READ|PROT_WRITE, flags = MAP_ANONYMOUS|MAP_PRIVATE;
1827 #ifdef SYS_mmap2
1828 	p = (void *)__syscall(SYS_mmap2, 0, n, prot, flags, -1, 0);
1829 #else
1830 	p = (void *)__syscall(SYS_mmap, 0, n, prot, flags, -1, 0);
1831 #endif
1832 	return (unsigned long)p > -4096UL ? 0 : p;
1833 }
1834 
makefuncdescs(struct dso * p)1835 static void makefuncdescs(struct dso *p)
1836 {
1837 	static int self_done;
1838 	size_t nsym = count_syms(p);
1839 	size_t i, size = nsym * sizeof(*p->funcdescs);
1840 
1841 	if (!self_done) {
1842 		p->funcdescs = dl_mmap(size);
1843 		self_done = 1;
1844 	} else {
1845 		p->funcdescs = malloc(size);
1846 	}
1847 	if (!p->funcdescs) {
1848 		if (!runtime) a_crash();
1849 		error("Error allocating function descriptors for %s", p->name);
1850 		longjmp(*rtld_fail, 1);
1851 	}
1852 	for (i=0; i<nsym; i++) {
1853 		if ((p->syms[i].st_info&0xf)==STT_FUNC && p->syms[i].st_shndx) {
1854 			p->funcdescs[i].addr = laddr(p, p->syms[i].st_value);
1855 			p->funcdescs[i].got = p->got;
1856 		} else {
1857 			p->funcdescs[i].addr = 0;
1858 			p->funcdescs[i].got = 0;
1859 		}
1860 	}
1861 }
1862 
get_sys_path(ns_configor * conf)1863 static void get_sys_path(ns_configor *conf)
1864 {
1865 	LD_LOGD("get_sys_path g_is_asan:%{public}d", g_is_asan);
1866 	/* Use ini file's system paths when Asan is not enabled */
1867 	if (!g_is_asan) {
1868 		sys_path = conf->get_sys_paths();
1869 	} else {
1870 		/* Use ini file's asan system paths when the Asan is enabled
1871 		 * Merge two strings when both sys_paths and asan_sys_paths are valid */
1872 		sys_path = conf->get_asan_sys_paths();
1873 		char *sys_path_default = conf->get_sys_paths();
1874 		if (!sys_path) {
1875 			sys_path = sys_path_default;
1876 		} else if (sys_path_default) {
1877 			size_t newlen = strlen(sys_path) + strlen(sys_path_default) + 2;
1878 			char *new_syspath = malloc(newlen);
1879 			memset(new_syspath, 0, newlen);
1880 			strcpy(new_syspath, sys_path);
1881 			strcat(new_syspath, ":");
1882 			strcat(new_syspath, sys_path_default);
1883 			sys_path = new_syspath;
1884 		}
1885 	}
1886 	if (!sys_path) sys_path = "/lib:/usr/local/lib:/usr/lib:/lib64";
1887 	LD_LOGD("get_sys_path sys_path:%{public}s", sys_path);
1888 }
1889 
search_dso_by_name(const char * name,const ns_t * ns)1890 static struct dso *search_dso_by_name(const char *name, const ns_t *ns) {
1891 	LD_LOGD("search_dso_by_name name:%{public}s, ns_name:%{public}s", name, ns ? ns->ns_name: "NULL");
1892 	for (size_t i = 0; i < ns->ns_dsos->num; i++){
1893 		struct dso *p = ns->ns_dsos->dsos[i];
1894 		if (p->shortname && !strcmp(p->shortname, name)) {
1895 			LD_LOGD("search_dso_by_name found name:%{public}s, ns_name:%{public}s", name, ns ? ns->ns_name: "NULL");
1896 			return p;
1897 		}
1898 	}
1899 	return NULL;
1900 }
1901 
search_dso_by_fstat(const struct stat * st,const ns_t * ns,uint64_t file_offset)1902 static struct dso *search_dso_by_fstat(const struct stat *st, const ns_t *ns, uint64_t file_offset) {
1903 	LD_LOGD("search_dso_by_fstat ns_name:%{public}s", ns ? ns->ns_name : "NULL");
1904 	for (size_t i = 0; i < ns->ns_dsos->num; i++){
1905 		struct dso *p = ns->ns_dsos->dsos[i];
1906 		if (p->dev == st->st_dev && p->ino == st->st_ino && p->file_offset == file_offset) {
1907 			LD_LOGD("search_dso_by_fstat found dev:%{public}lu, ino:%{public}lu, ns_name:%{public}s",
1908 				st->st_dev, st->st_ino, ns ? ns->ns_name : "NULL");
1909 			return p;
1910 		}
1911 	}
1912 	return NULL;
1913 }
1914 
app_has_same_name_so(const char * so_name,const ns_t * ns)1915 static inline int app_has_same_name_so(const char *so_name, const ns_t *ns)
1916 {
1917    int fd = -1;
1918    /* Only check system app. */
1919    if (((ns->flag & LOCAL_NS_PREFERED) != 0) && ns->lib_paths) {
1920        char tmp_buf[PATH_MAX+1];
1921        fd = path_open(so_name, ns->lib_paths, tmp_buf, sizeof tmp_buf);
1922    }
1923    return fd;
1924 }
1925 
1926 /* Find loaded so by name */
find_library_by_name(const char * name,const ns_t * ns,bool check_inherited)1927 static struct dso *find_library_by_name(const char *name, const ns_t *ns, bool check_inherited)
1928 {
1929 	LD_LOGD("find_library_by_name name:%{public}s, ns_name:%{public}s, check_inherited:%{public}d",
1930 		name,
1931 		ns ? ns->ns_name : "NULL",
1932 		!!check_inherited);
1933 	struct dso *p = search_dso_by_name(name, ns);
1934 	if (p) return p;
1935 	if (check_inherited && ns->ns_inherits) {
1936 		for (size_t i = 0; i < ns->ns_inherits->num; i++){
1937 			ns_inherit * inherit = ns->ns_inherits->inherits[i];
1938 			p = search_dso_by_name(name, inherit->inherited_ns);
1939 			if (p && is_sharable(inherit, name)) {
1940 			    if (app_has_same_name_so(name, ns) != -1) {
1941 			        return NULL;
1942 			    }
1943 			    return p;
1944 			}
1945 		}
1946 	}
1947 	return NULL;
1948 }
1949 /* Find loaded so by file stat */
find_library_by_fstat(const struct stat * st,const ns_t * ns,bool check_inherited,uint64_t file_offset)1950 UT_STATIC struct dso *find_library_by_fstat(const struct stat *st, const ns_t *ns, bool check_inherited, uint64_t file_offset) {
1951 	LD_LOGD("find_library_by_fstat ns_name:%{public}s, check_inherited :%{public}d",
1952 		ns ? ns->ns_name : "NULL",
1953 		!!check_inherited);
1954 	struct dso *p = search_dso_by_fstat(st, ns, file_offset);
1955 	if (p) return p;
1956 	if (check_inherited && ns->ns_inherits) {
1957 		for (size_t i = 0; i < ns->ns_inherits->num; i++){
1958 			ns_inherit *inherit = ns->ns_inherits->inherits[i];
1959 			p = search_dso_by_fstat(st, inherit->inherited_ns, file_offset);
1960 			if (p && is_sharable(inherit, p->shortname)) return p;
1961 		}
1962 	}
1963 	return NULL;
1964 }
1965 
1966 #ifndef LOAD_ORDER_RANDOMIZATION
1967 /* add namespace function */
load_library(const char * name,struct dso * needed_by,ns_t * namespace,bool check_inherited,struct reserved_address_params * reserved_params)1968 struct dso *load_library(
1969 	const char *name, struct dso *needed_by, ns_t *namespace, bool check_inherited, struct reserved_address_params *reserved_params)
1970 {
1971 	char buf[PATH_MAX+1];
1972 	const char *pathname;
1973 	unsigned char *map;
1974 	struct dso *p, temp_dso = {0};
1975 	int fd;
1976 	struct stat st;
1977 	size_t alloc_size;
1978 	int n_th = 0;
1979 	int is_self = 0;
1980 
1981 	if (!*name) {
1982 		errno = EINVAL;
1983 		return 0;
1984 	}
1985 
1986 	/* Catch and block attempts to reload the implementation itself */
1987 	if (name[0]=='l' && name[1]=='i' && name[2]=='b') {
1988 		static const char reserved[] =
1989 			"c.pthread.rt.m.dl.util.xnet.";
1990 		const char *rp, *next;
1991 		for (rp=reserved; *rp; rp=next) {
1992 			next = strchr(rp, '.') + 1;
1993 			if (strncmp(name+3, rp, next-rp) == 0)
1994 				break;
1995 		}
1996 		if (*rp) {
1997 			if (ldd_mode) {
1998 				/* Track which names have been resolved
1999 				 * and only report each one once. */
2000 				static unsigned reported;
2001 				unsigned mask = 1U<<(rp-reserved);
2002 				if (!(reported & mask)) {
2003 					reported |= mask;
2004 					dprintf(1, "\t%s => %s (%p)\n",
2005 						name, ldso.name,
2006 						ldso.base);
2007 				}
2008 			}
2009 			is_self = 1;
2010 		}
2011 	}
2012 	if (!strcmp(name, ldso.name)) is_self = 1;
2013 	if (is_self) {
2014 		if (!ldso.prev) {
2015 			tail->next = &ldso;
2016 			ldso.prev = tail;
2017 			tail = &ldso;
2018 			ldso.namespace = namespace;
2019 			ns_add_dso(namespace, &ldso);
2020 		}
2021 		return &ldso;
2022 	}
2023 	if (strchr(name, '/')) {
2024 		pathname = name;
2025 
2026 		if (!is_accessible(namespace, pathname, g_is_asan, check_inherited)) {
2027 			fd = -1;
2028 			LD_LOGD("load_library is_accessible return false,fd = -1");
2029 		} else {
2030 			fd = open(name, O_RDONLY|O_CLOEXEC);
2031 			LD_LOGD("load_library is_accessible return true, open file fd:%{public}d .", fd);
2032 		}
2033 	} else {
2034 		/* Search for the name to see if it's already loaded */
2035 		/* Search in namespace */
2036 		p = find_library_by_name(name, namespace, check_inherited);
2037 		if (p) {
2038 			LD_LOGD("load_library find_library_by_name found p, return it!");
2039 			return p;
2040 		}
2041 		if (strlen(name) > NAME_MAX) {
2042 			LD_LOGE("load_library name exceeding the maximum length, return 0!");
2043 			return 0;
2044 		}
2045 		fd = -1;
2046 		if (namespace->env_paths) fd = path_open(name, namespace->env_paths, buf, sizeof buf);
2047 		for (p = needed_by; fd == -1 && p; p = p->needed_by) {
2048 			if (fixup_rpath(p, buf, sizeof buf) < 0) {
2049 				LD_LOGD("load_library Inhibit further search,fd = -2.");
2050 				fd = -2; /* Inhibit further search. */
2051 			}
2052 			if (p->rpath) {
2053 				fd = path_open(name, p->rpath, buf, sizeof buf);
2054 				LD_LOGD("load_library  p->rpath path_open fd:%{public}d.", fd);
2055 			}
2056 
2057 		}
2058 		if (g_is_asan) {
2059 			fd = handle_asan_path_open(fd, name, namespace, buf, sizeof buf);
2060 			LD_LOGD("load_library handle_asan_path_open fd:%{public}d.", fd);
2061 		} else {
2062 			if (fd == -1 && namespace->lib_paths) {
2063 				fd = path_open(name, namespace->lib_paths, buf, sizeof buf);
2064 				LD_LOGD("load_library no asan lib_paths path_open fd:%{public}d.", fd);
2065 			}
2066 		}
2067 		pathname = buf;
2068 		LD_LOGD("load_library lib_paths pathname:%{public}s.", pathname);
2069 	}
2070 	if (fd < 0) {
2071 		if (!check_inherited || !namespace->ns_inherits) return 0;
2072 		/* Load lib in inherited namespace. Do not check inherited again.*/
2073 		for (size_t i = 0; i < namespace->ns_inherits->num; i++) {
2074 			ns_inherit *inherit = namespace->ns_inherits->inherits[i];
2075 			if (strchr(name, '/')==0 && !is_sharable(inherit, name)) continue;
2076 			p = load_library(name, needed_by, inherit->inherited_ns, false, reserved_params);
2077 			if (p) {
2078 				LD_LOGD("load_library search in inherited, found p ,inherited_ns name:%{public}s",
2079 						inherit->inherited_ns->ns_name);
2080 				return p;
2081 			}
2082 		}
2083 		return 0;
2084 	}
2085 	if (fstat(fd, &st) < 0) {
2086 		close(fd);
2087 		LD_LOGE("load_library fstat < 0,return 0!");
2088 		return 0;
2089 	}
2090 	/* Search in namespace */
2091 	p = find_library_by_fstat(&st, namespace, check_inherited, 0);
2092 	if (p) {
2093 		/* If this library was previously loaded with a
2094 		* pathname but a search found the same inode,
2095 		* setup its shortname so it can be found by name. */
2096 		if (!p->shortname && pathname != name)
2097 			p->shortname = strrchr(p->name, '/')+1;
2098 		close(fd);
2099 		LD_LOGD("load_library find_library_by_fstat, found p and return it!");
2100 		return p;
2101 	}
2102 	map = noload ? 0 : map_library(fd, &temp_dso, reserved_params);
2103 	close(fd);
2104 	if (!map) return 0;
2105 
2106 	/* Avoid the danger of getting two versions of libc mapped into the
2107 	 * same process when an absolute pathname was used. The symbols
2108 	 * checked are chosen to catch both musl and glibc, and to avoid
2109 	 * false positives from interposition-hack libraries. */
2110 	decode_dyn(&temp_dso);
2111 	if (find_sym(&temp_dso, "__libc_start_main", 1).sym &&
2112 		find_sym(&temp_dso, "stdin", 1).sym) {
2113 		unmap_library(&temp_dso);
2114 		return load_library("libc.so", needed_by, namespace, true, reserved_params);
2115 	}
2116 	/* Past this point, if we haven't reached runtime yet, ldso has
2117 	 * committed either to use the mapped library or to abort execution.
2118 	 * Unmapping is not possible, so we can safely reclaim gaps. */
2119 	if (!runtime) reclaim_gaps(&temp_dso);
2120 
2121 	/* Allocate storage for the new DSO. When there is TLS, this
2122 	 * storage must include a reservation for all pre-existing
2123 	 * threads to obtain copies of both the new TLS, and an
2124 	 * extended DTV capable of storing an additional slot for
2125 	 * the newly-loaded DSO. */
2126 	alloc_size = sizeof *p + strlen(pathname) + 1;
2127 	if (runtime && temp_dso.tls.image) {
2128 		size_t per_th = temp_dso.tls.size + temp_dso.tls.align
2129 			+ sizeof(void *) * (tls_cnt+3);
2130 		n_th = libc.threads_minus_1 + 1;
2131 		if (n_th > SSIZE_MAX / per_th) alloc_size = SIZE_MAX;
2132 		else alloc_size += n_th * per_th;
2133 	}
2134 	p = calloc(1, alloc_size);
2135 	if (!p) {
2136 		unmap_library(&temp_dso);
2137 		return 0;
2138 	}
2139 	memcpy(p, &temp_dso, sizeof temp_dso);
2140 	p->dev = st.st_dev;
2141 	p->ino = st.st_ino;
2142 	p->needed_by = needed_by;
2143 	p->name = p->buf;
2144 	p->runtime_loaded = runtime;
2145 	strcpy(p->name, pathname);
2146 	/* Add a shortname only if name arg was not an explicit pathname. */
2147 	if (pathname != name) p->shortname = strrchr(p->name, '/')+1;
2148 	if (p->tls.image) {
2149 		p->tls_id = ++tls_cnt;
2150 		tls_align = MAXP2(tls_align, p->tls.align);
2151 #ifdef TLS_ABOVE_TP
2152 		p->tls.offset = tls_offset + ( (p->tls.align-1) &
2153 			(-tls_offset + (uintptr_t)p->tls.image) );
2154 		tls_offset = p->tls.offset + p->tls.size;
2155 #else
2156 		tls_offset += p->tls.size + p->tls.align - 1;
2157 		tls_offset -= (tls_offset + (uintptr_t)p->tls.image)
2158 			& (p->tls.align-1);
2159 		p->tls.offset = tls_offset;
2160 #endif
2161 		p->new_dtv = (void *)(-sizeof(size_t) &
2162 			(uintptr_t)(p->name+strlen(p->name)+sizeof(size_t)));
2163 		p->new_tls = (void *)(p->new_dtv + n_th*(tls_cnt+1));
2164 		if (tls_tail) tls_tail->next = &p->tls;
2165 		else libc.tls_head = &p->tls;
2166 		tls_tail = &p->tls;
2167 	}
2168 
2169 	tail->next = p;
2170 	p->prev = tail;
2171 	tail = p;
2172 
2173 	/* Add dso to namespace */
2174 	p->namespace = namespace;
2175 	ns_add_dso(namespace, p);
2176 	if (runtime)
2177 		p->by_dlopen = 1;
2178 
2179 	if (DL_FDPIC) makefuncdescs(p);
2180 
2181 	if (ldd_mode) dprintf(1, "\t%s => %s (%p)\n", name, pathname, p->base);
2182 
2183 	return p;
2184 }
2185 
load_direct_deps(struct dso * p,ns_t * namespace,struct reserved_address_params * reserved_params)2186 static void load_direct_deps(struct dso *p, ns_t *namespace, struct reserved_address_params *reserved_params)
2187 {
2188 	size_t i, cnt=0;
2189 
2190 	if (p->deps) return;
2191 	/* For head, all preloads are direct pseudo-dependencies.
2192 	 * Count and include them now to avoid realloc later. */
2193 	if (p==head) for (struct dso *q=p->next; q; q=q->next)
2194 		cnt++;
2195 	for (i=0; p->dynv[i]; i+=2)
2196 		if (p->dynv[i] == DT_NEEDED) cnt++;
2197 	/* Use builtin buffer for apps with no external deps, to
2198 	 * preserve property of no runtime failure paths. */
2199 	p->deps = (p==head && cnt<2) ? builtin_deps :
2200 		calloc(cnt+1, sizeof *p->deps);
2201 	if (!p->deps) {
2202 		error("Error loading dependencies for %s", p->name);
2203 		if (runtime) longjmp(*rtld_fail, 1);
2204 	}
2205 	cnt=0;
2206 	if (p==head) for (struct dso *q=p->next; q; q=q->next)
2207 		p->deps[cnt++] = q;
2208 	for (i=0; p->dynv[i]; i+=2) {
2209 		if (p->dynv[i] != DT_NEEDED) continue;
2210 		struct dso *dep = load_library(p->strings + p->dynv[i+1], p, namespace, true, reserved_params);
2211 		LD_LOGD("loading shared library %{public}s: (needed by %{public}s)", p->strings + p->dynv[i+1], p->name);
2212 		if (!dep) {
2213 			error("Error loading shared library %s: %m (needed by %s)",
2214 				p->strings + p->dynv[i+1], p->name);
2215 			if (runtime) longjmp(*rtld_fail, 1);
2216 			continue;
2217 		}
2218 		p->deps[cnt++] = dep;
2219 	}
2220 	p->deps[cnt] = 0;
2221 	p->ndeps_direct = cnt;
2222 	for (i = 0; i < p->ndeps_direct; i++) {
2223 		add_dso_parent(p->deps[i], p);
2224 	}
2225 }
2226 
load_deps(struct dso * p,struct reserved_address_params * reserved_params)2227 static void load_deps(struct dso *p, struct reserved_address_params *reserved_params)
2228 {
2229 	if (p->deps) return;
2230 	for (; p; p=p->next)
2231 		load_direct_deps(p, p->namespace, reserved_params);
2232 }
2233 #endif
2234 
extend_bfs_deps(struct dso * p)2235 static void extend_bfs_deps(struct dso *p)
2236 {
2237 	size_t i, j, cnt, ndeps_all;
2238 	struct dso **tmp;
2239 
2240 	/* Can't use realloc if the original p->deps was allocated at
2241 	 * program entry and malloc has been replaced, or if it's
2242 	 * the builtin non-allocated trivial main program deps array. */
2243 	int no_realloc = (__malloc_replaced && !p->runtime_loaded)
2244 		|| p->deps == builtin_deps;
2245 
2246 	if (p->bfs_built) return;
2247 	ndeps_all = p->ndeps_direct;
2248 
2249 	/* Mark existing (direct) deps so they won't be duplicated. */
2250 	for (i=0; p->deps[i]; i++)
2251 		p->deps[i]->mark = 1;
2252 
2253 	/* For each dependency already in the list, copy its list of direct
2254 	 * dependencies to the list, excluding any items already in the
2255 	 * list. Note that the list this loop iterates over will grow during
2256 	 * the loop, but since duplicates are excluded, growth is bounded. */
2257 	for (i=0; p->deps[i]; i++) {
2258 		struct dso *dep = p->deps[i];
2259 		for (j=cnt=0; j<dep->ndeps_direct; j++)
2260 			if (!dep->deps[j]->mark) cnt++;
2261 		tmp = no_realloc ?
2262 			malloc(sizeof(*tmp) * (ndeps_all+cnt+1)) :
2263 			realloc(p->deps, sizeof(*tmp) * (ndeps_all+cnt+1));
2264 		if (!tmp) {
2265 			error("Error recording dependencies for %s", p->name);
2266 			if (runtime) longjmp(*rtld_fail, 1);
2267 			continue;
2268 		}
2269 		if (no_realloc) {
2270 			memcpy(tmp, p->deps, sizeof(*tmp) * (ndeps_all+1));
2271 			no_realloc = 0;
2272 		}
2273 		p->deps = tmp;
2274 		for (j=0; j<dep->ndeps_direct; j++) {
2275 			if (dep->deps[j]->mark) continue;
2276 			dep->deps[j]->mark = 1;
2277 			p->deps[ndeps_all++] = dep->deps[j];
2278 		}
2279 		p->deps[ndeps_all] = 0;
2280 	}
2281 	p->bfs_built = 1;
2282 	for (p=head; p; p=p->next)
2283 		p->mark = 0;
2284 }
2285 
2286 #ifndef LOAD_ORDER_RANDOMIZATION
load_preload(char * s,ns_t * ns)2287 static void load_preload(char *s, ns_t *ns)
2288 {
2289 	int tmp;
2290 	char *z;
2291 	for (z=s; *z; s=z) {
2292 		for (   ; *s && (isspace(*s) || *s==':'); s++);
2293 		for (z=s; *z && !isspace(*z) && *z!=':'; z++);
2294 		tmp = *z;
2295 		*z = 0;
2296 		load_library(s, 0, ns, true, NULL);
2297 		*z = tmp;
2298 	}
2299 }
2300 #endif
2301 
add_syms(struct dso * p)2302 static void add_syms(struct dso *p)
2303 {
2304 	if (!p->syms_next && syms_tail != p) {
2305 		syms_tail->syms_next = p;
2306 		syms_tail = p;
2307 	}
2308 }
2309 
revert_syms(struct dso * old_tail)2310 static void revert_syms(struct dso *old_tail)
2311 {
2312 	struct dso *p, *next;
2313 	/* Chop off the tail of the list of dsos that participate in
2314 	 * the global symbol table, reverting them to RTLD_LOCAL. */
2315 	for (p=old_tail; p; p=next) {
2316 		next = p->syms_next;
2317 		p->syms_next = 0;
2318 	}
2319 	syms_tail = old_tail;
2320 }
2321 
do_mips_relocs(struct dso * p,size_t * got)2322 static void do_mips_relocs(struct dso *p, size_t *got)
2323 {
2324 	size_t i, j, rel[2];
2325 	unsigned char *base = p->base;
2326 	i=0; search_vec(p->dynv, &i, DT_MIPS_LOCAL_GOTNO);
2327 	if (p==&ldso) {
2328 		got += i;
2329 	} else {
2330 		while (i--) *got++ += (size_t)base;
2331 	}
2332 	j=0; search_vec(p->dynv, &j, DT_MIPS_GOTSYM);
2333 	i=0; search_vec(p->dynv, &i, DT_MIPS_SYMTABNO);
2334 	Sym *sym = p->syms + j;
2335 	rel[0] = (unsigned char *)got - base;
2336 	for (i-=j; i; i--, sym++, rel[0]+=sizeof(size_t)) {
2337 		rel[1] = R_INFO(sym-p->syms, R_MIPS_JUMP_SLOT);
2338 		do_relocs(p, rel, sizeof rel, 2);
2339 	}
2340 }
2341 
sleb128_decoder(uint8_t * current,uint8_t * end,size_t * value)2342 static uint8_t* sleb128_decoder(uint8_t* current, uint8_t* end, size_t* value)
2343 {
2344 	size_t result = 0;
2345 	static const size_t size = CHAR_BIT * sizeof(result);
2346 
2347 	size_t shift = 0;
2348 	uint8_t byte;
2349 
2350 	do {
2351 		if (current >= end) {
2352 			a_crash();
2353 		}
2354 
2355 		byte = *current++;
2356 		result |= ((size_t)(byte & 127) << shift);
2357 		shift += 7;
2358 	} while (byte & 128);
2359 
2360 	if (shift < size && (byte & 64)) {
2361 		result |= -((size_t)(1) << shift);
2362 	}
2363 
2364 	*value = result;
2365 
2366 	return current;
2367 }
2368 
do_android_relocs(struct dso * p,size_t dt_name,size_t dt_size)2369 static void do_android_relocs(struct dso *p, size_t dt_name, size_t dt_size)
2370 {
2371 	size_t android_rel_addr = 0, android_rel_size = 0;
2372 	uint8_t *android_rel_curr, *android_rel_end;
2373 
2374 	search_vec(p->dynv, &android_rel_addr, dt_name);
2375 	search_vec(p->dynv, &android_rel_size, dt_size);
2376 
2377 	if (!android_rel_addr || (android_rel_size < 4)) {
2378 		return;
2379 	}
2380 
2381 	android_rel_curr = laddr(p, android_rel_addr);
2382 	if (memcmp(android_rel_curr, "APS2", ANDROID_REL_SIGN_SIZE)) {
2383 		return;
2384 	}
2385 
2386 	android_rel_curr += ANDROID_REL_SIGN_SIZE;
2387 	android_rel_size -= ANDROID_REL_SIGN_SIZE;
2388 
2389 	android_rel_end = android_rel_curr + android_rel_size;
2390 
2391 	size_t relocs_num;
2392 	size_t rel[3] = {0};
2393 
2394 	android_rel_curr = sleb128_decoder(android_rel_curr, android_rel_end, &relocs_num);
2395 	android_rel_curr = sleb128_decoder(android_rel_curr, android_rel_end, &rel[0]);
2396 
2397 	for (size_t i = 0; i < relocs_num;) {
2398 
2399 		size_t group_size, group_flags;
2400 
2401 		android_rel_curr = sleb128_decoder(android_rel_curr, android_rel_end, &group_size);
2402 		android_rel_curr = sleb128_decoder(android_rel_curr, android_rel_end, &group_flags);
2403 
2404 		size_t group_r_offset_delta = 0;
2405 
2406 		if (group_flags & RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG) {
2407 			android_rel_curr = sleb128_decoder(android_rel_curr, android_rel_end, &group_r_offset_delta);
2408 		}
2409 
2410 		if (group_flags & RELOCATION_GROUPED_BY_INFO_FLAG) {
2411 			android_rel_curr = sleb128_decoder(android_rel_curr, android_rel_end, &rel[1]);
2412 		}
2413 
2414 		const size_t addend_flags = group_flags & (RELOCATION_GROUP_HAS_ADDEND_FLAG | RELOCATION_GROUPED_BY_ADDEND_FLAG);
2415 
2416 		if (addend_flags == RELOCATION_GROUP_HAS_ADDEND_FLAG) {
2417 		} else if (addend_flags == (RELOCATION_GROUP_HAS_ADDEND_FLAG | RELOCATION_GROUPED_BY_ADDEND_FLAG)) {
2418 			size_t addend;
2419 			android_rel_curr = sleb128_decoder(android_rel_curr, android_rel_end, &addend);
2420 			rel[2] += addend;
2421 		} else {
2422 			rel[2] = 0;
2423 		}
2424 
2425 		for (size_t j = 0; j < group_size; j++) {
2426 			if (group_flags & RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG) {
2427 				rel[0] += group_r_offset_delta;
2428 			} else {
2429 				size_t offset_detla;
2430 				android_rel_curr = sleb128_decoder(android_rel_curr, android_rel_end, &offset_detla);
2431 
2432 				rel[0] += offset_detla;
2433 			}
2434 
2435 			if ((group_flags & RELOCATION_GROUPED_BY_INFO_FLAG) == 0) {
2436 				android_rel_curr = sleb128_decoder(android_rel_curr, android_rel_end, &rel[1]);
2437 			}
2438 
2439 			if (addend_flags == RELOCATION_GROUP_HAS_ADDEND_FLAG) {
2440 				size_t addend;
2441 				android_rel_curr = sleb128_decoder(android_rel_curr, android_rel_end, &addend);
2442 				rel[2] += addend;
2443 			}
2444 
2445 			if (dt_name == DT_ANDROID_REL) {
2446 				do_relocs(p, rel, sizeof(size_t)*2, 2);
2447 			} else {
2448 				do_relocs(p, rel, sizeof(size_t)*3, 3);
2449 			}
2450 		}
2451 
2452 		i += group_size;
2453 	}
2454 }
2455 
do_relr_relocs(struct dso * dso,size_t * relr,size_t relr_size)2456 static void do_relr_relocs(struct dso *dso, size_t *relr, size_t relr_size)
2457 {
2458 	unsigned char *base = dso->base;
2459 	size_t *reloc_addr;
2460 	for (; relr_size; relr++, relr_size-=sizeof(size_t))
2461 		if ((relr[0]&1) == 0) {
2462 			reloc_addr = laddr(dso, relr[0]);
2463 			*reloc_addr++ += (size_t)base;
2464 		} else {
2465 			int i = 0;
2466 			for (size_t bitmap=relr[0]; (bitmap>>=1); i++)
2467 				if (bitmap&1)
2468 					reloc_addr[i] += (size_t)base;
2469 			reloc_addr += 8*sizeof(size_t)-1;
2470 		}
2471 }
2472 
reloc_all(struct dso * p,const dl_extinfo * extinfo)2473 static void reloc_all(struct dso *p, const dl_extinfo *extinfo)
2474 {
2475 	ssize_t relro_fd_offset = 0;
2476 	size_t dyn[DYN_CNT];
2477 	for (; p; p=p->next) {
2478 		if (p->relocated) continue;
2479 		if (p != &ldso) {
2480 			add_can_search_so_list_in_dso(p, head);
2481 		}
2482 		decode_vec(p->dynv, dyn, DYN_CNT);
2483 		if (NEED_MIPS_GOT_RELOCS)
2484 			do_mips_relocs(p, laddr(p, dyn[DT_PLTGOT]));
2485 		do_relocs(p, laddr(p, dyn[DT_JMPREL]), dyn[DT_PLTRELSZ],
2486 			2+(dyn[DT_PLTREL]==DT_RELA));
2487 		do_relocs(p, laddr(p, dyn[DT_REL]), dyn[DT_RELSZ], 2);
2488 		do_relocs(p, laddr(p, dyn[DT_RELA]), dyn[DT_RELASZ], 3);
2489 		if (!DL_FDPIC)
2490 			do_relr_relocs(p, laddr(p, dyn[DT_RELR]), dyn[DT_RELRSZ]);
2491 
2492 		do_android_relocs(p, DT_ANDROID_REL, DT_ANDROID_RELSZ);
2493 		do_android_relocs(p, DT_ANDROID_RELA, DT_ANDROID_RELASZ);
2494 
2495 		if (head != &ldso && p->relro_start != p->relro_end &&
2496 			mprotect(laddr(p, p->relro_start), p->relro_end-p->relro_start, PROT_READ)
2497 			&& errno != ENOSYS) {
2498 			error("Error relocating %s: RELRO protection failed: %m",
2499 				p->name);
2500 			if (runtime) longjmp(*rtld_fail, 1);
2501 		}
2502 		/* Handle serializing/mapping the RELRO segment */
2503 		handle_relro_sharing(p, extinfo, &relro_fd_offset);
2504 
2505 		p->relocated = 1;
2506 		free_reloc_can_search_dso(p);
2507 	}
2508 }
2509 
kernel_mapped_dso(struct dso * p)2510 static void kernel_mapped_dso(struct dso *p)
2511 {
2512 	size_t min_addr = -1, max_addr = 0, cnt;
2513 	Phdr *ph = p->phdr;
2514 	for (cnt = p->phnum; cnt--; ph = (void *)((char *)ph + p->phentsize)) {
2515 		if (ph->p_type == PT_DYNAMIC) {
2516 			p->dynv = laddr(p, ph->p_vaddr);
2517 		} else if (ph->p_type == PT_GNU_RELRO) {
2518 			p->relro_start = ph->p_vaddr & -PAGE_SIZE;
2519 			p->relro_end = (ph->p_vaddr + ph->p_memsz) & -PAGE_SIZE;
2520 		} else if (ph->p_type == PT_GNU_STACK) {
2521 			if (!runtime && ph->p_memsz > __default_stacksize) {
2522 				__default_stacksize =
2523 					ph->p_memsz < DEFAULT_STACK_MAX ?
2524 					ph->p_memsz : DEFAULT_STACK_MAX;
2525 			}
2526 		}
2527 		if (ph->p_type != PT_LOAD) continue;
2528 		if (ph->p_vaddr < min_addr)
2529 			min_addr = ph->p_vaddr;
2530 		if (ph->p_vaddr+ph->p_memsz > max_addr)
2531 			max_addr = ph->p_vaddr+ph->p_memsz;
2532 	}
2533 	min_addr &= -PAGE_SIZE;
2534 	max_addr = (max_addr + PAGE_SIZE-1) & -PAGE_SIZE;
2535 	p->map = p->base + min_addr;
2536 	p->map_len = max_addr - min_addr;
2537 	p->kernel_mapped = 1;
2538 }
2539 
__libc_exit_fini()2540 void __libc_exit_fini()
2541 {
2542 	struct dso *p;
2543 	size_t dyn[DYN_CNT];
2544 	pthread_t self = __pthread_self();
2545 
2546 	/* Take both locks before setting shutting_down, so that
2547 	 * either lock is sufficient to read its value. The lock
2548 	 * order matches that in dlopen to avoid deadlock. */
2549 	pthread_rwlock_wrlock(&lock);
2550 	pthread_mutex_lock(&init_fini_lock);
2551 	shutting_down = 1;
2552 	pthread_rwlock_unlock(&lock);
2553 	for (p=fini_head; p; p=p->fini_next) {
2554 		while (p->ctor_visitor && p->ctor_visitor!=self)
2555 			pthread_cond_wait(&ctor_cond, &init_fini_lock);
2556 		if (!p->constructed) continue;
2557 		decode_vec(p->dynv, dyn, DYN_CNT);
2558 		if (dyn[0] & (1<<DT_FINI_ARRAY)) {
2559 			size_t n = dyn[DT_FINI_ARRAYSZ]/sizeof(size_t);
2560 			size_t *fn = (size_t *)laddr(p, dyn[DT_FINI_ARRAY])+n;
2561 			while (n--) ((void (*)(void))*--fn)();
2562 		}
2563 #ifndef NO_LEGACY_INITFINI
2564 		if ((dyn[0] & (1<<DT_FINI)) && dyn[DT_FINI])
2565 			fpaddr(p, dyn[DT_FINI])();
2566 #endif
2567 	}
2568 }
2569 
__ldso_atfork(int who)2570 void __ldso_atfork(int who)
2571 {
2572 	if (who<0) {
2573 		pthread_rwlock_wrlock(&lock);
2574 		pthread_mutex_lock(&init_fini_lock);
2575 	} else {
2576 		pthread_mutex_unlock(&init_fini_lock);
2577 		pthread_rwlock_unlock(&lock);
2578 	}
2579 }
2580 
queue_ctors(struct dso * dso)2581 static struct dso **queue_ctors(struct dso *dso)
2582 {
2583 	size_t cnt, qpos, spos, i;
2584 	struct dso *p, **queue, **stack;
2585 
2586 	if (ldd_mode) return 0;
2587 
2588 	/* Bound on queue size is the total number of indirect deps.
2589 	 * If a bfs deps list was built, we can use it. Otherwise,
2590 	 * bound by the total number of DSOs, which is always safe and
2591 	 * is reasonable we use it (for main app at startup). */
2592 	if (dso->bfs_built) {
2593 		for (cnt=0; dso->deps[cnt]; cnt++)
2594 			dso->deps[cnt]->mark = 0;
2595 		cnt++; /* self, not included in deps */
2596 	} else {
2597 		for (cnt=0, p=head; p; cnt++, p=p->next)
2598 			p->mark = 0;
2599 	}
2600 	cnt++; /* termination slot */
2601 	if (dso==head && cnt <= countof(builtin_ctor_queue))
2602 		queue = builtin_ctor_queue;
2603 	else
2604 		queue = calloc(cnt, sizeof *queue);
2605 
2606 	if (!queue) {
2607 		error("Error allocating constructor queue: %m\n");
2608 		if (runtime) longjmp(*rtld_fail, 1);
2609 		return 0;
2610 	}
2611 
2612 	/* Opposite ends of the allocated buffer serve as an output queue
2613 	 * and a working stack. Setup initial stack with just the argument
2614 	 * dso and initial queue empty... */
2615 	stack = queue;
2616 	qpos = 0;
2617 	spos = cnt;
2618 	stack[--spos] = dso;
2619 	dso->next_dep = 0;
2620 	dso->mark = 1;
2621 
2622 	/* Then perform pseudo-DFS sort, but ignoring circular deps. */
2623 	while (spos<cnt) {
2624 		p = stack[spos++];
2625 		while (p->next_dep < p->ndeps_direct) {
2626 			if (p->deps[p->next_dep]->mark) {
2627 				p->next_dep++;
2628 			} else {
2629 				stack[--spos] = p;
2630 				p = p->deps[p->next_dep];
2631 				p->next_dep = 0;
2632 				p->mark = 1;
2633 			}
2634 		}
2635 		queue[qpos++] = p;
2636 	}
2637 	queue[qpos] = 0;
2638 	for (i=0; i<qpos; i++) queue[i]->mark = 0;
2639 
2640 	return queue;
2641 }
2642 
do_init_fini(struct dso ** queue)2643 static void do_init_fini(struct dso **queue)
2644 {
2645 	struct dso *p;
2646 	size_t dyn[DYN_CNT], i;
2647 	pthread_t self = __pthread_self();
2648 
2649 	pthread_mutex_lock(&init_fini_lock);
2650 	for (i=0; (p=queue[i]); i++) {
2651 		while ((p->ctor_visitor && p->ctor_visitor!=self) || shutting_down)
2652 			pthread_cond_wait(&ctor_cond, &init_fini_lock);
2653 		if (p->ctor_visitor || p->constructed)
2654 			continue;
2655 		p->ctor_visitor = self;
2656 
2657 		decode_vec(p->dynv, dyn, DYN_CNT);
2658 		if (dyn[0] & ((1<<DT_FINI) | (1<<DT_FINI_ARRAY))) {
2659 			p->fini_next = fini_head;
2660 			fini_head = p;
2661 		}
2662 
2663 		pthread_mutex_unlock(&init_fini_lock);
2664 
2665 #ifndef NO_LEGACY_INITFINI
2666 		if ((dyn[0] & (1<<DT_INIT)) && dyn[DT_INIT])
2667 			fpaddr(p, dyn[DT_INIT])();
2668 #endif
2669 		if (dyn[0] & (1<<DT_INIT_ARRAY)) {
2670 			size_t n = dyn[DT_INIT_ARRAYSZ]/sizeof(size_t);
2671 			size_t *fn = laddr(p, dyn[DT_INIT_ARRAY]);
2672 			if (p != &ldso) {
2673 				trace_marker_begin(HITRACE_TAG_MUSL, "calling constructors: ", p->name);
2674 			}
2675 			while (n--) ((void (*)(void))*fn++)();
2676 			if (p != &ldso) {
2677 				trace_marker_end(HITRACE_TAG_MUSL);
2678 			}
2679 		}
2680 
2681 		pthread_mutex_lock(&init_fini_lock);
2682 		p->ctor_visitor = 0;
2683 		p->constructed = 1;
2684 		pthread_cond_broadcast(&ctor_cond);
2685 	}
2686 	pthread_mutex_unlock(&init_fini_lock);
2687 }
2688 
__libc_start_init(void)2689 void __libc_start_init(void)
2690 {
2691 	do_init_fini(main_ctor_queue);
2692 	if (!__malloc_replaced && main_ctor_queue != builtin_ctor_queue)
2693 		free(main_ctor_queue);
2694 	main_ctor_queue = 0;
2695 }
2696 
dl_debug_state(void)2697 static void dl_debug_state(void)
2698 {
2699 }
2700 
2701 weak_alias(dl_debug_state, _dl_debug_state);
2702 
__init_tls(size_t * auxv)2703 void __init_tls(size_t *auxv)
2704 {
2705 }
2706 
update_tls_size()2707 static void update_tls_size()
2708 {
2709 	libc.tls_cnt = tls_cnt;
2710 	libc.tls_align = tls_align;
2711 	libc.tls_size = ALIGN(
2712 		(1+tls_cnt) * sizeof(void *) +
2713 		tls_offset +
2714 		sizeof(struct pthread) +
2715 		tls_align * 2,
2716 	tls_align);
2717 }
2718 
install_new_tls(void)2719 static void install_new_tls(void)
2720 {
2721 	sigset_t set;
2722 	pthread_t self = __pthread_self(), td;
2723 	struct dso *dtv_provider = container_of(tls_tail, struct dso, tls);
2724 	uintptr_t (*newdtv)[tls_cnt+1] = (void *)dtv_provider->new_dtv;
2725 	struct dso *p;
2726 	size_t i, j;
2727 	size_t old_cnt = self->dtv[0];
2728 
2729 	__block_app_sigs(&set);
2730 	__tl_lock();
2731 	/* Copy existing dtv contents from all existing threads. */
2732 	for (i=0, td=self; !i || td!=self; i++, td=td->next) {
2733 		memcpy(newdtv+i, td->dtv,
2734 			(old_cnt+1)*sizeof(uintptr_t));
2735 		newdtv[i][0] = tls_cnt;
2736 	}
2737 	/* Install new dtls into the enlarged, uninstalled dtv copies. */
2738 	for (p=head; ; p=p->next) {
2739 		if (p->tls_id <= old_cnt) continue;
2740 		unsigned char *mem = p->new_tls;
2741 		for (j=0; j<i; j++) {
2742 			unsigned char *new = mem;
2743 			new += ((uintptr_t)p->tls.image - (uintptr_t)mem)
2744 				& (p->tls.align-1);
2745 			memcpy(new, p->tls.image, p->tls.len);
2746 			newdtv[j][p->tls_id] =
2747 				(uintptr_t)new + DTP_OFFSET;
2748 			mem += p->tls.size + p->tls.align;
2749 		}
2750 		if (p->tls_id == tls_cnt) break;
2751 	}
2752 
2753 	/* Broadcast barrier to ensure contents of new dtv is visible
2754 	 * if the new dtv pointer is. The __membarrier function has a
2755 	 * fallback emulation using signals for kernels that lack the
2756 	 * feature at the syscall level. */
2757 
2758 	__membarrier(MEMBARRIER_CMD_PRIVATE_EXPEDITED, 0);
2759 
2760 	/* Install new dtv for each thread. */
2761 	for (j=0, td=self; !j || td!=self; j++, td=td->next) {
2762 		td->dtv = newdtv[j];
2763 	}
2764 
2765 	__tl_unlock();
2766 	__restore_sigs(&set);
2767 }
2768 
2769 /* Stage 1 of the dynamic linker is defined in dlstart.c. It calls the
2770  * following stage 2 and stage 3 functions via primitive symbolic lookup
2771  * since it does not have access to their addresses to begin with. */
2772 
2773 /* Stage 2 of the dynamic linker is called after relative relocations
2774  * have been processed. It can make function calls to static functions
2775  * and access string literals and static data, but cannot use extern
2776  * symbols. Its job is to perform symbolic relocations on the dynamic
2777  * linker itself, but some of the relocations performed may need to be
2778  * replaced later due to copy relocations in the main program. */
2779 
__dls2(unsigned char * base,size_t * sp)2780 hidden void __dls2(unsigned char *base, size_t *sp)
2781 {
2782 	size_t *auxv;
2783 	for (auxv=sp+1+*sp+1; *auxv; auxv++);
2784 	auxv++;
2785 	if (DL_FDPIC) {
2786 		void *p1 = (void *)sp[-2];
2787 		void *p2 = (void *)sp[-1];
2788 		if (!p1) {
2789 			size_t aux[AUX_CNT];
2790 			decode_vec(auxv, aux, AUX_CNT);
2791 			if (aux[AT_BASE]) ldso.base = (void *)aux[AT_BASE];
2792 			else ldso.base = (void *)(aux[AT_PHDR] & -4096);
2793 		}
2794 		app_loadmap = p2 ? p1 : 0;
2795 		ldso.loadmap = p2 ? p2 : p1;
2796 		ldso.base = laddr(&ldso, 0);
2797 	} else {
2798 		ldso.base = base;
2799 	}
2800 	size_t aux[AUX_CNT];
2801 	decode_vec(auxv, aux, AUX_CNT);
2802 	libc.page_size = aux[AT_PAGESZ];
2803 	Ehdr *ehdr = (void *)ldso.base;
2804 	ldso.name = ldso.shortname = "libc.so";
2805 	ldso.phnum = ehdr->e_phnum;
2806 	ldso.phdr = laddr(&ldso, ehdr->e_phoff);
2807 	ldso.phentsize = ehdr->e_phentsize;
2808 	ldso.is_global = true;
2809 	kernel_mapped_dso(&ldso);
2810 	decode_dyn(&ldso);
2811 
2812 	if (DL_FDPIC) makefuncdescs(&ldso);
2813 
2814 	/* Prepare storage for to save clobbered REL addends so they
2815 	 * can be reused in stage 3. There should be very few. If
2816 	 * something goes wrong and there are a huge number, abort
2817 	 * instead of risking stack overflow. */
2818 	size_t dyn[DYN_CNT];
2819 	decode_vec(ldso.dynv, dyn, DYN_CNT);
2820 	size_t *rel = laddr(&ldso, dyn[DT_REL]);
2821 	size_t rel_size = dyn[DT_RELSZ];
2822 	size_t symbolic_rel_cnt = 0;
2823 	apply_addends_to = rel;
2824 	for (; rel_size; rel+=2, rel_size-=2*sizeof(size_t))
2825 		if (!IS_RELATIVE(rel[1], ldso.syms)) symbolic_rel_cnt++;
2826 	if (symbolic_rel_cnt >= ADDEND_LIMIT) a_crash();
2827 	size_t addends[symbolic_rel_cnt+1];
2828 	saved_addends = addends;
2829 
2830 	head = &ldso;
2831 	reloc_all(&ldso, NULL);
2832 
2833 	ldso.relocated = 0;
2834 
2835 	/* Call dynamic linker stage-2b, __dls2b, looking it up
2836 	 * symbolically as a barrier against moving the address
2837 	 * load across the above relocation processing. */
2838 	struct symdef dls2b_def = find_sym(&ldso, "__dls2b", 0);
2839 	if (DL_FDPIC) ((stage3_func)&ldso.funcdescs[dls2b_def.sym-ldso.syms])(sp, auxv, aux);
2840 	else ((stage3_func)laddr(&ldso, dls2b_def.sym->st_value))(sp, auxv, aux);
2841 }
2842 
2843 /* Stage 2b sets up a valid thread pointer, which requires relocations
2844  * completed in stage 2, and on which stage 3 is permitted to depend.
2845  * This is done as a separate stage, with symbolic lookup as a barrier,
2846  * so that loads of the thread pointer and &errno can be pure/const and
2847  * thereby hoistable. */
2848 
__dls2b(size_t * sp,size_t * auxv,size_t * aux)2849 void __dls2b(size_t *sp, size_t *auxv, size_t *aux)
2850 {
2851 	/* Setup early thread pointer in builtin_tls for ldso/libc itself to
2852 	 * use during dynamic linking. If possible it will also serve as the
2853 	 * thread pointer at runtime. */
2854 	search_vec(auxv, &__hwcap, AT_HWCAP);
2855 	libc.auxv = auxv;
2856 	libc.tls_size = sizeof builtin_tls;
2857 	libc.tls_align = tls_align;
2858 	if (__init_tp(__copy_tls((void *)builtin_tls)) < 0) {
2859 		a_crash();
2860 	}
2861 	__pthread_self()->stack = (void *)(sp + 1);
2862 	struct symdef dls3_def = find_sym(&ldso, "__dls3", 0);
2863 	if (DL_FDPIC) ((stage3_func)&ldso.funcdescs[dls3_def.sym-ldso.syms])(sp, auxv, aux);
2864 	else ((stage3_func)laddr(&ldso, dls3_def.sym->st_value))(sp, auxv, aux);
2865 }
2866 
2867 /* Stage 3 of the dynamic linker is called with the dynamic linker/libc
2868  * fully functional. Its job is to load (if not already loaded) and
2869  * process dependencies and relocations for the main application and
2870  * transfer control to its entry point. */
2871 
__dls3(size_t * sp,size_t * auxv,size_t * aux)2872 void __dls3(size_t *sp, size_t *auxv, size_t *aux)
2873 {
2874 	static struct dso app, vdso;
2875 	size_t i;
2876 	char *env_preload=0;
2877 	char *replace_argv0=0;
2878 	size_t vdso_base;
2879 	int argc = *sp;
2880 	char **argv = (void *)(sp+1);
2881 	char **argv_orig = argv;
2882 	char **envp = argv+argc+1;
2883 
2884 	/* Find aux vector just past environ[] and use it to initialize
2885 	 * global data that may be needed before we can make syscalls. */
2886 	__environ = envp;
2887 	search_vec(auxv, &__sysinfo, AT_SYSINFO);
2888 	__pthread_self()->sysinfo = __sysinfo;
2889 	libc.secure = ((aux[0]&0x7800)!=0x7800 || aux[AT_UID]!=aux[AT_EUID]
2890 		|| aux[AT_GID]!=aux[AT_EGID] || aux[AT_SECURE]);
2891 
2892 	/* Only trust user/env if kernel says we're not suid/sgid */
2893 	if (!libc.secure) {
2894 		env_path = getenv("LD_LIBRARY_PATH");
2895 		env_preload = getenv("LD_PRELOAD");
2896 	}
2897 #ifdef OHOS_ENABLE_PARAMETER
2898 	InitParameterClient();
2899 #endif
2900 // we may abort when linking other libs, load signal handler before stage start
2901 #ifdef DFX_SIGNAL_LIBC
2902 	DFX_InstallSignalHandler();
2903 #endif
2904 	__init_fdsan();
2905 	/* If the main program was already loaded by the kernel,
2906 	 * AT_PHDR will point to some location other than the dynamic
2907 	 * linker's program headers. */
2908 	if (aux[AT_PHDR] != (size_t)ldso.phdr) {
2909 		size_t interp_off = 0;
2910 		size_t tls_image = 0;
2911 		/* Find load address of the main program, via AT_PHDR vs PT_PHDR. */
2912 		Phdr *phdr = app.phdr = (void *)aux[AT_PHDR];
2913 		app.phnum = aux[AT_PHNUM];
2914 		app.phentsize = aux[AT_PHENT];
2915 		for (i=aux[AT_PHNUM]; i; i--, phdr=(void *)((char *)phdr + aux[AT_PHENT])) {
2916 			if (phdr->p_type == PT_PHDR)
2917 				app.base = (void *)(aux[AT_PHDR] - phdr->p_vaddr);
2918 			else if (phdr->p_type == PT_INTERP)
2919 				interp_off = (size_t)phdr->p_vaddr;
2920 			else if (phdr->p_type == PT_TLS) {
2921 				tls_image = phdr->p_vaddr;
2922 				app.tls.len = phdr->p_filesz;
2923 				app.tls.size = phdr->p_memsz;
2924 				app.tls.align = phdr->p_align;
2925 			}
2926 		}
2927 		if (DL_FDPIC) app.loadmap = app_loadmap;
2928 		if (app.tls.size) app.tls.image = laddr(&app, tls_image);
2929 		if (interp_off) ldso.name = laddr(&app, interp_off);
2930 		if ((aux[0] & (1UL<<AT_EXECFN))
2931 			&& strncmp((char *)aux[AT_EXECFN], "/proc/", 6))
2932 			app.name = (char *)aux[AT_EXECFN];
2933 		else
2934 			app.name = argv[0];
2935 		kernel_mapped_dso(&app);
2936 	} else {
2937 		int fd;
2938 		char *ldname = argv[0];
2939 		size_t l = strlen(ldname);
2940 		if (l >= 3 && !strcmp(ldname+l-3, "ldd")) ldd_mode = 1;
2941 		argv++;
2942 		while (argv[0] && argv[0][0]=='-' && argv[0][1]=='-') {
2943 			char *opt = argv[0]+2;
2944 			*argv++ = (void *)-1;
2945 			if (!*opt) {
2946 				break;
2947 			} else if (!memcmp(opt, "list", 5)) {
2948 				ldd_mode = 1;
2949 			} else if (!memcmp(opt, "library-path", 12)) {
2950 				if (opt[12]=='=') env_path = opt+13;
2951 				else if (opt[12]) *argv = 0;
2952 				else if (*argv) env_path = *argv++;
2953 			} else if (!memcmp(opt, "preload", 7)) {
2954 				if (opt[7]=='=') env_preload = opt+8;
2955 				else if (opt[7]) *argv = 0;
2956 				else if (*argv) env_preload = *argv++;
2957 			} else if (!memcmp(opt, "argv0", 5)) {
2958 				if (opt[5]=='=') replace_argv0 = opt+6;
2959 				else if (opt[5]) *argv = 0;
2960 				else if (*argv) replace_argv0 = *argv++;
2961 			} else {
2962 				argv[0] = 0;
2963 			}
2964 		}
2965 		argv[-1] = (void *)(argc - (argv-argv_orig));
2966 		if (!argv[0]) {
2967 			dprintf(2, "musl libc (" LDSO_ARCH ")\n"
2968 				"Version %s\n"
2969 				"Dynamic Program Loader\n"
2970 				"Usage: %s [options] [--] pathname%s\n",
2971 				__libc_version, ldname,
2972 				ldd_mode ? "" : " [args]");
2973 			_exit(1);
2974 		}
2975 		fd = open(argv[0], O_RDONLY);
2976 		if (fd < 0) {
2977 			dprintf(2, "%s: cannot load %s: %s\n", ldname, argv[0], strerror(errno));
2978 			_exit(1);
2979 		}
2980 		Ehdr *ehdr = map_library(fd, &app, NULL);
2981 		if (!ehdr) {
2982 			dprintf(2, "%s: %s: Not a valid dynamic program\n", ldname, argv[0]);
2983 			_exit(1);
2984 		}
2985 		close(fd);
2986 		ldso.name = ldname;
2987 		app.name = argv[0];
2988 		aux[AT_ENTRY] = (size_t)laddr(&app, ehdr->e_entry);
2989 		/* Find the name that would have been used for the dynamic
2990 		 * linker had ldd not taken its place. */
2991 		if (ldd_mode) {
2992 			for (i=0; i<app.phnum; i++) {
2993 				if (app.phdr[i].p_type == PT_INTERP)
2994 					ldso.name = laddr(&app, app.phdr[i].p_vaddr);
2995 			}
2996 			dprintf(1, "\t%s (%p)\n", ldso.name, ldso.base);
2997 		}
2998 	}
2999 	if (app.tls.size) {
3000 		libc.tls_head = tls_tail = &app.tls;
3001 		app.tls_id = tls_cnt = 1;
3002 #ifdef TLS_ABOVE_TP
3003 		app.tls.offset = GAP_ABOVE_TP;
3004 		app.tls.offset += (-GAP_ABOVE_TP + (uintptr_t)app.tls.image)
3005 			& (app.tls.align-1);
3006 		tls_offset = app.tls.offset + app.tls.size;
3007 #else
3008 		tls_offset = app.tls.offset = app.tls.size
3009 			+ ( -((uintptr_t)app.tls.image + app.tls.size)
3010 			& (app.tls.align-1) );
3011 #endif
3012 		tls_align = MAXP2(tls_align, app.tls.align);
3013 	}
3014 	decode_dyn(&app);
3015 	if (DL_FDPIC) {
3016 		makefuncdescs(&app);
3017 		if (!app.loadmap) {
3018 			app.loadmap = (void *)&app_dummy_loadmap;
3019 			app.loadmap->nsegs = 1;
3020 			app.loadmap->segs[0].addr = (size_t)app.map;
3021 			app.loadmap->segs[0].p_vaddr = (size_t)app.map
3022 				- (size_t)app.base;
3023 			app.loadmap->segs[0].p_memsz = app.map_len;
3024 		}
3025 		argv[-3] = (void *)app.loadmap;
3026 	}
3027 	app.is_global = true;
3028 
3029 	/* Initial dso chain consists only of the app. */
3030 	head = tail = syms_tail = &app;
3031 
3032 	/* Donate unused parts of app and library mapping to malloc */
3033 	reclaim_gaps(&app);
3034 	reclaim_gaps(&ldso);
3035 
3036 	find_and_set_bss_name(&app);
3037 	find_and_set_bss_name(&ldso);
3038 
3039 	/* Load preload/needed libraries, add symbols to global namespace. */
3040 	ldso.deps = (struct dso **)no_deps;
3041 	/* Init g_is_asan */
3042 	g_is_asan = false;
3043 	LD_LOGD("__dls3 ldso.name:%{public}s.", ldso.name);
3044 	/* Through ldso Name to judge whether the Asan function is enabled */
3045 	if (strstr(ldso.name, "-asan")) {
3046 		g_is_asan = true;
3047 		LD_LOGD("__dls3 g_is_asan is true.");
3048 	}
3049 	/* Init all namespaces by config file. there is a default namespace always*/
3050 	init_namespace(&app);
3051 
3052 #ifdef LOAD_ORDER_RANDOMIZATION
3053 	struct loadtasks *tasks = create_loadtasks();
3054 	if (!tasks) {
3055 		_exit(1);
3056 	}
3057 	if (env_preload) {
3058 		load_preload(env_preload, get_default_ns(), tasks);
3059 	}
3060 	for (struct dso *q=head; q; q=q->next) {
3061 		q->is_global = true;
3062 	}
3063 	preload_deps(&app, tasks);
3064 	unmap_preloaded_sections(tasks);
3065 	shuffle_loadtasks(tasks);
3066 	run_loadtasks(tasks, NULL);
3067 	free_loadtasks(tasks);
3068 	assign_tls(app.next);
3069 #else
3070 	if (env_preload) load_preload(env_preload, get_default_ns());
3071 	for (struct dso *q=head; q; q=q->next) {
3072 		q->is_global = true;
3073 	}
3074  	load_deps(&app, NULL);
3075 #endif
3076 
3077 	/* Set is_reloc_head_so_dep to true for all direct and indirect dependent sos of app, including app self. */
3078 	for (struct dso *p=head; p; p=p->next) {
3079 		p->is_reloc_head_so_dep = true;
3080 		add_syms(p);
3081 	}
3082 
3083 	/* Attach to vdso, if provided by the kernel, last so that it does
3084 	 * not become part of the global namespace.  */
3085 	if (search_vec(auxv, &vdso_base, AT_SYSINFO_EHDR) && vdso_base) {
3086 		Ehdr *ehdr = (void *)vdso_base;
3087 		Phdr *phdr = vdso.phdr = (void *)(vdso_base + ehdr->e_phoff);
3088 		vdso.phnum = ehdr->e_phnum;
3089 		vdso.phentsize = ehdr->e_phentsize;
3090 		for (i=ehdr->e_phnum; i; i--, phdr=(void *)((char *)phdr + ehdr->e_phentsize)) {
3091 			if (phdr->p_type == PT_DYNAMIC)
3092 				vdso.dynv = (void *)(vdso_base + phdr->p_offset);
3093 			if (phdr->p_type == PT_LOAD)
3094 				vdso.base = (void *)(vdso_base - phdr->p_vaddr + phdr->p_offset);
3095 		}
3096 		vdso.name = "";
3097 		vdso.shortname = "linux-gate.so.1";
3098 		vdso.relocated = 1;
3099 		vdso.deps = (struct dso **)no_deps;
3100 		decode_dyn(&vdso);
3101 		vdso.prev = tail;
3102 		tail->next = &vdso;
3103 		tail = &vdso;
3104 		vdso.namespace = get_default_ns();
3105 		ns_add_dso(vdso.namespace, &vdso);
3106 	}
3107 
3108 	for (i=0; app.dynv[i]; i+=2) {
3109 		if (!DT_DEBUG_INDIRECT && app.dynv[i]==DT_DEBUG)
3110 			app.dynv[i+1] = (size_t)&debug;
3111 		if (DT_DEBUG_INDIRECT && app.dynv[i]==DT_DEBUG_INDIRECT) {
3112 			size_t *ptr = (size_t *) app.dynv[i+1];
3113 			*ptr = (size_t)&debug;
3114 		}
3115 	}
3116 
3117 	/* This must be done before final relocations, since it calls
3118 	 * malloc, which may be provided by the application. Calling any
3119 	 * application code prior to the jump to its entry point is not
3120 	 * valid in our model and does not work with FDPIC, where there
3121 	 * are additional relocation-like fixups that only the entry point
3122 	 * code can see to perform. */
3123 	main_ctor_queue = queue_ctors(&app);
3124 
3125 	/* Initial TLS must also be allocated before final relocations
3126 	 * might result in calloc being a call to application code. */
3127 	update_tls_size();
3128 	void *initial_tls = builtin_tls;
3129 	if (libc.tls_size > sizeof builtin_tls || tls_align > MIN_TLS_ALIGN) {
3130 		initial_tls = calloc(libc.tls_size, 1);
3131 		if (!initial_tls) {
3132 			dprintf(2, "%s: Error getting %zu bytes thread-local storage: %m\n",
3133 				argv[0], libc.tls_size);
3134 			_exit(127);
3135 		}
3136 	}
3137 	static_tls_cnt = tls_cnt;
3138 
3139 	/* The main program must be relocated LAST since it may contain
3140 	 * copy relocations which depend on libraries' relocations. */
3141 	reloc_all(app.next, NULL);
3142 	reloc_all(&app, NULL);
3143 	for (struct dso *q=head; q; q=q->next) {
3144 		q->is_reloc_head_so_dep = false;
3145 	}
3146 
3147 	/* Actual copying to new TLS needs to happen after relocations,
3148 	 * since the TLS images might have contained relocated addresses. */
3149 	if (initial_tls != builtin_tls) {
3150 		pthread_t self = __pthread_self();
3151 		pthread_t td = __copy_tls(initial_tls);
3152 		if (__init_tp(td) < 0) {
3153 			a_crash();
3154 		}
3155 		td->tsd = self->tsd;
3156 	} else {
3157 		size_t tmp_tls_size = libc.tls_size;
3158 		pthread_t self = __pthread_self();
3159 		/* Temporarily set the tls size to the full size of
3160 		 * builtin_tls so that __copy_tls will use the same layout
3161 		 * as it did for before. Then check, just to be safe. */
3162 		libc.tls_size = sizeof builtin_tls;
3163 		if (__copy_tls((void*)builtin_tls) != self) a_crash();
3164 		libc.tls_size = tmp_tls_size;
3165 	}
3166 
3167 	if (init_cfi_shadow(head, &ldso) == CFI_FAILED) {
3168 		error("[%s] init_cfi_shadow failed: %m", __FUNCTION__);
3169 	}
3170 
3171 	if (ldso_fail) _exit(127);
3172 	if (ldd_mode) _exit(0);
3173 
3174 	/* Determine if malloc was interposed by a replacement implementation
3175 	 * so that calloc and the memalign family can harden against the
3176 	 * possibility of incomplete replacement. */
3177 	if (find_sym(head, "malloc", 1).dso != &ldso)
3178 		__malloc_replaced = 1;
3179 	if (find_sym(head, "aligned_alloc", 1).dso != &ldso)
3180 		__aligned_alloc_replaced = 1;
3181 
3182 	/* Switch to runtime mode: any further failures in the dynamic
3183 	 * linker are a reportable failure rather than a fatal startup
3184 	 * error. */
3185 	runtime = 1;
3186 
3187 	sync_with_debugger();
3188 
3189 	if (replace_argv0) argv[0] = replace_argv0;
3190 
3191 #ifdef USE_GWP_ASAN
3192 	init_gwp_asan_by_libc(false);
3193 #endif
3194 
3195 	errno = 0;
3196 
3197 	CRTJMP((void *)aux[AT_ENTRY], argv-1);
3198 	for(;;);
3199 }
3200 
prepare_lazy(struct dso * p)3201 static void prepare_lazy(struct dso *p)
3202 {
3203 	size_t dyn[DYN_CNT], n, flags1=0;
3204 	decode_vec(p->dynv, dyn, DYN_CNT);
3205 	search_vec(p->dynv, &flags1, DT_FLAGS_1);
3206 	if (dyn[DT_BIND_NOW] || (dyn[DT_FLAGS] & DF_BIND_NOW) || (flags1 & DF_1_NOW))
3207 		return;
3208 	n = dyn[DT_RELSZ]/2 + dyn[DT_RELASZ]/3 + dyn[DT_PLTRELSZ]/2 + 1;
3209 	if (NEED_MIPS_GOT_RELOCS) {
3210 		size_t j=0; search_vec(p->dynv, &j, DT_MIPS_GOTSYM);
3211 		size_t i=0; search_vec(p->dynv, &i, DT_MIPS_SYMTABNO);
3212 		n += i-j;
3213 	}
3214 	p->lazy = calloc(n, 3*sizeof(size_t));
3215 	if (!p->lazy) {
3216 		error("Error preparing lazy relocation for %s: %m", p->name);
3217 		longjmp(*rtld_fail, 1);
3218 	}
3219 	p->lazy_next = lazy_head;
3220 	lazy_head = p;
3221 }
3222 
dlopen_post(struct dso * p,int mode)3223 static void *dlopen_post(struct dso* p, int mode) {
3224 	if (p == NULL) {
3225 		return p;
3226 	}
3227 	bool is_dlclose_debug = false;
3228 	if (is_dlclose_debug_enable()) {
3229 		is_dlclose_debug = true;
3230 	}
3231 	p->nr_dlopen++;
3232 	if (is_dlclose_debug) {
3233 		LD_LOGE("[dlclose]: %{public}s nr_dlopen++ when dlopen %{public}s, nr_dlopen:%{public}d ",
3234 				p->name, p->name, p->nr_dlopen);
3235 	}
3236 	if (p->bfs_built) {
3237 		for (int i = 0; p->deps[i]; i++) {
3238 			p->deps[i]->nr_dlopen++;
3239 			if (is_dlclose_debug) {
3240 				LD_LOGE("[dlclose]: %{public}s nr_dlopen++ when dlopen %{public}s, nr_dlopen:%{public}d",
3241 						p->deps[i]->name, p->name, p->deps[i]->nr_dlopen);
3242 			}
3243 			if (mode & RTLD_NODELETE) {
3244 				p->deps[i]->flags |= DSO_FLAGS_NODELETE;
3245 			}
3246 		}
3247 	}
3248 
3249 #ifdef HANDLE_RANDOMIZATION
3250 	void *handle = assign_valid_handle(p);
3251 	if (handle == NULL) {
3252 		LD_LOGE("dlopen_post: generate random handle failed");
3253 		do_dlclose(p);
3254 	}
3255 
3256 	return handle;
3257 #endif
3258 
3259 	return p;
3260 }
3261 
3262 static char *dlopen_permitted_list[] =
3263 {
3264 	"default",
3265 	"ndk",
3266 };
3267 
3268 #define PERMITIED_TARGET  "nweb_ns"
in_permitted_list(char * caller,char * target)3269 static bool in_permitted_list(char *caller, char *target)
3270 {
3271 	for (int i = 0; i < sizeof(dlopen_permitted_list)/sizeof(char*); i++) {
3272 		if (strcmp(dlopen_permitted_list[i], caller) == 0) {
3273 			return true;
3274 		}
3275 	}
3276 
3277 	if (strcmp(PERMITIED_TARGET, target) == 0) {
3278 		return true;
3279 	}
3280 
3281 	return false;
3282 }
3283 
is_permitted(const void * caller_addr,char * target)3284 static bool is_permitted(const void *caller_addr, char *target)
3285 {
3286 	struct dso *caller;
3287 	ns_t *ns;
3288 	caller = (struct dso *)addr2dso((size_t)caller_addr);
3289 	if ((caller == NULL) || (caller->namespace == NULL)) {
3290 		LD_LOGE("caller ns get error");
3291 		return false;
3292 	}
3293 
3294 	ns = caller->namespace;
3295 	if (in_permitted_list(ns->ns_name, target) == false) {
3296 		LD_LOGE("caller ns: %{public}s have no permission, target is %{public}s", ns->ns_name, target);
3297 		return false;
3298 	}
3299 
3300 	return true;
3301 }
3302 
3303 /* Add namespace function.
3304  * Some limitations come from sanitizer:
3305  *  Sanitizer requires this interface to be exposed.
3306  *  Pay attention to call __builtin_return_address in this interface because sanitizer can hook and call this interface.
3307  */
dlopen_impl(const char * file,int mode,const char * namespace,const void * caller_addr,const dl_extinfo * extinfo)3308 void *dlopen_impl(
3309 	const char *file, int mode, const char *namespace, const void *caller_addr, const dl_extinfo *extinfo)
3310 {
3311 	struct dso *volatile p, *orig_tail, *orig_syms_tail, *orig_lazy_head, *next;
3312 	struct tls_module *orig_tls_tail;
3313 	size_t orig_tls_cnt, orig_tls_offset, orig_tls_align;
3314 	size_t i;
3315 	int cs;
3316 	jmp_buf jb;
3317 	struct dso **volatile ctor_queue = 0;
3318 	ns_t *ns;
3319 	struct dso *caller;
3320 	bool reserved_address = false;
3321 	bool reserved_address_recursive = false;
3322 	struct reserved_address_params reserved_params = {0};
3323 #ifdef LOAD_ORDER_RANDOMIZATION
3324 	struct loadtasks *tasks = NULL;
3325 	struct loadtask *task = NULL;
3326 	bool is_task_appended = false;
3327 #endif
3328 
3329 	if (!file) {
3330 		LD_LOGD("dlopen_impl file is null, return head.");
3331 		return dlopen_post(head, mode);
3332 	}
3333 
3334 	if (extinfo) {
3335 		reserved_address_recursive = extinfo->flag & DL_EXT_RESERVED_ADDRESS_RECURSIVE;
3336 		if (extinfo->flag & DL_EXT_RESERVED_ADDRESS) {
3337 			reserved_address = true;
3338 			reserved_params.start_addr = extinfo->reserved_addr;
3339 			reserved_params.reserved_size = extinfo->reserved_size;
3340 			reserved_params.must_use_reserved = true;
3341 			reserved_params.reserved_address_recursive = reserved_address_recursive;
3342 		} else if (extinfo->flag & DL_EXT_RESERVED_ADDRESS_HINT) {
3343 			reserved_address = true;
3344 			reserved_params.start_addr = extinfo->reserved_addr;
3345 			reserved_params.reserved_size = extinfo->reserved_size;
3346 			reserved_params.must_use_reserved = false;
3347 			reserved_params.reserved_address_recursive = reserved_address_recursive;
3348 		}
3349 	}
3350 
3351 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
3352 	pthread_rwlock_wrlock(&lock);
3353 	__inhibit_ptc();
3354 	trace_marker_reset();
3355 	trace_marker_begin(HITRACE_TAG_MUSL, "dlopen: ", file);
3356 
3357 	/* When namespace does not exist, use caller's namespce
3358 	 * and when caller does not exist, use default namespce. */
3359 	caller = (struct dso *)addr2dso((size_t)caller_addr);
3360 	ns = find_ns_by_name(namespace);
3361 	if (!ns) ns = ((caller && caller->namespace) ? caller->namespace : get_default_ns());
3362 
3363 	p = 0;
3364 	if (shutting_down) {
3365 		error("Cannot dlopen while program is exiting.");
3366 		goto end;
3367 	}
3368 	orig_tls_tail = tls_tail;
3369 	orig_tls_cnt = tls_cnt;
3370 	orig_tls_offset = tls_offset;
3371 	orig_tls_align = tls_align;
3372 	orig_lazy_head = lazy_head;
3373 	orig_syms_tail = syms_tail;
3374 	orig_tail = tail;
3375 	noload = mode & RTLD_NOLOAD;
3376 
3377 	rtld_fail = &jb;
3378 	if (setjmp(*rtld_fail)) {
3379 		/* Clean up anything new that was (partially) loaded */
3380 		revert_syms(orig_syms_tail);
3381 		for (p=orig_tail->next; p; p=next) {
3382 			next = p->next;
3383 			while (p->td_index) {
3384 				void *tmp = p->td_index->next;
3385 				free(p->td_index);
3386 				p->td_index = tmp;
3387 			}
3388 			free(p->funcdescs);
3389 			if (p->rpath != p->rpath_orig)
3390 				free(p->rpath);
3391 			if (p->deps) {
3392 				for (int i = 0; i < p->ndeps_direct; i++) {
3393 					remove_dso_parent(p->deps[i], p);
3394 				}
3395 			}
3396 			free(p->deps);
3397 			dlclose_ns(p);
3398 			unmap_library(p);
3399 			if (p->parents) {
3400 				free(p->parents);
3401 			}
3402 			free_reloc_can_search_dso(p);
3403 		}
3404 		for (p=orig_tail->next; p; p=next) {
3405 			next = p->next;
3406 			free(p);
3407 		}
3408 		free(ctor_queue);
3409 		ctor_queue = 0;
3410 		if (!orig_tls_tail) libc.tls_head = 0;
3411 		tls_tail = orig_tls_tail;
3412 		if (tls_tail) tls_tail->next = 0;
3413 		tls_cnt = orig_tls_cnt;
3414 		tls_offset = orig_tls_offset;
3415 		tls_align = orig_tls_align;
3416 		lazy_head = orig_lazy_head;
3417 		tail = orig_tail;
3418 		tail->next = 0;
3419 		p = 0;
3420 		goto end;
3421 	} else {
3422 #ifdef LOAD_ORDER_RANDOMIZATION
3423 		tasks = create_loadtasks();
3424 		if (!tasks) {
3425 			LD_LOGE("dlopen_impl create loadtasks failed");
3426 			goto end;
3427 		}
3428 		task = create_loadtask(file, head, ns, true);
3429 		if (!task) {
3430 			LD_LOGE("dlopen_impl create loadtask failed");
3431 			goto end;
3432 		}
3433 		trace_marker_begin(HITRACE_TAG_MUSL, "loading: entry so", file);
3434 		if (!load_library_header(task)) {
3435 			error(noload ?
3436 				"Library %s is not already loaded" :
3437 				"Error loading shared library %s: %m",
3438 				file);
3439 			LD_LOGE("dlopen_impl load library header failed for %{public}s", task->name);
3440 			trace_marker_end(HITRACE_TAG_MUSL); // "loading: entry so" trace end.
3441 			goto end;
3442 		}
3443 		if (reserved_address) {
3444 			reserved_params.target = task->p;
3445 		}
3446 	}
3447 	if (!task->p) {
3448 		LD_LOGE("dlopen_impl load library failed for %{public}s", task->name);
3449 		error(noload ?
3450 			"Library %s is not already loaded" :
3451 			"Error loading shared library %s: %m",
3452 			file);
3453 		trace_marker_end(HITRACE_TAG_MUSL); // "loading: entry so" trace end.
3454 		goto end;
3455 	}
3456 	if (!task->isloaded) {
3457 		is_task_appended = append_loadtasks(tasks, task);
3458 	}
3459 	preload_deps(task->p, tasks);
3460 	unmap_preloaded_sections(tasks);
3461 	if (!reserved_address_recursive) {
3462 		shuffle_loadtasks(tasks);
3463 	}
3464 	run_loadtasks(tasks, reserved_address ? &reserved_params : NULL);
3465 	p = task->p;
3466 	if (!task->isloaded) {
3467 		assign_tls(p);
3468 	}
3469 	if (!is_task_appended) {
3470 		free_task(task);
3471 		task = NULL;
3472 	}
3473 	free_loadtasks(tasks);
3474 	tasks = NULL;
3475 #else
3476 		trace_marker_begin(HITRACE_TAG_MUSL, "loading: entry so", file);
3477 		p = load_library(file, head, ns, true, reserved_address ? &reserved_params : NULL);
3478 	}
3479 
3480 	if (!p) {
3481 		error(noload ?
3482 			"Library %s is not already loaded" :
3483 			"Error loading shared library %s: %m",
3484 			file);
3485 		trace_marker_end(HITRACE_TAG_MUSL); // "loading: entry so" trace end.
3486 		goto end;
3487 	}
3488 	/* First load handling */
3489 	load_deps(p, reserved_address && reserved_address_recursive ? &reserved_params : NULL);
3490 #endif
3491 	trace_marker_end(HITRACE_TAG_MUSL); // "loading: entry so" trace end.
3492 	extend_bfs_deps(p);
3493 	pthread_mutex_lock(&init_fini_lock);
3494 	int constructed = p->constructed;
3495 	pthread_mutex_unlock(&init_fini_lock);
3496 	if (!constructed) ctor_queue = queue_ctors(p);
3497 	if (!p->relocated && (mode & RTLD_LAZY)) {
3498 		prepare_lazy(p);
3499 		for (i=0; p->deps[i]; i++)
3500 			if (!p->deps[i]->relocated)
3501 				prepare_lazy(p->deps[i]);
3502 	}
3503 	if (!p->relocated || (mode & RTLD_GLOBAL)) {
3504 		/* Make new symbols global, at least temporarily, so we can do
3505 		 * relocations. If not RTLD_GLOBAL, this is reverted below. */
3506 		add_syms(p);
3507 		/* Set is_reloc_head_so_dep to true for all direct and indirect dependent sos of p, including p self. */
3508 		p->is_reloc_head_so_dep = true;
3509 		for (i=0; p->deps[i]; i++) {
3510 			p->deps[i]->is_reloc_head_so_dep = true;
3511 			add_syms(p->deps[i]);
3512 		}
3513 	}
3514 	struct dso *reloc_head_so = p;
3515 	trace_marker_begin(HITRACE_TAG_MUSL, "linking: entry so", p->name);
3516 	if (!p->relocated) {
3517 		reloc_all(p, extinfo);
3518 	}
3519 	trace_marker_end(HITRACE_TAG_MUSL);
3520 	reloc_head_so->is_reloc_head_so_dep = false;
3521 	for (size_t i=0; reloc_head_so->deps[i]; i++) {
3522 		reloc_head_so->deps[i]->is_reloc_head_so_dep = false;
3523 	}
3524 
3525 	/* If RTLD_GLOBAL was not specified, undo any new additions
3526 	 * to the global symbol table. This is a nop if the library was
3527 	 * previously loaded and already global. */
3528 	if (!(mode & RTLD_GLOBAL))
3529 		revert_syms(orig_syms_tail);
3530 
3531 	/* Processing of deferred lazy relocations must not happen until
3532 	 * the new libraries are committed; otherwise we could end up with
3533 	 * relocations resolved to symbol definitions that get removed. */
3534 	redo_lazy_relocs();
3535 
3536 	if (map_dso_to_cfi_shadow(p) == CFI_FAILED) {
3537 		error("[%s] map_dso_to_cfi_shadow failed: %m", __FUNCTION__);
3538 		longjmp(*rtld_fail, 1);
3539 	}
3540 
3541 	if (mode & RTLD_NODELETE) {
3542 		p->flags |= DSO_FLAGS_NODELETE;
3543 	}
3544 
3545 	update_tls_size();
3546 	if (tls_cnt != orig_tls_cnt)
3547 		install_new_tls();
3548 
3549 	if (orig_tail != tail) {
3550 		notify_addition_to_debugger(orig_tail->next);
3551 	}
3552 
3553 	orig_tail = tail;
3554 
3555 	p = dlopen_post(p, mode);
3556 end:
3557 #ifdef LOAD_ORDER_RANDOMIZATION
3558 	if (!is_task_appended) {
3559 		free_task(task);
3560 	}
3561 	free_loadtasks(tasks);
3562 #endif
3563 	__release_ptc();
3564 	if (p) gencnt++;
3565 	pthread_rwlock_unlock(&lock);
3566 	if (ctor_queue) {
3567 		do_init_fini(ctor_queue);
3568 		free(ctor_queue);
3569 	}
3570 	pthread_setcancelstate(cs, 0);
3571 	trace_marker_end(HITRACE_TAG_MUSL); // "dlopen: " trace end.
3572 	return p;
3573 }
3574 
dlopen(const char * file,int mode)3575 void *dlopen(const char *file, int mode)
3576 {
3577 	const void *caller_addr = __builtin_return_address(0);
3578 	musl_log_reset();
3579 	ld_log_reset();
3580 	LD_LOGI("dlopen file:%{public}s, mode:%{public}x ,caller_addr:%{public}p .", file, mode, caller_addr);
3581 	return dlopen_impl(file, mode, NULL, caller_addr, NULL);
3582 }
3583 
dlns_init(Dl_namespace * dlns,const char * name)3584 void dlns_init(Dl_namespace *dlns, const char *name)
3585 {
3586 	if (!dlns) {
3587 		return;
3588 	}
3589 	if (!name) {
3590 		dlns->name[0] = 0;
3591 		return;
3592 	}
3593 
3594 	const void *caller_addr = __builtin_return_address(0);
3595 	if (is_permitted(caller_addr, name) == false) {
3596 		return;
3597 	}
3598 
3599 	snprintf(dlns->name, sizeof dlns->name, name);
3600 	LD_LOGI("dlns_init dlns->name:%{public}s .", dlns->name);
3601 }
3602 
dlns_get(const char * name,Dl_namespace * dlns)3603 int dlns_get(const char *name, Dl_namespace *dlns)
3604 {
3605 	if (!dlns) {
3606 		LD_LOGE("dlns_get dlns is null.");
3607 		return EINVAL;
3608 	}
3609 	int ret = 0;
3610 	ns_t *ns = NULL;
3611 	pthread_rwlock_rdlock(&lock);
3612 	if (!name) {
3613 		struct dso *caller;
3614 		const void *caller_addr = __builtin_return_address(0);
3615 		caller = (struct dso *)addr2dso((size_t)caller_addr);
3616 		ns = ((caller && caller->namespace) ? caller->namespace : get_default_ns());
3617 		(void)snprintf(dlns->name, sizeof dlns->name, ns->ns_name);
3618 		LD_LOGI("dlns_get name is null, current dlns dlns->name:%{public}s.", dlns->name);
3619 	} else {
3620 		ns = find_ns_by_name(name);
3621 		if (ns) {
3622 			(void)snprintf(dlns->name, sizeof dlns->name, ns->ns_name);
3623 			LD_LOGI("dlns_get found ns, current dlns dlns->name:%{public}s.", dlns->name);
3624 		} else {
3625 			LD_LOGI("dlns_get not found ns! name:%{public}s.", name);
3626 			ret = ENOKEY;
3627 		}
3628 	}
3629 	pthread_rwlock_unlock(&lock);
3630 	return ret;
3631 }
3632 
dlopen_ns(Dl_namespace * dlns,const char * file,int mode)3633 void *dlopen_ns(Dl_namespace *dlns, const char *file, int mode)
3634 {
3635 	const void *caller_addr = __builtin_return_address(0);
3636 	if (is_permitted(caller_addr, dlns->name) == false) {
3637 		return NULL;
3638 	}
3639 
3640 	musl_log_reset();
3641 	ld_log_reset();
3642 	LD_LOGI("dlopen_ns file:%{public}s, mode:%{public}x , caller_addr:%{public}p , dlns->name:%{public}s.",
3643 		file,
3644 		mode,
3645 		caller_addr,
3646 		dlns ? dlns->name : "NULL");
3647 	return dlopen_impl(file, mode, dlns->name, caller_addr, NULL);
3648 }
3649 
dlopen_ns_ext(Dl_namespace * dlns,const char * file,int mode,const dl_extinfo * extinfo)3650 void *dlopen_ns_ext(Dl_namespace *dlns, const char *file, int mode, const dl_extinfo *extinfo)
3651 {
3652 	const void *caller_addr = __builtin_return_address(0);
3653 	if (is_permitted(caller_addr, dlns->name) == false) {
3654 		return NULL;
3655 	}
3656 
3657 	musl_log_reset();
3658 	ld_log_reset();
3659 	LD_LOGI("dlopen_ns_ext file:%{public}s, mode:%{public}x , caller_addr:%{public}p , "
3660 			"dlns->name:%{public}s. , extinfo->flag:%{public}x",
3661 		file,
3662 		mode,
3663 		caller_addr,
3664 		dlns->name,
3665 		extinfo ? extinfo->flag : 0);
3666 	return dlopen_impl(file, mode, dlns->name, caller_addr, extinfo);
3667 }
3668 
dlns_create2(Dl_namespace * dlns,const char * lib_path,int flags)3669 int dlns_create2(Dl_namespace *dlns, const char *lib_path, int flags)
3670 {
3671 	if (!dlns) {
3672 		LD_LOGE("dlns_create2 dlns is null.");
3673 		return EINVAL;
3674 	}
3675 	ns_t *ns;
3676 
3677 	pthread_rwlock_wrlock(&lock);
3678 	const void *caller_addr = __builtin_return_address(0);
3679 	if (is_permitted(caller_addr, dlns->name) == false) {
3680 		pthread_rwlock_unlock(&lock);
3681 		return EPERM;
3682 	}
3683 
3684 	ns = find_ns_by_name(dlns->name);
3685 	if (ns) {
3686 		LD_LOGE("dlns_create2 ns is exist.");
3687 		pthread_rwlock_unlock(&lock);
3688 		return EEXIST;
3689 	}
3690 	ns = ns_alloc();
3691 	if (!ns) {
3692 		LD_LOGE("dlns_create2 no memery.");
3693 		pthread_rwlock_unlock(&lock);
3694 		return ENOMEM;
3695 	}
3696 	ns_set_name(ns, dlns->name);
3697 	ns_set_flag(ns, flags);
3698 	ns_add_dso(ns, get_default_ns()->ns_dsos->dsos[0]); /* add main app to this namespace*/
3699 	nslist_add_ns(ns); /* add ns to list*/
3700 	ns_set_lib_paths(ns, lib_path);
3701 
3702 	if ((flags & CREATE_INHERIT_DEFAULT) != 0) {
3703 		ns_add_inherit(ns, get_default_ns(), NULL);
3704 	}
3705 
3706 	if ((flags & CREATE_INHERIT_CURRENT) != 0) {
3707 		struct dso *caller;
3708 		caller_addr = __builtin_return_address(0);
3709 		caller = (struct dso *)addr2dso((size_t)caller_addr);
3710 		if (caller && caller->namespace) {
3711 			ns_add_inherit(ns, caller->namespace, NULL);
3712 		}
3713 	}
3714 
3715 	LD_LOGI("dlns_create2:"
3716 			"ns_name: %{public}s ,"
3717 			"separated:%{public}d ,"
3718 			"lib_paths:%{public}s ",
3719 			ns->ns_name, ns->separated, ns->lib_paths);
3720 	pthread_rwlock_unlock(&lock);
3721 
3722 	return 0;
3723 }
3724 
dlns_create(Dl_namespace * dlns,const char * lib_path)3725 int dlns_create(Dl_namespace *dlns, const char *lib_path)
3726 {
3727 	LD_LOGI("dlns_create lib_paths:%{public}s", lib_path);
3728 	return dlns_create2(dlns, lib_path, CREATE_INHERIT_DEFAULT);
3729 }
3730 
dlns_inherit(Dl_namespace * dlns,Dl_namespace * inherited,const char * shared_libs)3731 int dlns_inherit(Dl_namespace *dlns, Dl_namespace *inherited, const char *shared_libs)
3732 {
3733 	if (!dlns || !inherited) {
3734 		LD_LOGE("dlns_inherit dlns or inherited is null.");
3735 		return EINVAL;
3736 	}
3737 
3738 	pthread_rwlock_wrlock(&lock);
3739 	const void *caller_addr = __builtin_return_address(0);
3740 	if (is_permitted(caller_addr, dlns->name) == false) {
3741 		pthread_rwlock_unlock(&lock);
3742 		return EPERM;
3743 	}
3744 
3745 	ns_t* ns = find_ns_by_name(dlns->name);
3746 	ns_t* ns_inherited = find_ns_by_name(inherited->name);
3747 	if (!ns || !ns_inherited) {
3748 		LD_LOGE("dlns_inherit ns or ns_inherited is not found.");
3749 		pthread_rwlock_unlock(&lock);
3750 		return ENOKEY;
3751 	}
3752 	ns_add_inherit(ns, ns_inherited, shared_libs);
3753 	pthread_rwlock_unlock(&lock);
3754 
3755 	return 0;
3756 }
3757 
dlclose_ns(struct dso * p)3758 static void dlclose_ns(struct dso *p)
3759 {
3760 	if (!p) return;
3761 	ns_t * ns = p->namespace;
3762 	if (!ns||!ns->ns_dsos) return;
3763 	for (size_t i=0; i<ns->ns_dsos->num; i++) {
3764 		if (p == ns->ns_dsos->dsos[i]) {
3765 			for (size_t j=i+1; j<ns->ns_dsos->num; j++) {
3766 				ns->ns_dsos->dsos[j-1] = ns->ns_dsos->dsos[j];
3767 			}
3768 			ns->ns_dsos->num--;
3769 			return;
3770 		}
3771 	}
3772 }
3773 
__dl_invalid_handle(void * h)3774 hidden int __dl_invalid_handle(void *h)
3775 {
3776 	struct dso *p;
3777 	for (p=head; p; p=p->next) if (h==p) return 0;
3778 	error("Invalid library handle %p", (void *)h);
3779 	return 1;
3780 }
3781 
addr2dso(size_t a)3782 void *addr2dso(size_t a)
3783 {
3784 	struct dso *p;
3785 	size_t i;
3786 	for (p=head; p; p=p->next) {
3787 		if (a < p->map || a - (size_t)p->map >= p->map_len) continue;
3788 		Phdr *ph = p->phdr;
3789 		size_t phcnt = p->phnum;
3790 		size_t entsz = p->phentsize;
3791 		size_t base = (size_t)p->base;
3792 		for (; phcnt--; ph=(void *)((char *)ph+entsz)) {
3793 			if (ph->p_type != PT_LOAD) continue;
3794 			if (a-base-ph->p_vaddr < ph->p_memsz)
3795 				return p;
3796 		}
3797 		if (a-(size_t)p->map < p->map_len)
3798 			return 0;
3799 	}
3800 	return 0;
3801 }
3802 
do_dlsym(struct dso * p,const char * s,const char * v,void * ra)3803 static void *do_dlsym(struct dso *p, const char *s, const char *v, void *ra)
3804 {
3805 	int use_deps = 0;
3806 	bool ra2dso = false;
3807 	ns_t *ns = NULL;
3808 	struct dso *caller = NULL;
3809 	if (p == head || p == RTLD_DEFAULT) {
3810 		p = head;
3811 		ra2dso = true;
3812 	} else if (p == RTLD_NEXT) {
3813 		p = addr2dso((size_t)ra);
3814 		if (!p) p=head;
3815 		p = p->next;
3816 		ra2dso = true;
3817 #ifndef HANDLE_RANDOMIZATION
3818 	} else if (__dl_invalid_handle(p)) {
3819 		return 0;
3820 #endif
3821 	} else {
3822 		use_deps = 1;
3823 		ns = p->namespace;
3824 	}
3825 	if (ra2dso) {
3826 		caller = (struct dso *)addr2dso((size_t)ra);
3827 		if (caller && caller->namespace) {
3828 			ns = caller->namespace;
3829 		}
3830 	}
3831 	trace_marker_begin(HITRACE_TAG_MUSL, "dlsym: ", (s == NULL ? "(NULL)" : s));
3832 	struct verinfo verinfo = { .s = s, .v = v, .use_vna_hash = false };
3833 	struct symdef def = use_deps ? find_sym_by_deps(p, &verinfo, 0, ns) :
3834 		find_sym2(p, &verinfo, 0, use_deps, ns);
3835 	trace_marker_end(HITRACE_TAG_MUSL);
3836 	if (!def.sym) {
3837 		LD_LOGW("do_dlsym failed: symbol not found. so=%{public}s s=%{public}s v=%{public}s",
3838 			(p == NULL ? "NULL" : p->name), s, v);
3839 		error("do_dlsym failed: Symbol not found: %s, version: %s so=%s",
3840 			s, strlen(v) > 0 ? v : "null", (p == NULL ? "NULL" : p->name));
3841 		return 0;
3842 	}
3843 	if ((def.sym->st_info&0xf) == STT_TLS)
3844 		return __tls_get_addr((tls_mod_off_t []){def.dso->tls_id, def.sym->st_value-DTP_OFFSET});
3845 	if (DL_FDPIC && (def.sym->st_info&0xf) == STT_FUNC)
3846 		return def.dso->funcdescs + (def.sym - def.dso->syms);
3847 	return laddr(def.dso, def.sym->st_value);
3848 }
3849 
3850 extern int invalidate_exit_funcs(struct dso *p);
3851 
so_can_unload(struct dso * p,int check_flag)3852 static int so_can_unload(struct dso *p, int check_flag)
3853 {
3854 	if ((check_flag & UNLOAD_COMMON_CHECK) != 0) {
3855 		if (__dl_invalid_handle(p)) {
3856 			LD_LOGE("[dlclose]: invalid handle %{public}p", p);
3857 			error("[dlclose]: Handle is invalid.");
3858 			return 0;
3859 		}
3860 
3861 		if (!p->by_dlopen) {
3862 			LD_LOGD("[dlclose]: skip unload %{public}s because it's not loaded by dlopen", p->name);
3863 			return 0;
3864 		}
3865 
3866 		/* dso is marked  as RTLD_NODELETE library, do nothing here. */
3867 		if ((p->flags & DSO_FLAGS_NODELETE) != 0) {
3868 			LD_LOGD("[dlclose]: skip unload %{public}s because flags is RTLD_NODELETE", p->name);
3869 			return 0;
3870 		}
3871 	}
3872 
3873 	if ((check_flag & UNLOAD_NR_DLOPEN_CHECK) != 0) {
3874 		if (p->nr_dlopen > 0) {
3875 			LD_LOGD("[dlclose]: skip unload %{public}s because nr_dlopen=%{public}d > 0", p->name, p->nr_dlopen);
3876 			return 0;
3877 		}
3878 	}
3879 
3880 	return 1;
3881 }
3882 
dlclose_post(struct dso * p)3883 static int dlclose_post(struct dso *p)
3884 {
3885 	if (p == NULL) {
3886 		return -1;
3887 	}
3888 #ifdef ENABLE_HWASAN
3889 		if (libc.unload_hook) {
3890 			libc.unload_hook((unsigned long int)p->base, p->phdr, p->phnum);
3891 		}
3892 #endif
3893 	unmap_library(p);
3894 	if (p->parents) {
3895 		free(p->parents);
3896 	}
3897 	free_reloc_can_search_dso(p);
3898 	if (p->tls.size == 0) {
3899 		free(p);
3900 	}
3901 
3902 	return 0;
3903 }
3904 
dlclose_impl(struct dso * p)3905 static int dlclose_impl(struct dso *p)
3906 {
3907 	struct dso *d;
3908 
3909 	trace_marker_reset();
3910 	trace_marker_begin(HITRACE_TAG_MUSL, "dlclose", p->name);
3911 
3912 	/* remove dso symbols from global list */
3913 	if (p->syms_next) {
3914 		for (d = head; d->syms_next != p; d = d->syms_next)
3915 			; /* NOP */
3916 		d->syms_next = p->syms_next;
3917 	} else if (p == syms_tail) {
3918 		for (d = head; d->syms_next != p; d = d->syms_next)
3919 			; /* NOP */
3920 		d->syms_next = NULL;
3921 		syms_tail = d;
3922 	}
3923 
3924 	/* remove dso from lazy list if needed */
3925 	if (p == lazy_head) {
3926 		lazy_head = p->lazy_next;
3927 	} else if (p->lazy_next) {
3928 		for (d = lazy_head; d->lazy_next != p; d = d->lazy_next)
3929 			; /* NOP */
3930 		d->lazy_next = p->lazy_next;
3931 	}
3932 
3933 	pthread_mutex_lock(&init_fini_lock);
3934 	/* remove dso from fini list */
3935 	if (p == fini_head) {
3936 		fini_head = p->fini_next;
3937 	} else if (p->fini_next) {
3938 		for (d = fini_head; d->fini_next != p; d = d->fini_next)
3939 			; /* NOP */
3940 		d->fini_next = p->fini_next;
3941 	}
3942 	pthread_mutex_unlock(&init_fini_lock);
3943 
3944 	/* empty tls image */
3945 	if (p->tls.size != 0) {
3946 		p->tls.image = NULL;
3947 	}
3948 
3949 	/* remove dso from global dso list */
3950 	if (p == tail) {
3951 		tail = p->prev;
3952 		tail->next = NULL;
3953 	} else {
3954 		p->next->prev = p->prev;
3955 		p->prev->next = p->next;
3956 	}
3957 
3958 	/* remove dso from namespace */
3959 	dlclose_ns(p);
3960 
3961 	/* */
3962 	void* handle = find_handle_by_dso(p);
3963 	if (handle) {
3964 		remove_handle_node(handle);
3965 	}
3966 
3967 	/* after destruct, invalidate atexit funcs which belong to this dso */
3968 #if (defined(FEATURE_ATEXIT_CB_PROTECT))
3969 	invalidate_exit_funcs(p);
3970 #endif
3971 
3972 	notify_remove_to_debugger(p);
3973 
3974 	unmap_dso_from_cfi_shadow(p);
3975 
3976 	if (p->lazy != NULL)
3977 		free(p->lazy);
3978 	if (p->deps != no_deps)
3979 		free(p->deps);
3980 
3981 	trace_marker_end(HITRACE_TAG_MUSL);
3982 
3983 	return 0;
3984 }
3985 
do_dlclose(struct dso * p)3986 static int do_dlclose(struct dso *p)
3987 {
3988 	struct dso_entry *ef = NULL;
3989 	struct dso_entry *ef_tmp = NULL;
3990 	size_t n;
3991 	int unload_check_result;
3992 	TAILQ_HEAD(unload_queue, dso_entry) unload_queue;
3993 	TAILQ_HEAD(need_unload_queue, dso_entry) need_unload_queue;
3994 	unload_check_result = so_can_unload(p, UNLOAD_COMMON_CHECK);
3995 	if (unload_check_result != 1) {
3996 		return unload_check_result;
3997 	}
3998 	// Unconditionally subtract 1 because unconditionally add 1 at dlopen_post.
3999 	if (p->nr_dlopen > 0) {
4000 		--(p->nr_dlopen);
4001 	} else {
4002 		LD_LOGE("[dlclose]: number of dlopen and dlclose of %{public}s doesn't match when dlclose %{public}s",
4003 		        p->name, p->name);
4004 		return 0;
4005 	}
4006 
4007 	if (p->bfs_built) {
4008 		for (int i = 0; p->deps[i]; i++) {
4009 			if (p->deps[i]->nr_dlopen > 0) {
4010 				p->deps[i]->nr_dlopen--;
4011 			} else {
4012 				LD_LOGE("[dlclose]: number of dlopen and dlclose of %{public}s doesn't match when dlclose %{public}s",
4013 						p->deps[i]->name, p->name);
4014 				return 0;
4015 			}
4016 		}
4017 	}
4018 	unload_check_result = so_can_unload(p, UNLOAD_NR_DLOPEN_CHECK);
4019 	if (unload_check_result != 1) {
4020 		return unload_check_result;
4021 	}
4022 	TAILQ_INIT(&unload_queue);
4023 	TAILQ_INIT(&need_unload_queue);
4024 	struct dso_entry *start_entry = (struct dso_entry *)malloc(sizeof(struct dso_entry));
4025 	start_entry->dso = p;
4026 	TAILQ_INSERT_TAIL(&unload_queue, start_entry, entries);
4027 
4028 	while (!TAILQ_EMPTY(&unload_queue)) {
4029 		struct dso_entry *ecur = TAILQ_FIRST(&unload_queue);
4030 		struct dso *cur = ecur->dso;
4031 		TAILQ_REMOVE(&unload_queue, ecur, entries);
4032 		bool already_in_need_unload_queue = false;
4033 		TAILQ_FOREACH(ef, &need_unload_queue, entries) {
4034 			if (ef->dso == cur) {
4035 				already_in_need_unload_queue = true;
4036 				break;
4037 			}
4038 		}
4039 		if (already_in_need_unload_queue) {
4040 			continue;
4041 		}
4042 		TAILQ_INSERT_TAIL(&need_unload_queue, ecur, entries);
4043 		for (int i = 0; i < cur->ndeps_direct; i++) {
4044 			remove_dso_parent(cur->deps[i], cur);
4045 			if ((cur->deps[i]->parents_count == 0) && (so_can_unload(cur->deps[i], UNLOAD_ALL_CHECK) == 1)) {
4046 				bool already_in_unload_queue = false;
4047 				TAILQ_FOREACH(ef, &unload_queue, entries) {
4048 					if (ef->dso == cur->deps[i]) {
4049 						already_in_unload_queue = true;
4050 						break;
4051 					}
4052 				}
4053 				if (already_in_unload_queue) {
4054 					continue;
4055 				}
4056 
4057 				struct dso_entry *edeps = (struct dso_entry *)malloc(sizeof(struct dso_entry));
4058 				edeps->dso = cur->deps[i];
4059 				TAILQ_INSERT_TAIL(&unload_queue, edeps, entries);
4060 			}
4061 		} /* for */
4062 	} /* while */
4063 
4064 	if (is_dlclose_debug_enable()) {
4065 		TAILQ_FOREACH(ef, &need_unload_queue, entries) {
4066 			LD_LOGE("[dlclose]: unload %{public}s succeed when dlclose %{public}s", ef->dso->name, p->name);
4067 		}
4068 		for (size_t deps_num = 0; p->deps[deps_num]; deps_num++) {
4069 			bool ready_to_unload = false;
4070 			TAILQ_FOREACH(ef, &need_unload_queue, entries) {
4071 				if (ef->dso == p->deps[deps_num]) {
4072 					ready_to_unload = true;
4073 					break;
4074 				}
4075 			}
4076 			if (!ready_to_unload) {
4077 				LD_LOGE("[dlclose]: unload %{public}s failed when dlclose %{public}s,"
4078 				        "nr_dlopen:%{public}d, by_dlopen:%{public}d, parents_count:%{public}d",
4079 						p->deps[deps_num]->name, p->name, p->deps[deps_num]->nr_dlopen,
4080 						p->deps[deps_num]->by_dlopen, p->deps[deps_num]->parents_count);
4081 			}
4082 		}
4083 	}
4084 
4085 	TAILQ_FOREACH(ef, &need_unload_queue, entries) {
4086 		dlclose_impl(ef->dso);
4087 	}
4088 
4089 	TAILQ_FOREACH(ef, &need_unload_queue, entries) {
4090 		/* call destructors if needed */
4091 		pthread_mutex_lock(&init_fini_lock);
4092 		int constructed = ef->dso->constructed;
4093 		pthread_mutex_unlock(&init_fini_lock);
4094 
4095 		if (constructed) {
4096 			size_t dyn[DYN_CNT];
4097 			decode_vec(ef->dso->dynv, dyn, DYN_CNT);
4098 			if (dyn[0] & (1<<DT_FINI_ARRAY)) {
4099 				n = dyn[DT_FINI_ARRAYSZ] / sizeof(size_t);
4100 				size_t *fn = (size_t *)laddr(ef->dso, dyn[DT_FINI_ARRAY]) + n;
4101 				trace_marker_begin(HITRACE_TAG_MUSL, "calling destructors:", ef->dso->name);
4102 
4103 				pthread_rwlock_unlock(&lock);
4104 				while (n--)
4105 					((void (*)(void))*--fn)();
4106 				pthread_rwlock_wrlock(&lock);
4107 
4108 				trace_marker_end(HITRACE_TAG_MUSL);
4109 			}
4110 			pthread_mutex_lock(&init_fini_lock);
4111 			ef->dso->constructed = 0;
4112 			pthread_mutex_unlock(&init_fini_lock);
4113 		}
4114 	}
4115 	// Unload all sos at the end because weak symbol may cause later unloaded so to access the previous so's function.
4116 	TAILQ_FOREACH(ef, &need_unload_queue, entries) {
4117 		dlclose_post(ef->dso);
4118 	}
4119 	// Free dso_entry.
4120 	TAILQ_FOREACH_SAFE(ef, &need_unload_queue, entries, ef_tmp) {
4121 		if (ef) {
4122 			free(ef);
4123 		}
4124 	}
4125 
4126 	return 0;
4127 }
4128 
__dlclose(void * p)4129 hidden int __dlclose(void *p)
4130 {
4131 	int rc;
4132 	pthread_rwlock_wrlock(&lock);
4133 	if (shutting_down) {
4134 		error("Cannot dlclose while program is exiting.");
4135 		pthread_rwlock_unlock(&lock);
4136 		return -1;
4137 	}
4138 #ifdef HANDLE_RANDOMIZATION
4139 	struct dso *dso = find_dso_by_handle(p);
4140 	if (dso == NULL) {
4141 		errno = EINVAL;
4142 		error("Handle is invalid.");
4143 		LD_LOGE("Handle is not find.");
4144 		pthread_rwlock_unlock(&lock);
4145 		return -1;
4146 	}
4147 	rc = do_dlclose(dso);
4148 #else
4149 	rc = do_dlclose(p);
4150 #endif
4151 	pthread_rwlock_unlock(&lock);
4152 	return rc;
4153 }
4154 
sym_is_matched(const Sym * sym,size_t addr_offset_so)4155 static inline int sym_is_matched(const Sym* sym, size_t addr_offset_so) {
4156 	return sym->st_value &&
4157 		(1<<(sym->st_info&0xf) != STT_TLS) &&
4158 		(addr_offset_so >= sym->st_value) &&
4159 		(addr_offset_so < sym->st_value + sym->st_size);
4160 }
4161 
find_addr_by_elf(size_t addr_offset_so,struct dso * p)4162 static inline Sym* find_addr_by_elf(size_t addr_offset_so, struct dso *p) {
4163 	uint32_t nsym = p->hashtab[1];
4164 	Sym *sym = p->syms;
4165 	for (; nsym; nsym--, sym++) {
4166 		if (sym_is_matched(sym, addr_offset_so)) {
4167 			return sym;
4168 		}
4169 	}
4170 
4171 	return NULL;
4172 }
4173 
find_addr_by_gnu(size_t addr_offset_so,struct dso * p)4174 static inline Sym* find_addr_by_gnu(size_t addr_offset_so, struct dso *p) {
4175 
4176 	size_t i, nsym, first_hash_sym_index;
4177 	uint32_t *hashval;
4178 	Sym *sym_tab = p->syms;
4179 	uint32_t *buckets= p->ghashtab + 4 + (p->ghashtab[2]*sizeof(size_t)/4);
4180 	// Points to the first defined symbol, all symbols before it are undefined.
4181 	first_hash_sym_index = buckets[0];
4182 	Sym *sym = &sym_tab[first_hash_sym_index];
4183 
4184 	// Get the location pointed by the last bucket.
4185 	for (i = nsym = 0; i < p->ghashtab[0]; i++) {
4186 		if (buckets[i] > nsym)
4187 			nsym = buckets[i];
4188 	}
4189 
4190 	for (i = first_hash_sym_index; i < nsym; i++) {
4191 		if (sym_is_matched(sym, addr_offset_so)) {
4192 			return sym;
4193 		}
4194 		sym++;
4195 	}
4196 
4197 	// Start traversing the hash list from the position pointed to by the last bucket.
4198 	if (nsym) {
4199 		hashval = buckets + p->ghashtab[0] + (nsym - p->ghashtab[1]);
4200 		do {
4201 			nsym++;
4202 			if (sym_is_matched(sym, addr_offset_so)) {
4203 				return sym;
4204 			}
4205 			sym++;
4206 		}
4207 		while (!(*hashval++ & 1));
4208 	}
4209 
4210 	return NULL;
4211 }
4212 
4213 
dladdr(const void * addr_arg,Dl_info * info)4214 int dladdr(const void *addr_arg, Dl_info *info)
4215 {
4216 	size_t addr = (size_t)addr_arg;
4217 	struct dso *p;
4218 	Sym *match_sym = NULL;
4219 	char *strings;
4220 
4221 	pthread_rwlock_rdlock(&lock);
4222 	p = addr2dso(addr);
4223 	pthread_rwlock_unlock(&lock);
4224 
4225 	if (!p) return 0;
4226 
4227 	strings = p->strings;
4228 	size_t addr_offset_so = addr - (size_t)p->base;
4229 
4230 	info->dli_fname = p->name;
4231 	info->dli_fbase = p->map;
4232 
4233 	if (p->ghashtab) {
4234 		match_sym = find_addr_by_gnu(addr_offset_so, p);
4235 
4236 	} else {
4237 		match_sym = find_addr_by_elf(addr_offset_so, p);
4238 	}
4239 
4240 	if (!match_sym) {
4241 		info->dli_sname = 0;
4242 		info->dli_saddr = 0;
4243 		return 1;
4244 	}
4245 	info->dli_sname = strings + match_sym->st_name;
4246 	info->dli_saddr = (void *)laddr(p, match_sym->st_value);
4247 	return 1;
4248 }
4249 
__dlsym(void * restrict p,const char * restrict s,void * restrict ra)4250 hidden void *__dlsym(void *restrict p, const char *restrict s, void *restrict ra)
4251 {
4252 	void *res;
4253 	pthread_rwlock_rdlock(&lock);
4254 #ifdef HANDLE_RANDOMIZATION
4255 	if ((p != RTLD_DEFAULT) && (p != RTLD_NEXT)) {
4256 		struct dso *dso = find_dso_by_handle(p);
4257 		if (dso == NULL) {
4258 			pthread_rwlock_unlock(&lock);
4259 			return 0;
4260 		}
4261 		res = do_dlsym(dso, s, "", ra);
4262 	} else {
4263 		res = do_dlsym(p, s, "", ra);
4264 	}
4265 #else
4266 	res = do_dlsym(p, s, "", ra);
4267 #endif
4268 	pthread_rwlock_unlock(&lock);
4269 	return res;
4270 }
4271 
__dlvsym(void * restrict p,const char * restrict s,const char * restrict v,void * restrict ra)4272 hidden void *__dlvsym(void *restrict p, const char *restrict s, const char *restrict v, void *restrict ra)
4273 {
4274 	void *res;
4275 	pthread_rwlock_rdlock(&lock);
4276 #ifdef HANDLE_RANDOMIZATION
4277 	if ((p != RTLD_DEFAULT) && (p != RTLD_NEXT)) {
4278 		struct dso *dso = find_dso_by_handle(p);
4279 		if (dso == NULL) {
4280 			pthread_rwlock_unlock(&lock);
4281 			return 0;
4282 		}
4283 		res = do_dlsym(dso, s, v, ra);
4284 	} else {
4285 		res = do_dlsym(p, s, v, ra);
4286 	}
4287 #else
4288 	res = do_dlsym(p, s, v, ra);
4289 #endif
4290 	pthread_rwlock_unlock(&lock);
4291 	return res;
4292 }
4293 
__dlsym_redir_time64(void * restrict p,const char * restrict s,void * restrict ra)4294 hidden void *__dlsym_redir_time64(void *restrict p, const char *restrict s, void *restrict ra)
4295 {
4296 #if _REDIR_TIME64
4297 	const char *suffix, *suffix2 = "";
4298 	char redir[36];
4299 
4300 	/* Map the symbol name to a time64 version of itself according to the
4301 	 * pattern used for naming the redirected time64 symbols. */
4302 	size_t l = strnlen(s, sizeof redir);
4303 	if (l<4 || l==sizeof redir) goto no_redir;
4304 	if (s[l-2]=='_' && s[l-1]=='r') {
4305 		l -= 2;
4306 		suffix2 = s+l;
4307 	}
4308 	if (l<4) goto no_redir;
4309 	if (!strcmp(s+l-4, "time")) suffix = "64";
4310 	else suffix = "_time64";
4311 
4312 	/* Use the presence of the remapped symbol name in libc to determine
4313 	 * whether it's one that requires time64 redirection; replace if so. */
4314 	snprintf(redir, sizeof redir, "__%.*s%s%s", (int)l, s, suffix, suffix2);
4315 	if (find_sym(&ldso, redir, 1).sym) s = redir;
4316 no_redir:
4317 #endif
4318 	return __dlsym(p, s, ra);
4319 }
4320 
dl_iterate_phdr(int (* callback)(struct dl_phdr_info * info,size_t size,void * data),void * data)4321 int dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size_t size, void *data), void *data)
4322 {
4323 	struct dso *current;
4324 	struct dl_phdr_info info;
4325 	int ret = 0;
4326 	for(current = head; current;) {
4327 		info.dlpi_addr      = (uintptr_t)current->base;
4328 		info.dlpi_name      = current->name;
4329 		info.dlpi_phdr      = current->phdr;
4330 		info.dlpi_phnum     = current->phnum;
4331 		info.dlpi_adds      = gencnt;
4332 		info.dlpi_subs      = 0;
4333 		info.dlpi_tls_modid = current->tls_id;
4334 		info.dlpi_tls_data = !current->tls_id ? 0 :
4335 			__tls_get_addr((tls_mod_off_t[]){current->tls_id,0});
4336 
4337 		ret = (callback)(&info, sizeof (info), data);
4338 
4339 		if (ret != 0) break;
4340 
4341 		pthread_rwlock_rdlock(&lock);
4342 		current = current->next;
4343 		pthread_rwlock_unlock(&lock);
4344 	}
4345 	return ret;
4346 }
4347 
error(const char * fmt,...)4348 static void error(const char *fmt, ...)
4349 {
4350 	va_list ap;
4351 	va_start(ap, fmt);
4352 	if (!runtime) {
4353 		vdprintf(2, fmt, ap);
4354 		dprintf(2, "\n");
4355 		ldso_fail = 1;
4356 		va_end(ap);
4357 		return;
4358 	}
4359 	__dl_vseterr(fmt, ap);
4360 	va_end(ap);
4361 }
4362 
dlns_set_namespace_lib_path(const char * name,const char * lib_path)4363 int dlns_set_namespace_lib_path(const char * name, const char * lib_path)
4364 {
4365 	if (!name || !lib_path) {
4366 		LD_LOGE("dlns_set_namespace_lib_path name or lib_path is null.");
4367 		return EINVAL;
4368 	}
4369 
4370 	pthread_rwlock_wrlock(&lock);
4371 	const void *caller_addr = __builtin_return_address(0);
4372 	if (is_permitted(caller_addr, name) == false) {
4373 		pthread_rwlock_unlock(&lock);
4374 		return EPERM;
4375 	}
4376 
4377 	ns_t* ns = find_ns_by_name(name);
4378 	if (!ns) {
4379 		pthread_rwlock_unlock(&lock);
4380 		LD_LOGE("dlns_set_namespace_lib_path fail, input ns name : [%{public}s] is not found.", name);
4381 		return ENOKEY;
4382 	}
4383 
4384 	ns_set_lib_paths(ns, lib_path);
4385 	pthread_rwlock_unlock(&lock);
4386 	return 0;
4387 }
4388 
dlns_set_namespace_separated(const char * name,const bool separated)4389 int dlns_set_namespace_separated(const char * name, const bool separated)
4390 {
4391 	if (!name) {
4392 		LD_LOGE("dlns_set_namespace_separated name  is null.");
4393 		return EINVAL;
4394 	}
4395 
4396 	pthread_rwlock_wrlock(&lock);
4397 	const void *caller_addr = __builtin_return_address(0);
4398 	if (is_permitted(caller_addr, name) == false) {
4399 		pthread_rwlock_unlock(&lock);
4400 		return EPERM;
4401 	}
4402 
4403 	ns_t* ns = find_ns_by_name(name);
4404 	if (!ns) {
4405 		pthread_rwlock_unlock(&lock);
4406 		LD_LOGE("dlns_set_namespace_separated fail, input ns name : [%{public}s] is not found.", name);
4407 		return ENOKEY;
4408 	}
4409 
4410 	ns_set_separated(ns, separated);
4411 	pthread_rwlock_unlock(&lock);
4412 	return 0;
4413 }
4414 
dlns_set_namespace_permitted_paths(const char * name,const char * permitted_paths)4415 int dlns_set_namespace_permitted_paths(const char * name, const char * permitted_paths)
4416 {
4417 	if (!name || !permitted_paths) {
4418 		LD_LOGE("dlns_set_namespace_permitted_paths name or permitted_paths is null.");
4419 		return EINVAL;
4420 	}
4421 
4422 	pthread_rwlock_wrlock(&lock);
4423 	const void *caller_addr = __builtin_return_address(0);
4424 	if (is_permitted(caller_addr, name) == false) {
4425 		pthread_rwlock_unlock(&lock);
4426 		return EPERM;
4427 	}
4428 
4429 	ns_t* ns = find_ns_by_name(name);
4430 	if (!ns) {
4431 		pthread_rwlock_unlock(&lock);
4432 		LD_LOGE("dlns_set_namespace_permitted_paths fail, input ns name : [%{public}s] is not found.", name);
4433 		return ENOKEY;
4434 	}
4435 
4436 	ns_set_permitted_paths(ns, permitted_paths);
4437 	pthread_rwlock_unlock(&lock);
4438 	return 0;
4439 }
4440 
dlns_set_namespace_allowed_libs(const char * name,const char * allowed_libs)4441 int dlns_set_namespace_allowed_libs(const char * name, const char * allowed_libs)
4442 {
4443 	if (!name || !allowed_libs) {
4444 		LD_LOGE("dlns_set_namespace_allowed_libs name or allowed_libs is null.");
4445 		return EINVAL;
4446 	}
4447 
4448 	pthread_rwlock_wrlock(&lock);
4449 	const void *caller_addr = __builtin_return_address(0);
4450 	if (is_permitted(caller_addr, name) == false) {
4451 		pthread_rwlock_unlock(&lock);
4452 		return EPERM;
4453 	}
4454 
4455 	ns_t* ns = find_ns_by_name(name);
4456 	if (!ns) {
4457 		pthread_rwlock_unlock(&lock);
4458 		LD_LOGE("dlns_set_namespace_allowed_libs fail, input ns name : [%{public}s] is not found.", name);
4459 		return ENOKEY;
4460 	}
4461 
4462 	ns_set_allowed_libs(ns, allowed_libs);
4463 	pthread_rwlock_unlock(&lock);
4464 	return 0;
4465 }
4466 
handle_asan_path_open(int fd,const char * name,ns_t * namespace,char * buf,size_t buf_size)4467 int handle_asan_path_open(int fd, const char *name, ns_t *namespace, char *buf, size_t buf_size)
4468 {
4469 	LD_LOGD("handle_asan_path_open fd:%{public}d, name:%{public}s , namespace:%{public}s .",
4470 		fd,
4471 		name,
4472 		namespace ? namespace->ns_name : "NULL");
4473 	int fd_tmp = fd;
4474 	if (fd == -1 && (namespace->asan_lib_paths || namespace->lib_paths)) {
4475 		if (namespace->lib_paths && namespace->asan_lib_paths) {
4476 			size_t newlen = strlen(namespace->asan_lib_paths) + strlen(namespace->lib_paths) + 2;
4477 			char *new_lib_paths = malloc(newlen);
4478 			memset(new_lib_paths, 0, newlen);
4479 			strcpy(new_lib_paths, namespace->asan_lib_paths);
4480 			strcat(new_lib_paths, ":");
4481 			strcat(new_lib_paths, namespace->lib_paths);
4482 			fd_tmp = path_open(name, new_lib_paths, buf, buf_size);
4483 			LD_LOGD("handle_asan_path_open path_open new_lib_paths:%{public}s ,fd: %{public}d.", new_lib_paths, fd_tmp);
4484 			free(new_lib_paths);
4485 		} else if (namespace->asan_lib_paths) {
4486 			fd_tmp = path_open(name, namespace->asan_lib_paths, buf, buf_size);
4487 			LD_LOGD("handle_asan_path_open path_open asan_lib_paths:%{public}s ,fd: %{public}d.",
4488 				namespace->asan_lib_paths,
4489 				fd_tmp);
4490 		} else {
4491 			fd_tmp = path_open(name, namespace->lib_paths, buf, buf_size);
4492 			LD_LOGD(
4493 				"handle_asan_path_open path_open lib_paths:%{public}s ,fd: %{public}d.", namespace->lib_paths, fd_tmp);
4494 		}
4495 	}
4496 	return fd_tmp;
4497 }
4498 
dlopen_ext(const char * file,int mode,const dl_extinfo * extinfo)4499 void* dlopen_ext(const char *file, int mode, const dl_extinfo *extinfo)
4500 {
4501 	const void *caller_addr = __builtin_return_address(0);
4502 	musl_log_reset();
4503 	ld_log_reset();
4504 	if (extinfo != NULL) {
4505 		if ((extinfo->flag & ~(DL_EXT_VALID_FLAG_BITS)) != 0) {
4506 			LD_LOGE("Error dlopen_ext %{public}s: invalid flag %{public}x", file, extinfo->flag);
4507 			return NULL;
4508 		}
4509 	}
4510 	LD_LOGI("dlopen_ext file:%{public}s, mode:%{public}x , caller_addr:%{public}p , extinfo->flag:%{public}x",
4511 		file,
4512 		mode,
4513 		caller_addr,
4514 		extinfo ? extinfo->flag : 0);
4515 	return dlopen_impl(file, mode, NULL, caller_addr, extinfo);
4516 }
4517 
4518 #ifdef LOAD_ORDER_RANDOMIZATION
open_library_by_path(const char * name,const char * s,struct loadtask * task,struct zip_info * z_info)4519 static void open_library_by_path(const char *name, const char *s, struct loadtask *task, struct zip_info *z_info)
4520 {
4521 	char *buf = task->buf;
4522 	size_t buf_size = sizeof task->buf;
4523 	size_t l;
4524 	for (;;) {
4525 		s += strspn(s, ":\n");
4526 		l = strcspn(s, ":\n");
4527 		if (l-1 >= INT_MAX) return;
4528 		if (snprintf(buf, buf_size, "%.*s/%s", (int)l, s, name) < buf_size) {
4529 			char *separator = strstr(buf, ZIP_FILE_PATH_SEPARATOR);
4530 			if (separator != NULL) {
4531 				int res = open_uncompressed_library_in_zipfile(buf, z_info, separator);
4532 				if (res == 0) {
4533 					task->fd = z_info->fd;
4534 					task->file_offset = z_info->file_offset;
4535 					break;
4536 				} else {
4537 					memset(z_info->path_buf, 0, sizeof(z_info->path_buf));
4538 				}
4539 			} else {
4540 				if ((task->fd = open(buf, O_RDONLY|O_CLOEXEC))>=0) break;
4541 			}
4542 		}
4543 		s += l;
4544 	}
4545 	return;
4546 }
4547 
handle_asan_path_open_by_task(int fd,const char * name,ns_t * namespace,struct loadtask * task,struct zip_info * z_info)4548 static void handle_asan_path_open_by_task(int fd, const char *name, ns_t *namespace, struct loadtask *task,
4549 										  struct zip_info *z_info)
4550 {
4551 	LD_LOGD("handle_asan_path_open_by_task fd:%{public}d, name:%{public}s , namespace:%{public}s .",
4552 			fd,
4553 			name,
4554 			namespace ? namespace->ns_name : "NULL");
4555 	if (fd == -1 && (namespace->asan_lib_paths || namespace->lib_paths)) {
4556 		if (namespace->lib_paths && namespace->asan_lib_paths) {
4557 			size_t newlen = strlen(namespace->asan_lib_paths) + strlen(namespace->lib_paths) + 2;
4558 			char *new_lib_paths = malloc(newlen);
4559 			memset(new_lib_paths, 0, newlen);
4560 			strcpy(new_lib_paths, namespace->asan_lib_paths);
4561 			strcat(new_lib_paths, ":");
4562 			strcat(new_lib_paths, namespace->lib_paths);
4563 			open_library_by_path(name, new_lib_paths, task, z_info);
4564 			LD_LOGD("handle_asan_path_open_by_task open_library_by_path new_lib_paths:%{public}s ,fd: %{public}d.",
4565 					new_lib_paths,
4566 					task->fd);
4567 			free(new_lib_paths);
4568 		} else if (namespace->asan_lib_paths) {
4569 			open_library_by_path(name, namespace->asan_lib_paths, task, z_info);
4570 			LD_LOGD("handle_asan_path_open_by_task open_library_by_path asan_lib_paths:%{public}s ,fd: %{public}d.",
4571 					namespace->asan_lib_paths,
4572 					task->fd);
4573 		} else {
4574 			open_library_by_path(name, namespace->lib_paths, task, z_info);
4575 			LD_LOGD("handle_asan_path_open_by_task open_library_by_path lib_paths:%{public}s ,fd: %{public}d.",
4576 					namespace->lib_paths,
4577 					task->fd);
4578 		}
4579 	}
4580 	return;
4581 }
4582 
4583 /* Used to get an uncompress library offset in zip file, then we can use the offset to mmap the library directly. */
open_uncompressed_library_in_zipfile(const char * path,struct zip_info * z_info,char * separator)4584 int open_uncompressed_library_in_zipfile(const char *path, struct zip_info *z_info, char *separator)
4585 {
4586 	struct local_file_header zip_file_header;
4587 	struct central_dir_entry c_dir_entry;
4588 	struct zip_end_locator end_locator;
4589 
4590 	/* Use "'!/' to split the path into zipfile path and library path in zipfile.
4591 	 * For example:
4592 	 * - path: x/xx/xxx.zip!/x/xx/xxx.so
4593 	 * - zipfile path: x/xx/xxx.zip
4594 	 * - library path in zipfile: x/xx/xxx.so  */
4595 	if (strlcpy(z_info->path_buf, path, PATH_BUF_SIZE) >= PATH_BUF_SIZE) {
4596 		LD_LOGE("Open uncompressed library: input path %{public}s is too long.", path);
4597 		return -1;
4598 	}
4599 	z_info->path_buf[separator - path] = '\0';
4600 	z_info->file_path_index = separator - path + 2;
4601 	char *zip_file_path = z_info->path_buf;
4602 	char *lib_path = &z_info->path_buf[z_info->file_path_index];
4603 	if (zip_file_path == NULL || lib_path == NULL) {
4604 		LD_LOGE("Open uncompressed library: get zip and lib path failed.");
4605 		return -1;
4606 	}
4607 	LD_LOGD("Open uncompressed library: input path: %{public}s, zip file path: %{public}s, library path: %{public}s.",
4608 			path, zip_file_path, lib_path);
4609 
4610 	// Get zip file length
4611 	FILE *zip_file = fopen(zip_file_path, "re");
4612 	if (zip_file == NULL) {
4613 		LD_LOGE("Open uncompressed library: fopen %{public}s failed.", zip_file_path);
4614 		return -1;
4615 	}
4616 	if (fseek(zip_file, 0, SEEK_END) != 0) {
4617 		LD_LOGE("Open uncompressed library: fseek SEEK_END failed.");
4618 		fclose(zip_file);
4619 		return -1;
4620 	}
4621 	int64_t zip_file_len = ftell(zip_file);
4622 	if (zip_file_len == -1) {
4623 		LD_LOGE("Open uncompressed library: get zip file length failed.");
4624 		fclose(zip_file);
4625 		return -1;
4626 	}
4627 
4628 	// Read end of central directory record.
4629 	size_t end_locator_len = sizeof(end_locator);
4630 	size_t end_locator_pos = zip_file_len - end_locator_len;
4631 	if (fseek(zip_file, end_locator_pos, SEEK_SET) != 0) {
4632 		LD_LOGE("Open uncompressed library: fseek end locator position failed.");
4633 		fclose(zip_file);
4634 		return -1;
4635 	}
4636 	if (fread(&end_locator, sizeof(end_locator), 1, zip_file) != 1 || end_locator.signature != EOCD_SIGNATURE) {
4637 		LD_LOGE("Open uncompressed library: fread end locator failed.");
4638 		fclose(zip_file);
4639 		return -1;
4640 	}
4641 
4642 	char file_name[PATH_BUF_SIZE];
4643 	uint64_t current_dir_pos = end_locator.offset;
4644 	for (uint16_t i = 0; i < end_locator.total_entries; i++) {
4645 		// Read central dir entry.
4646 		if (fseek(zip_file, current_dir_pos, SEEK_SET) != 0) {
4647 			LD_LOGE("Open uncompressed library: fseek current centra dir entry position failed.");
4648 			fclose(zip_file);
4649 			return -1;
4650 		}
4651 		if (fread(&c_dir_entry, sizeof(c_dir_entry), 1, zip_file) != 1 || c_dir_entry.signature != CENTRAL_SIGNATURE) {
4652 			LD_LOGE("Open uncompressed library: fread centra dir entry failed.");
4653 			fclose(zip_file);
4654 			return -1;
4655 		}
4656 
4657 		if (fread(file_name, c_dir_entry.name_size, 1, zip_file) != 1) {
4658 			LD_LOGE("Open uncompressed library: fread file name failed.");
4659 			fclose(zip_file);
4660 			return -1;
4661 		}
4662 		if (strcmp(file_name, lib_path) == 0) {
4663 			// Read local file header.
4664 			if (fseek(zip_file, c_dir_entry.local_header_offset, SEEK_SET) != 0) {
4665 				LD_LOGE("Open uncompressed library: fseek local file header failed.");
4666 				fclose(zip_file);
4667 				return -1;
4668 			}
4669 			if (fread(&zip_file_header, sizeof(zip_file_header), 1, zip_file) != 1) {
4670 				LD_LOGE("Open uncompressed library: fread local file header failed.");
4671 				fclose(zip_file);
4672 				return -1;
4673 			}
4674 			if (zip_file_header.signature != LOCAL_FILE_HEADER_SIGNATURE) {
4675 				LD_LOGE("Open uncompressed library: read local file header signature error.");
4676 				fclose(zip_file);
4677 				return -1;
4678 			}
4679 
4680 			z_info->file_offset = c_dir_entry.local_header_offset + sizeof(zip_file_header) +
4681 									zip_file_header.name_size + zip_file_header.extra_size;
4682 			if (zip_file_header.compression_method != COMPRESS_STORED || z_info->file_offset % PAGE_SIZE != 0) {
4683 				LD_LOGE("Open uncompressed library: open %{public}s in %{public}s failed because of misalignment or saved with compression."
4684 						"compress method %{public}d, file offset %{public}lu",
4685 						lib_path, zip_file_path, zip_file_header.compression_method, z_info->file_offset);
4686 				fclose(zip_file);
4687 				return -2;
4688 			}
4689 			z_info->found = true;
4690 			break;
4691 		}
4692 
4693 		memset(file_name, 0, sizeof(file_name));
4694 		current_dir_pos += sizeof(c_dir_entry);
4695 		current_dir_pos += c_dir_entry.name_size + c_dir_entry.extra_size + c_dir_entry.comment_size;
4696 	}
4697 	if(!z_info->found) {
4698 		LD_LOGE("Open uncompressed library: %{public}s was not found in %{public}s.", lib_path, zip_file_path);
4699 		fclose(zip_file);
4700 		return -3;
4701 	}
4702 	z_info->fd = fileno(zip_file);
4703 
4704 	return 0;
4705 }
4706 
map_library_header(struct loadtask * task)4707 static bool map_library_header(struct loadtask *task)
4708 {
4709 	off_t off_start;
4710 	Phdr *ph;
4711 	size_t i;
4712 	size_t str_size;
4713 	off_t str_table;
4714 
4715 	ssize_t l = pread(task->fd, task->ehdr_buf, sizeof task->ehdr_buf, task->file_offset);
4716 	task->eh = task->ehdr_buf;
4717 	if (l < 0) {
4718 		LD_LOGE("Error mapping header %{public}s: failed to read fd errno: %{public}d", task->name, errno);
4719 		return false;
4720 	}
4721 	if (l < sizeof(Ehdr) || (task->eh->e_type != ET_DYN && task->eh->e_type != ET_EXEC)) {
4722 		LD_LOGE("Error mapping header %{public}s: invaliled Ehdr l=%{public}d", task->name, l);
4723 		goto noexec;
4724 	}
4725 	task->phsize = task->eh->e_phentsize * task->eh->e_phnum;
4726 	if (task->phsize > sizeof task->ehdr_buf - sizeof(Ehdr)) {
4727 		task->allocated_buf = malloc(task->phsize);
4728 		if (!task->allocated_buf) {
4729 			LD_LOGE("Error mapping header %{public}s: failed to alloc memory errno: %{public}d", task->name, errno);
4730 			return false;
4731 		}
4732 		l = pread(task->fd, task->allocated_buf, task->phsize, task->eh->e_phoff + task->file_offset);
4733 		if (l < 0) {
4734 			LD_LOGE("Error mapping header %{public}s: failed to pread errno: %{public}d", task->name, errno);
4735 			goto error;
4736 		}
4737 		if (l != task->phsize) {
4738 			LD_LOGE("Error mapping header %{public}s: unmatched phsize errno: %{public}d", task->name, errno);
4739 			goto noexec;
4740 		}
4741 		ph = task->ph0 = task->allocated_buf;
4742 	} else if (task->eh->e_phoff + task->phsize > l) {
4743 		l = pread(task->fd, task->ehdr_buf + 1, task->phsize, task->eh->e_phoff + task->file_offset);
4744 		if (l < 0) {
4745 			LD_LOGE("Error mapping header %{public}s: failed to pread errno: %{public}d", task->name, errno);
4746 			goto error;
4747 		}
4748 		if (l != task->phsize) {
4749 			LD_LOGE("Error mapping header %{public}s: unmatched phsize", task->name);
4750 			goto noexec;
4751 		}
4752 		ph = task->ph0 = (void *)(task->ehdr_buf + 1);
4753 	} else {
4754 		ph = task->ph0 = (void *)((char *)task->ehdr_buf + task->eh->e_phoff);
4755 	}
4756 
4757 	for (i = task->eh->e_phnum; i; i--, ph = (void *)((char *)ph + task->eh->e_phentsize)) {
4758 		if (ph->p_type == PT_DYNAMIC) {
4759 			task->dyn = ph->p_vaddr;
4760 		} else if (ph->p_type == PT_TLS) {
4761 			task->tls_image = ph->p_vaddr;
4762 			task->tls.align = ph->p_align;
4763 			task->tls.len = ph->p_filesz;
4764 			task->tls.size = ph->p_memsz;
4765 		}
4766 
4767 		if (ph->p_type != PT_DYNAMIC) {
4768 			continue;
4769 		}
4770 		// map the dynamic segment and the string table of the library
4771 		off_start = ph->p_offset;
4772 		off_start &= -PAGE_SIZE;
4773 		task->dyn_map_len = ph->p_memsz + (ph->p_offset - off_start);
4774 		/* The default value of file_offset is 0.
4775 		 * The value of file_offset may be greater than 0 when opening library from zip file.
4776 		 * The value of file_offset ensures PAGE_SIZE aligned. */
4777 		task->dyn_map = mmap(0, task->dyn_map_len, PROT_READ, MAP_PRIVATE, task->fd, off_start + task->file_offset);
4778 		if (task->dyn_map == MAP_FAILED) {
4779 			LD_LOGE("Error mapping header %{public}s: failed to map dynamic section errno: %{public}d", task->name, errno);
4780 			goto error;
4781 		}
4782 		task->dyn_addr = (size_t *)((unsigned char *)task->dyn_map + (ph->p_offset - off_start));
4783 		size_t dyn_tmp;
4784 		if (search_vec(task->dyn_addr, &dyn_tmp, DT_STRTAB)) {
4785 			str_table = dyn_tmp;
4786 		} else {
4787 			LD_LOGE("Error mapping header %{public}s: DT_STRTAB not found", task->name);
4788 			goto error;
4789 		}
4790 		if (search_vec(task->dyn_addr, &dyn_tmp, DT_STRSZ)) {
4791 			str_size = dyn_tmp;
4792 		} else {
4793 			LD_LOGE("Error mapping header %{public}s: DT_STRSZ not found", task->name);
4794 			goto error;
4795 		}
4796 	}
4797 
4798 	task->shsize = task->eh->e_shentsize * task->eh->e_shnum;
4799 	off_start = task->eh->e_shoff;
4800 	off_start &= -PAGE_SIZE;
4801 	task->shsize += task->eh->e_shoff - off_start;
4802 	task->shdr_allocated_buf = mmap(0, task->shsize, PROT_READ, MAP_PRIVATE, task->fd, off_start + task->file_offset);
4803 	if (task->shdr_allocated_buf == MAP_FAILED) {
4804 		LD_LOGE("Error mapping section header %{public}s: failed to map shdr_allocated_buf errno: %{public}d",
4805 			task->name, errno);
4806 		goto error;
4807 	}
4808 	Shdr *sh = (char *)task->shdr_allocated_buf + task->eh->e_shoff - off_start;
4809 	for (i = task->eh->e_shnum; i; i--, sh = (void *)((char *)sh + task->eh->e_shentsize)) {
4810 		if (sh->sh_type != SHT_STRTAB || sh->sh_addr != str_table || sh->sh_size != str_size) {
4811 			continue;
4812 		}
4813 		off_start = sh->sh_offset;
4814 		off_start &= -PAGE_SIZE;
4815 		task->str_map_len = sh->sh_size + (sh->sh_offset - off_start);
4816 		task->str_map = mmap(0, task->str_map_len, PROT_READ, MAP_PRIVATE, task->fd, off_start + task->file_offset);
4817 		if (task->str_map == MAP_FAILED) {
4818 			LD_LOGE("Error mapping section header %{public}s: failed to map string section errno: %{public}d",
4819 				task->name, errno);
4820 			goto error;
4821 		}
4822 		task->str_addr = (char *)task->str_map + sh->sh_offset - off_start;
4823 		break;
4824 	}
4825 	if (!task->dyn) {
4826 		LD_LOGE("Error mapping header %{public}s: dynamic section not found", task->name);
4827 		goto noexec;
4828 	}
4829 	return true;
4830 noexec:
4831 	errno = ENOEXEC;
4832 error:
4833 	free(task->allocated_buf);
4834 	task->allocated_buf = NULL;
4835 	if (task->shdr_allocated_buf != MAP_FAILED) {
4836 		munmap(task->shdr_allocated_buf, task->shsize);
4837 		task->shdr_allocated_buf = MAP_FAILED;
4838 	}
4839 	return false;
4840 }
4841 
task_map_library(struct loadtask * task,struct reserved_address_params * reserved_params)4842 static bool task_map_library(struct loadtask *task, struct reserved_address_params *reserved_params)
4843 {
4844 	size_t addr_min = SIZE_MAX, addr_max = 0, map_len;
4845 	size_t this_min, this_max;
4846 	size_t nsegs = 0;
4847 	off_t off_start;
4848 	Phdr *ph = task->ph0;
4849 	unsigned prot;
4850 	unsigned char *map = MAP_FAILED, *base;
4851 	size_t i;
4852 	int map_flags = MAP_PRIVATE;
4853 	size_t start_addr;
4854 	size_t start_alignment = PAGE_SIZE;
4855 	bool hugepage_enabled = false;
4856 
4857 	for (i = task->eh->e_phnum; i; i--, ph = (void *)((char *)ph + task->eh->e_phentsize)) {
4858 		if (ph->p_type == PT_GNU_RELRO) {
4859 			task->p->relro_start = ph->p_vaddr & -PAGE_SIZE;
4860 			task->p->relro_end = (ph->p_vaddr + ph->p_memsz) & -PAGE_SIZE;
4861 		} else if (ph->p_type == PT_GNU_STACK) {
4862 			if (!runtime && ph->p_memsz > __default_stacksize) {
4863 				__default_stacksize =
4864 					ph->p_memsz < DEFAULT_STACK_MAX ?
4865 					ph->p_memsz : DEFAULT_STACK_MAX;
4866 			}
4867 		}
4868 		if (ph->p_type != PT_LOAD) {
4869 			continue;
4870 		}
4871 		nsegs++;
4872 		if (ph->p_vaddr < addr_min) {
4873 			addr_min = ph->p_vaddr;
4874 			off_start = ph->p_offset;
4875 			prot = (((ph->p_flags & PF_R) ? PROT_READ : 0) |
4876 				((ph->p_flags & PF_W) ? PROT_WRITE : 0) |
4877 				((ph->p_flags & PF_X) ? PROT_EXEC : 0));
4878 		}
4879 		if (ph->p_vaddr + ph->p_memsz > addr_max) {
4880 			addr_max = ph->p_vaddr + ph->p_memsz;
4881 		}
4882 	}
4883 	if (!task->dyn) {
4884 		LD_LOGE("Error mapping library: !task->dyn dynamic section not found task->name=%{public}s", task->name);
4885 		goto noexec;
4886 	}
4887 	if (DL_FDPIC && !(task->eh->e_flags & FDPIC_CONSTDISP_FLAG)) {
4888 		task->p->loadmap = calloc(1, sizeof(struct fdpic_loadmap) + nsegs * sizeof(struct fdpic_loadseg));
4889 		if (!task->p->loadmap) {
4890 			LD_LOGE("Error mapping library: calloc failed errno=%{public}d nsegs=%{public}d", errno, nsegs);
4891 			goto error;
4892 		}
4893 		task->p->loadmap->nsegs = nsegs;
4894 		for (ph = task->ph0, i = 0; i < nsegs; ph = (void *)((char *)ph + task->eh->e_phentsize)) {
4895 			if (ph->p_type != PT_LOAD) {
4896 				continue;
4897 			}
4898 			prot = (((ph->p_flags & PF_R) ? PROT_READ : 0) |
4899 				((ph->p_flags & PF_W) ? PROT_WRITE : 0) |
4900 				((ph->p_flags & PF_X) ? PROT_EXEC : 0));
4901 			map = mmap(0, ph->p_memsz + (ph->p_vaddr & PAGE_SIZE - 1),
4902 				prot, MAP_PRIVATE,
4903 				task->fd, ph->p_offset & -PAGE_SIZE + task->file_offset);
4904 			if (map == MAP_FAILED) {
4905 				unmap_library(task->p);
4906 				LD_LOGE("Error mapping library: PT_LOAD mmap failed task->name=%{public}s errno=%{public}d map_len=%{public}d",
4907 					task->name, errno, ph->p_memsz + (ph->p_vaddr & PAGE_SIZE - 1));
4908 				goto error;
4909 			}
4910 			task->p->loadmap->segs[i].addr = (size_t)map +
4911 				(ph->p_vaddr & PAGE_SIZE - 1);
4912 			task->p->loadmap->segs[i].p_vaddr = ph->p_vaddr;
4913 			task->p->loadmap->segs[i].p_memsz = ph->p_memsz;
4914 			i++;
4915 			if (prot & PROT_WRITE) {
4916 				size_t brk = (ph->p_vaddr & PAGE_SIZE - 1) + ph->p_filesz;
4917 				size_t pgbrk = (brk + PAGE_SIZE - 1) & -PAGE_SIZE;
4918 				size_t pgend = (brk + ph->p_memsz - ph->p_filesz + PAGE_SIZE - 1) & -PAGE_SIZE;
4919 				if (pgend > pgbrk && mmap_fixed(map + pgbrk,
4920 					pgend - pgbrk, prot,
4921 					MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,
4922 					-1, off_start) == MAP_FAILED)
4923 					LD_LOGE("Error mapping library: PROT_WRITE mmap_fixed failed errno=%{public}d", errno);
4924 					goto error;
4925 				memset(map + brk, 0, pgbrk - brk);
4926 			}
4927 		}
4928 		map = (void *)task->p->loadmap->segs[0].addr;
4929 		map_len = 0;
4930 		goto done_mapping;
4931 	}
4932 	addr_max += PAGE_SIZE - 1;
4933 	addr_max &= -PAGE_SIZE;
4934 	addr_min &= -PAGE_SIZE;
4935 	off_start &= -PAGE_SIZE;
4936 	map_len = addr_max - addr_min + off_start;
4937 	start_addr = addr_min;
4938 
4939 	hugepage_enabled = get_transparent_hugepages_supported();
4940 	if (hugepage_enabled) {
4941 		size_t maxinum_alignment = phdr_table_get_maxinum_alignment(task->ph0, task->eh->e_phnum);
4942 
4943 		start_alignment = maxinum_alignment == KPMD_SIZE ? KPMD_SIZE : PAGE_SIZE;
4944 	}
4945 
4946 	if (reserved_params) {
4947 		if (map_len > reserved_params->reserved_size) {
4948 			if (reserved_params->must_use_reserved) {
4949 				LD_LOGE("Error mapping library: map len is larger than reserved address task->name=%{public}s", task->name);
4950 				goto error;
4951 			}
4952 		} else {
4953 			start_addr = ((size_t)reserved_params->start_addr - 1 + PAGE_SIZE) & -PAGE_SIZE;
4954 			map_flags |= MAP_FIXED;
4955 		}
4956 	}
4957 
4958 	/* we will find a mapping_align aligned address as the start of dso
4959 	 * so we need a tmp_map_len as map_len + mapping_align to make sure
4960 	 * we have enough space to shift the dso to the correct location. */
4961 	size_t mapping_align = start_alignment > LIBRARY_ALIGNMENT ? start_alignment : LIBRARY_ALIGNMENT;
4962 	size_t tmp_map_len = ALIGN(map_len, mapping_align) + mapping_align - PAGE_SIZE;
4963 
4964 	/* map the whole load segments with PROT_READ first for security consideration. */
4965 	prot = PROT_READ;
4966 
4967 	/* if reserved_params exists, we should use start_addr as prefered result to do the mmap operation */
4968 	if (reserved_params) {
4969 		map = DL_NOMMU_SUPPORT
4970 			? mmap((void *)start_addr, map_len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)
4971 			: mmap((void *)start_addr, map_len, prot, map_flags, task->fd, off_start + task->file_offset);
4972 		if (map == MAP_FAILED) {
4973 			LD_LOGE("Error mapping library: reserved_params mmap failed errno=%{public}d DL_NOMMU_SUPPORT=%{public}d"
4974 				" task->fd=%{public}d task->name=%{public}s map_len=%{public}d",
4975 				errno, DL_NOMMU_SUPPORT, task->fd, task->name, map_len);
4976 			goto error;
4977 		}
4978 		if (reserved_params && map_len < reserved_params->reserved_size) {
4979 			reserved_params->reserved_size -= (map_len + (start_addr - (size_t)reserved_params->start_addr));
4980 			reserved_params->start_addr = (void *)((uint8_t *)map + map_len);
4981 		}
4982 	/* if reserved_params does not exist, we should use real_map as prefered result to do the mmap operation */
4983 	} else {
4984 		/* use tmp_map_len to mmap enough space for the dso with anonymous mapping */
4985 		unsigned char *temp_map = mmap((void *)NULL, tmp_map_len, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
4986 		if (temp_map == MAP_FAILED) {
4987 			LD_LOGE("Error mapping library: !reserved_params mmap failed errno=%{public}d tmp_map_len=%{public}d",
4988 				errno, tmp_map_len);
4989 			goto error;
4990 		}
4991 
4992 		/* find the mapping_align aligned address */
4993 		unsigned char *real_map = (unsigned char*)ALIGN((uintptr_t)temp_map, mapping_align);
4994 
4995 		/* mummap the space we mmap before so that we can mmap correct space again */
4996 		munmap(temp_map, tmp_map_len);
4997 
4998 		map = DL_NOMMU_SUPPORT
4999 			? mmap(real_map, map_len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)
5000 			/* use map_len to mmap correct space for the dso with file mapping */
5001 			: mmap(real_map, map_len, prot, map_flags, task->fd, off_start + task->file_offset);
5002 		if (map == MAP_FAILED) {
5003 			LD_LOGE("Error mapping library: !reserved_params mmap failed errno=%{public}d DL_NOMMU_SUPPORT=%{public}d"
5004 				"task->fd=%{public}d task->name=%{public}s map_len=%{public}d",
5005 				errno, DL_NOMMU_SUPPORT, task->fd, task->name, map_len);
5006 			goto error;
5007 		}
5008 	}
5009 	task->p->map = map;
5010 	task->p->map_len = map_len;
5011 	/* If the loaded file is not relocatable and the requested address is
5012 	 * not available, then the load operation must fail. */
5013 	if (task->eh->e_type != ET_DYN && addr_min && map != (void *)addr_min) {
5014 		LD_LOGE("Error mapping library: ET_DYN task->name=%{public}s", task->name);
5015 		errno = EBUSY;
5016 		goto error;
5017 	}
5018 	base = map - addr_min;
5019 	task->p->phdr = 0;
5020 	task->p->phnum = 0;
5021 	for (ph = task->ph0, i = task->eh->e_phnum; i; i--, ph = (void *)((char *)ph + task->eh->e_phentsize)) {
5022 		if (ph->p_type == PT_OHOS_RANDOMDATA) {
5023 			fill_random_data((void *)(ph->p_vaddr + base), ph->p_memsz);
5024 			continue;
5025 		}
5026 		if (ph->p_type != PT_LOAD) {
5027 			continue;
5028 		}
5029 		/* Check if the programs headers are in this load segment, and
5030 		 * if so, record the address for use by dl_iterate_phdr. */
5031 		if (!task->p->phdr && task->eh->e_phoff >= ph->p_offset
5032 			&& task->eh->e_phoff + task->phsize <= ph->p_offset + ph->p_filesz) {
5033 			task->p->phdr = (void *)(base + ph->p_vaddr + (task->eh->e_phoff - ph->p_offset));
5034 			task->p->phnum = task->eh->e_phnum;
5035 			task->p->phentsize = task->eh->e_phentsize;
5036 		}
5037 		this_min = ph->p_vaddr & -PAGE_SIZE;
5038 		this_max = ph->p_vaddr + ph->p_memsz + PAGE_SIZE - 1 & -PAGE_SIZE;
5039 		off_start = ph->p_offset & -PAGE_SIZE;
5040 		prot = (((ph->p_flags & PF_R) ? PROT_READ : 0) |
5041 			((ph->p_flags & PF_W) ? PROT_WRITE : 0) |
5042 			((ph->p_flags & PF_X) ? PROT_EXEC : 0));
5043 		/* Reuse the existing mapping for the lowest-address LOAD */
5044 		if (mmap_fixed(
5045 				base + this_min,
5046 				this_max - this_min,
5047 				prot, MAP_PRIVATE | MAP_FIXED,
5048 				task->fd,
5049 				off_start + task->file_offset) == MAP_FAILED) {
5050 			LD_LOGE("Error mapping library: mmap fix failed task->name=%{public}s errno=%{public}d", task->name, errno);
5051 			goto error;
5052 		}
5053 		if ((ph->p_flags & PF_X) && (ph->p_align == KPMD_SIZE) && hugepage_enabled)
5054 			madvise(base + this_min, this_max - this_min, MADV_HUGEPAGE);
5055 		if (ph->p_memsz > ph->p_filesz && (ph->p_flags & PF_W)) {
5056 			size_t brk = (size_t)base + ph->p_vaddr + ph->p_filesz;
5057 			size_t pgbrk = brk + PAGE_SIZE - 1 & -PAGE_SIZE;
5058 			size_t zeromap_size = (size_t)base + this_max - pgbrk;
5059 			memset((void *)brk, 0, pgbrk - brk & PAGE_SIZE - 1);
5060 			if (pgbrk - (size_t)base < this_max && mmap_fixed(
5061 				(void *)pgbrk,
5062 				zeromap_size,
5063 				prot,
5064 				MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,
5065 				-1,
5066 				0) == MAP_FAILED) {
5067 				LD_LOGE("Error mapping library: PF_W mmap fix failed errno=%{public}d task->name=%{public}s zeromap_size=%{public}d",
5068 					errno, task->name, zeromap_size);
5069 				goto error;
5070 			}
5071 			set_bss_vma_name(task->p->name, (void *)pgbrk, zeromap_size);
5072 		}
5073 	}
5074 	for (i = 0; ((size_t *)(base + task->dyn))[i]; i += NEXT_DYNAMIC_INDEX) {
5075 		if (((size_t *)(base + task->dyn))[i] == DT_TEXTREL) {
5076 			if (mprotect(map, map_len, PROT_READ | PROT_WRITE | PROT_EXEC) && errno != ENOSYS) {
5077 				LD_LOGE("Error mapping library: mprotect failed task->name=%{public}s errno=%{public}d", task->name, errno);
5078 				goto error;
5079 			}
5080 			break;
5081 		}
5082 	}
5083 done_mapping:
5084 	task->p->base = base;
5085 	task->p->dynv = laddr(task->p, task->dyn);
5086 	if (task->p->tls.size) {
5087 		task->p->tls.image = laddr(task->p, task->tls_image);
5088 	}
5089 	free(task->allocated_buf);
5090 	task->allocated_buf = NULL;
5091 	if (task->shdr_allocated_buf != MAP_FAILED) {
5092 		munmap(task->shdr_allocated_buf, task->shsize);
5093 		task->shdr_allocated_buf = MAP_FAILED;
5094 	}
5095 	return true;
5096 noexec:
5097 	errno = ENOEXEC;
5098 error:
5099 	if (map != MAP_FAILED) {
5100 		unmap_library(task->p);
5101 	}
5102 	free(task->allocated_buf);
5103 	task->allocated_buf = NULL;
5104 	if (task->shdr_allocated_buf != MAP_FAILED) {
5105 		munmap(task->shdr_allocated_buf, task->shsize);
5106 		task->shdr_allocated_buf = MAP_FAILED;
5107 	}
5108 	return false;
5109 }
5110 
resolve_fd_to_realpath(struct loadtask * task)5111 static bool resolve_fd_to_realpath(struct loadtask *task)
5112 {
5113 	char proc_self_fd[32];
5114 	static char resolved_path[PATH_MAX];
5115 
5116 	int ret = snprintf(proc_self_fd, sizeof(proc_self_fd), "/proc/self/fd/%d", task->fd);
5117 	if (ret < 0 || ret >= sizeof(proc_self_fd)) {
5118 		return false;
5119 	}
5120 	ssize_t len = readlink(proc_self_fd, resolved_path, sizeof(resolved_path) - 1);
5121 	if (len < 0) {
5122 		return false;
5123 	}
5124 	resolved_path[len] = '\0';
5125 	strncpy(task->buf, resolved_path, PATH_MAX);
5126 
5127 	return true;
5128 }
5129 
load_library_header(struct loadtask * task)5130 static bool load_library_header(struct loadtask *task)
5131 {
5132 	const char *name = task->name;
5133 	struct dso *needed_by = task->needed_by;
5134 	ns_t *namespace = task->namespace;
5135 	bool check_inherited = task->check_inherited;
5136 	struct zip_info z_info;
5137 
5138 	bool map = false;
5139 	struct stat st;
5140 	size_t alloc_size;
5141 	int n_th = 0;
5142 	int is_self = 0;
5143 
5144 	if (!*name) {
5145 		errno = EINVAL;
5146 		return false;
5147 	}
5148 
5149 	/* Catch and block attempts to reload the implementation itself */
5150 	if (name[NAME_INDEX_ZERO] == 'l' && name[NAME_INDEX_ONE] == 'i' && name[NAME_INDEX_TWO] == 'b') {
5151 		static const char reserved[] =
5152 			"c.pthread.rt.m.dl.util.xnet.";
5153 		const char *rp, *next;
5154 		for (rp = reserved; *rp; rp = next) {
5155 			next = strchr(rp, '.') + 1;
5156 			if (strncmp(name + NAME_INDEX_THREE, rp, next - rp) == 0) {
5157 				break;
5158 			}
5159 		}
5160 		if (*rp) {
5161 			if (ldd_mode) {
5162 				/* Track which names have been resolved
5163 				 * and only report each one once. */
5164 				static unsigned reported;
5165 				unsigned mask = 1U << (rp - reserved);
5166 				if (!(reported & mask)) {
5167 					reported |= mask;
5168 					dprintf(1, "\t%s => %s (%p)\n",
5169 						name, ldso.name,
5170 						ldso.base);
5171 				}
5172 			}
5173 			is_self = 1;
5174 		}
5175 	}
5176 	if (!strcmp(name, ldso.name)) {
5177 		is_self = 1;
5178 	}
5179 	if (is_self) {
5180 		if (!ldso.prev) {
5181 			tail->next = &ldso;
5182 			ldso.prev = tail;
5183 			tail = &ldso;
5184 			ldso.namespace = namespace;
5185 			ns_add_dso(namespace, &ldso);
5186 		}
5187 		task->isloaded = true;
5188 		task->p = &ldso;
5189 		return true;
5190 	}
5191 	if (strchr(name, '/')) {
5192 		char *separator = strstr(name, ZIP_FILE_PATH_SEPARATOR);
5193 		if (separator != NULL) {
5194 			int res = open_uncompressed_library_in_zipfile(name, &z_info, separator);
5195 			if (!res) {
5196 				task->pathname = name;
5197 				if (!is_accessible(namespace, task->pathname, g_is_asan, check_inherited)) {
5198 					LD_LOGE("Open uncompressed library: check ns accessible failed, pathname %{public}s namespace %{public}s.",
5199 							task->pathname, namespace ? namespace->ns_name : "NULL");
5200 					task->fd = -1;
5201 				} else {
5202 					task->fd = z_info.fd;
5203 					task->file_offset = z_info.file_offset;
5204 				}
5205 			} else {
5206 				LD_LOGE("Open uncompressed library in zip file failed, name:%{public}s res:%{public}d", name, res);
5207 				return false;
5208 			}
5209 		} else {
5210 			task->pathname = name;
5211 			if (!is_accessible(namespace, task->pathname, g_is_asan, check_inherited)) {
5212 				LD_LOGE("Open absolute_path library: check ns accessible failed, pathname %{public}s namespace %{public}s.",
5213 						task->pathname, namespace ? namespace->ns_name : "NULL");
5214 				task->fd = -1;
5215 			} else {
5216 				task->fd = open(name, O_RDONLY | O_CLOEXEC);
5217 			}
5218 		}
5219 	} else {
5220 		/* Search for the name to see if it's already loaded */
5221 		/* Search in namespace */
5222 		task->p = find_library_by_name(name, namespace, check_inherited);
5223 		if (task->p) {
5224 			task->isloaded = true;
5225 			LD_LOGD("find_library_by_name(name=%{public}s ns=%{public}s) already loaded by %{public}s in %{public}s namespace  ",
5226 					name, namespace->ns_name, task->p->name, task->p->namespace->ns_name);
5227 			return true;
5228 		}
5229 		if (strlen(name) > NAME_MAX) {
5230 			LD_LOGE("load_library name length is larger than NAME_MAX:%{public}s.", name);
5231 			return false;
5232 		}
5233 		task->fd = -1;
5234 		if (namespace->env_paths) {
5235 			open_library_by_path(name, namespace->env_paths, task, &z_info);
5236 		}
5237 		for (task->p = needed_by; task->fd == -1 && task->p; task->p = task->p->needed_by) {
5238 			if (fixup_rpath(task->p, task->buf, sizeof task->buf) < 0) {
5239 				task->fd = INVALID_FD_INHIBIT_FURTHER_SEARCH; /* Inhibit further search. */
5240 			}
5241 			if (task->p->rpath) {
5242 				open_library_by_path(name, task->p->rpath, task, &z_info);
5243 				if (task->fd != -1 && resolve_fd_to_realpath(task)) {
5244 					if (!is_accessible(namespace, task->buf, g_is_asan, check_inherited)) {
5245 						LD_LOGE("Open library: check ns accessible failed, name %{public}s namespace %{public}s.",
5246 								name, namespace ? namespace->ns_name : "NULL");
5247 						close(task->fd);
5248 						task->fd = -1;
5249 					}
5250 				}
5251 			}
5252 		}
5253 		if (g_is_asan) {
5254 			handle_asan_path_open_by_task(task->fd, name, namespace, task, &z_info);
5255 			LD_LOGD("load_library handle_asan_path_open_by_task fd:%{public}d.", task->fd);
5256 		} else {
5257 			if (task->fd == -1 && namespace->lib_paths) {
5258 				open_library_by_path(name, namespace->lib_paths, task, &z_info);
5259 				LD_LOGD("load_library no asan lib_paths path_open fd:%{public}d.", task->fd);
5260 			}
5261 		}
5262 		task->pathname = task->buf;
5263 	}
5264 	if (task->fd < 0) {
5265 		if (!check_inherited || !namespace->ns_inherits) {
5266 			LD_LOGE("Error loading header %{public}s, namespace %{public}s has no inherits, errno=%{public}d",
5267 				task->name, namespace->ns_name, errno);
5268 			return false;
5269 		}
5270 		/* Load lib in inherited namespace. Do not check inherited again.*/
5271 		for (size_t i = 0; i < namespace->ns_inherits->num; i++) {
5272 			ns_inherit *inherit = namespace->ns_inherits->inherits[i];
5273 			if (strchr(name, '/') == 0 && !is_sharable(inherit, name)) {
5274 				continue;
5275 			}
5276 			task->namespace = inherit->inherited_ns;
5277 			task->check_inherited = false;
5278 			if (load_library_header(task)) {
5279 				return true;
5280 			}
5281 		}
5282 		LD_LOGE("Error loading header: can't find library %{public}s in namespace: %{public}s",
5283 			task->name, namespace->ns_name);
5284 		return false;
5285 	}
5286 
5287 	if (fstat(task->fd, &st) < 0) {
5288 		LD_LOGE("Error loading header %{public}s: failed to get file state errno=%{public}d", task->name, errno);
5289 		close(task->fd);
5290 		task->fd = -1;
5291 		return false;
5292 	}
5293 	/* Search in namespace */
5294 	task->p = find_library_by_fstat(&st, namespace, check_inherited, task->file_offset);
5295 	if (task->p) {
5296 		/* If this library was previously loaded with a
5297 		* pathname but a search found the same inode,
5298 		* setup its shortname so it can be found by name. */
5299 		if (!task->p->shortname && task->pathname != name) {
5300 			task->p->shortname = strrchr(task->p->name, '/') + 1;
5301 		}
5302 		close(task->fd);
5303 		task->fd = -1;
5304 		task->isloaded = true;
5305 		LD_LOGD("find_library_by_fstat(name=%{public}s ns=%{public}s) already loaded by %{public}s in %{public}s namespace  ",
5306 				name, namespace->ns_name, task->p->name, task->p->namespace->ns_name);
5307 		return true;
5308 	}
5309 
5310 	map = noload ? 0 : map_library_header(task);
5311 	if (!map) {
5312 		LD_LOGE("Error loading header %{public}s: failed to map header", task->name);
5313 		close(task->fd);
5314 		task->fd = -1;
5315 		return false;
5316 	}
5317 
5318 	/* Allocate storage for the new DSO. When there is TLS, this
5319 	 * storage must include a reservation for all pre-existing
5320 	 * threads to obtain copies of both the new TLS, and an
5321 	 * extended DTV capable of storing an additional slot for
5322 	 * the newly-loaded DSO. */
5323 	alloc_size = sizeof(struct dso) + strlen(task->pathname) + 1;
5324 	if (runtime && task->tls.size) {
5325 		size_t per_th = task->tls.size + task->tls.align + sizeof(void *) * (tls_cnt + TLS_CNT_INCREASE);
5326 		n_th = libc.threads_minus_1 + 1;
5327 		if (n_th > SSIZE_MAX / per_th) {
5328 			alloc_size = SIZE_MAX;
5329 		} else {
5330 			alloc_size += n_th * per_th;
5331 		}
5332 	}
5333 	task->p = calloc(1, alloc_size);
5334 	if (!task->p) {
5335 		LD_LOGE("Error loading header %{public}s: failed to allocate dso", task->name);
5336 		close(task->fd);
5337 		task->fd = -1;
5338 		return false;
5339 	}
5340 	task->p->dev = st.st_dev;
5341 	task->p->ino = st.st_ino;
5342 	task->p->file_offset = task->file_offset;
5343 	task->p->needed_by = needed_by;
5344 	task->p->name = task->p->buf;
5345 	strcpy(task->p->name, task->pathname);
5346 	task->p->tls = task->tls;
5347 	task->p->dynv = task->dyn_addr;
5348 	task->p->strings = task->str_addr;
5349 	size_t rpath_offset;
5350 	size_t runpath_offset;
5351 	if (search_vec(task->p->dynv, &rpath_offset, DT_RPATH))
5352 		task->p->rpath_orig = task->p->strings + rpath_offset;
5353 	if (search_vec(task->p->dynv, &runpath_offset, DT_RUNPATH))
5354 		task->p->rpath_orig = task->p->strings + runpath_offset;
5355 
5356 	/* Add a shortname only if name arg was not an explicit pathname. */
5357 	if (task->pathname != name) {
5358 		task->p->shortname = strrchr(task->p->name, '/') + 1;
5359 	}
5360 
5361 	if (task->p->tls.size) {
5362 		task->p->tls_id = ++tls_cnt;
5363 		task->p->new_dtv = (void *)(-sizeof(size_t) &
5364 			(uintptr_t)(task->p->name + strlen(task->p->name) + sizeof(size_t)));
5365 		task->p->new_tls = (void *)(task->p->new_dtv + n_th * (tls_cnt + 1));
5366 	}
5367 
5368 	tail->next = task->p;
5369 	task->p->prev = tail;
5370 	tail = task->p;
5371 
5372 	/* Add dso to namespace */
5373 	task->p->namespace = namespace;
5374 	ns_add_dso(namespace, task->p);
5375 	return true;
5376 }
5377 
task_load_library(struct loadtask * task,struct reserved_address_params * reserved_params)5378 static void task_load_library(struct loadtask *task, struct reserved_address_params *reserved_params)
5379 {
5380 	LD_LOGD("load_library loading ns=%{public}s name=%{public}s by_dlopen=%{public}d", task->namespace->ns_name, task->p->name, runtime);
5381 	bool map = noload ? 0 : task_map_library(task, reserved_params);
5382 	__close(task->fd);
5383 	task->fd = -1;
5384 	if (!map) {
5385 		LD_LOGE("Error loading library %{public}s: failed to map library noload=%{public}d errno=%{public}d",
5386 			task->name, noload, errno);
5387 		error("Error loading library %s: failed to map library noload=%d errno=%d", task->name, noload, errno);
5388 		if (runtime) {
5389 			longjmp(*rtld_fail, 1);
5390 		}
5391 		return;
5392 	};
5393 
5394 	/* Avoid the danger of getting two versions of libc mapped into the
5395 	 * same process when an absolute pathname was used. The symbols
5396 	 * checked are chosen to catch both musl and glibc, and to avoid
5397 	 * false positives from interposition-hack libraries. */
5398 	decode_dyn(task->p);
5399 	if (find_sym(task->p, "__libc_start_main", 1).sym &&
5400 		find_sym(task->p, "stdin", 1).sym) {
5401 		do_dlclose(task->p);
5402 		task->p = NULL;
5403 		free((void*)task->name);
5404 		task->name = ld_strdup("libc.so");
5405 		task->check_inherited = true;
5406 		if (!load_library_header(task)) {
5407 			LD_LOGE("Error loading library %{public}s: failed to load libc.so", task->name);
5408 			error("Error loading library %s: failed to load libc.so", task->name);
5409 			if (runtime) {
5410 				longjmp(*rtld_fail, 1);
5411 			}
5412 		}
5413 		return;
5414 	}
5415 	/* Past this point, if we haven't reached runtime yet, ldso has
5416 	 * committed either to use the mapped library or to abort execution.
5417 	 * Unmapping is not possible, so we can safely reclaim gaps. */
5418 	if (!runtime) {
5419 		reclaim_gaps(task->p);
5420 	}
5421 	task->p->runtime_loaded = runtime;
5422 	if (runtime)
5423 		task->p->by_dlopen = 1;
5424 
5425 	if (DL_FDPIC) {
5426 		makefuncdescs(task->p);
5427 	}
5428 
5429 	if (ldd_mode) {
5430 		dprintf(1, "\t%s => %s (%p)\n", task->name, task->pathname, task->p->base);
5431 	}
5432 
5433 #ifdef ENABLE_HWASAN
5434 	if (libc.load_hook) {
5435 		libc.load_hook((long unsigned int)task->p->base, task->p->phdr, task->p->phnum);
5436 	}
5437 #endif
5438 }
5439 
preload_direct_deps(struct dso * p,ns_t * namespace,struct loadtasks * tasks)5440 static void preload_direct_deps(struct dso *p, ns_t *namespace, struct loadtasks *tasks)
5441 {
5442 	size_t i, cnt = 0;
5443 	if (p->deps) {
5444 		return;
5445 	}
5446 	/* For head, all preloads are direct pseudo-dependencies.
5447 	 * Count and include them now to avoid realloc later. */
5448 	if (p == head) {
5449 		for (struct dso *q = p->next; q; q = q->next) {
5450 			cnt++;
5451 		}
5452 	}
5453 	for (i = 0; p->dynv[i]; i += NEXT_DYNAMIC_INDEX) {
5454 		if (p->dynv[i] == DT_NEEDED) {
5455 			cnt++;
5456 		}
5457 	}
5458 	/* Use builtin buffer for apps with no external deps, to
5459 	 * preserve property of no runtime failure paths. */
5460 	p->deps = (p == head && cnt < MIN_DEPS_COUNT) ? builtin_deps :
5461 		calloc(cnt + 1, sizeof *p->deps);
5462 	if (!p->deps) {
5463 		LD_LOGE("Error loading dependencies for %{public}s", p->name);
5464 		error("Error loading dependencies for %s", p->name);
5465 		if (runtime) {
5466 			longjmp(*rtld_fail, 1);
5467 		}
5468 	}
5469 	cnt = 0;
5470 	if (p == head) {
5471 		for (struct dso *q = p->next; q; q = q->next) {
5472 			p->deps[cnt++] = q;
5473 		}
5474 	}
5475 	for (i = 0; p->dynv[i]; i += NEXT_DYNAMIC_INDEX) {
5476 		if (p->dynv[i] != DT_NEEDED) {
5477 			continue;
5478 		}
5479 		const char* dtneed_name = p->strings + p->dynv[i + 1];
5480 		LD_LOGD("load_library %{public}s adding DT_NEEDED task %{public}s namespace(%{public}s)", p->name, dtneed_name, namespace->ns_name);
5481 		struct loadtask *task = create_loadtask(dtneed_name, p, namespace, true);
5482 		if (!task) {
5483 			LD_LOGE("Error loading dependencies %{public}s : create load task failed", p->name);
5484 			error("Error loading dependencies for %s : create load task failed", p->name);
5485 			if (runtime) {
5486 				longjmp(*rtld_fail, 1);
5487 			}
5488 			continue;
5489 		}
5490 		LD_LOGD("loading shared library %{public}s: (needed by %{public}s)", p->strings + p->dynv[i+1], p->name);
5491 		if (!load_library_header(task)) {
5492 			free_task(task);
5493 			task = NULL;
5494 			LD_LOGE("Error loading shared library %{public}s: (needed by %{public}s)",
5495 				p->strings + p->dynv[i + 1],
5496 				p->name);
5497 			error("Error loading shared library %s: %m (needed by %s)",
5498 				p->strings + p->dynv[i + 1], p->name);
5499 			if (runtime) {
5500 				longjmp(*rtld_fail, 1);
5501 			}
5502 			continue;
5503 		}
5504 		p->deps[cnt++] = task->p;
5505 		if (task->isloaded) {
5506 			free_task(task);
5507 			task = NULL;
5508 		} else {
5509 			append_loadtasks(tasks, task);
5510 		}
5511 	}
5512 	p->deps[cnt] = 0;
5513 	p->ndeps_direct = cnt;
5514 	for (i = 0; i < p->ndeps_direct; i++) {
5515 		add_dso_parent(p->deps[i], p);
5516 	}
5517 }
5518 
unmap_preloaded_sections(struct loadtasks * tasks)5519 static void unmap_preloaded_sections(struct loadtasks *tasks)
5520 {
5521 	struct loadtask *task = NULL;
5522 	for (size_t i = 0; i < tasks->length; i++) {
5523 		task = get_loadtask(tasks, i);
5524 		if (!task) {
5525 			continue;
5526 		}
5527 		if (task->dyn_map_len) {
5528 			munmap(task->dyn_map, task->dyn_map_len);
5529 			task->dyn_map = NULL;
5530 			task->dyn_map_len = 0;
5531 			if (task->p) {
5532 				task->p->dynv = NULL;
5533 			}
5534 		}
5535 		if (task->str_map_len) {
5536 			munmap(task->str_map, task->str_map_len);
5537 			task->str_map = NULL;
5538 			task->str_map_len = 0;
5539 			if (task->p) {
5540 				task->p->strings = NULL;
5541 			}
5542 		}
5543 	}
5544 }
5545 
preload_deps(struct dso * p,struct loadtasks * tasks)5546 static void preload_deps(struct dso *p, struct loadtasks *tasks)
5547 {
5548 	if (p->deps) {
5549 		return;
5550 	}
5551 	for (; p; p = p->next) {
5552 		preload_direct_deps(p, p->namespace, tasks);
5553 	}
5554 }
5555 
run_loadtasks(struct loadtasks * tasks,struct reserved_address_params * reserved_params)5556 static void run_loadtasks(struct loadtasks *tasks, struct reserved_address_params *reserved_params)
5557 {
5558 	struct loadtask *task = NULL;
5559 	bool reserved_address = false;
5560 	for (size_t i = 0; i < tasks->length; i++) {
5561 		task = get_loadtask(tasks, i);
5562 		if (task) {
5563 			if (reserved_params) {
5564 				reserved_address = reserved_params->reserved_address_recursive || (reserved_params->target == task->p);
5565 			}
5566 			task_load_library(task, reserved_address ? reserved_params : NULL);
5567 		}
5568 	}
5569 }
5570 
assign_tls(struct dso * p)5571 UT_STATIC void assign_tls(struct dso *p)
5572 {
5573 	while (p) {
5574 		if (p->tls.image) {
5575 			tls_align = MAXP2(tls_align, p->tls.align);
5576 #ifdef TLS_ABOVE_TP
5577 			p->tls.offset = tls_offset + ((p->tls.align - 1) &
5578 				(-tls_offset + (uintptr_t)p->tls.image));
5579 			tls_offset = p->tls.offset + p->tls.size;
5580 #else
5581 			tls_offset += p->tls.size + p->tls.align - 1;
5582 			tls_offset -= (tls_offset + (uintptr_t)p->tls.image)
5583 				& (p->tls.align - 1);
5584 			p->tls.offset = tls_offset;
5585 #endif
5586 			if (tls_tail) {
5587 				tls_tail->next = &p->tls;
5588 			} else {
5589 				libc.tls_head = &p->tls;
5590 			}
5591 			tls_tail = &p->tls;
5592 		}
5593 
5594 		p = p->next;
5595 	}
5596 }
5597 
load_preload(char * s,ns_t * ns,struct loadtasks * tasks)5598 UT_STATIC void load_preload(char *s, ns_t *ns, struct loadtasks *tasks)
5599 {
5600 	int tmp;
5601 	char *z;
5602 
5603 	struct loadtask *task = NULL;
5604 	for (z = s; *z; s = z) {
5605 		for (; *s && (isspace(*s) || *s == ':'); s++) {
5606 			;
5607 		}
5608 		for (z = s; *z && !isspace(*z) && *z != ':'; z++) {
5609 			;
5610 		}
5611 		tmp = *z;
5612 		*z = 0;
5613 		task = create_loadtask(s, NULL, ns, true);
5614 		if (!task) {
5615 			continue;
5616 		}
5617 		if (load_library_header(task)) {
5618 			if (!task->isloaded) {
5619 				append_loadtasks(tasks, task);
5620 				task = NULL;
5621 			}
5622 		}
5623 		if (task) {
5624 			free_task(task);
5625 		}
5626 		*z = tmp;
5627 	}
5628 }
5629 #endif
5630 
serialize_gnu_relro(int fd,struct dso * dso,ssize_t * file_offset)5631 static int serialize_gnu_relro(int fd, struct dso *dso, ssize_t *file_offset)
5632 {
5633 	ssize_t count = dso->relro_end - dso->relro_start;
5634 	ssize_t offset = 0;
5635 	while (count > 0) {
5636 		ssize_t write_size = TEMP_FAILURE_RETRY(write(fd, laddr(dso, dso->relro_start + offset), count));
5637 		if (-1 == write_size) {
5638 			LD_LOGE("Error serializing relro %{public}s: failed to write GNU_RELRO", dso->name);
5639 			return -1;
5640 		}
5641 		offset += write_size;
5642 		count -= write_size;
5643 	}
5644 
5645 	ssize_t size = dso->relro_end - dso->relro_start;
5646 	void *map = mmap(
5647 		laddr(dso, dso->relro_start),
5648 		size,
5649 		PROT_READ,
5650 		MAP_PRIVATE | MAP_FIXED,
5651 		fd,
5652 		*file_offset);
5653 	if (map == MAP_FAILED) {
5654 		LD_LOGE("Error serializing relro %{public}s: failed to map GNU_RELRO", dso->name);
5655 		return -1;
5656 	}
5657 	*file_offset += size;
5658 	return 0;
5659 }
5660 
map_gnu_relro(int fd,struct dso * dso,ssize_t * file_offset)5661 static int map_gnu_relro(int fd, struct dso *dso, ssize_t *file_offset)
5662 {
5663 	ssize_t ext_fd_file_size = 0;
5664 	struct stat ext_fd_file_stat;
5665 	if (TEMP_FAILURE_RETRY(fstat(fd, &ext_fd_file_stat)) != 0) {
5666 		LD_LOGE("Error mapping relro %{public}s: failed to get file state", dso->name);
5667 		return -1;
5668 	}
5669 	ext_fd_file_size = ext_fd_file_stat.st_size;
5670 
5671 	void *ext_temp_map = MAP_FAILED;
5672 	ext_temp_map = mmap(NULL, ext_fd_file_size, PROT_READ, MAP_PRIVATE, fd, 0);
5673 	if (ext_temp_map == MAP_FAILED) {
5674 		LD_LOGE("Error mapping relro %{public}s: failed to map fd", dso->name);
5675 		return -1;
5676 	}
5677 
5678 	char *file_base = (char *)(ext_temp_map) + *file_offset;
5679 	char *mem_base = (char *)(laddr(dso, dso->relro_start));
5680 	ssize_t start_offset = 0;
5681 	ssize_t size = dso->relro_end - dso->relro_start;
5682 
5683 	if (size > ext_fd_file_size - *file_offset) {
5684 		LD_LOGE("Error mapping relro %{public}s: invalid file size", dso->name);
5685 		return -1;
5686 	}
5687 	while (start_offset < size) {
5688 		// Find start location.
5689 		while (start_offset < size) {
5690 			if (memcmp(mem_base + start_offset, file_base + start_offset, PAGE_SIZE) == 0) {
5691 				break;
5692 			}
5693 			start_offset += PAGE_SIZE;
5694 		}
5695 
5696 		// Find end location.
5697 		ssize_t end_offset = start_offset;
5698 		while (end_offset < size) {
5699 			if (memcmp(mem_base + end_offset, file_base + end_offset, PAGE_SIZE) != 0) {
5700 				break;
5701 			}
5702 			end_offset += PAGE_SIZE;
5703 		}
5704 
5705 		// Map pages.
5706 		ssize_t map_length = end_offset - start_offset;
5707 		ssize_t map_offset = *file_offset + start_offset;
5708 		if (map_length > 0) {
5709 			void *map = mmap(
5710 				mem_base + start_offset, map_length, PROT_READ, MAP_PRIVATE | MAP_FIXED, fd, map_offset);
5711 			if (map == MAP_FAILED) {
5712 				LD_LOGE("Error mapping relro %{public}s: failed to map GNU_RELRO", dso->name);
5713 				munmap(ext_temp_map, ext_fd_file_size);
5714 				return -1;
5715 			}
5716 		}
5717 
5718 		start_offset = end_offset;
5719 	}
5720 	*file_offset += size;
5721 	munmap(ext_temp_map, ext_fd_file_size);
5722 	return 0;
5723 }
5724 
handle_relro_sharing(struct dso * p,const dl_extinfo * extinfo,ssize_t * relro_fd_offset)5725 static void handle_relro_sharing(struct dso *p, const dl_extinfo *extinfo, ssize_t *relro_fd_offset)
5726 {
5727 	if (extinfo == NULL) {
5728 		return;
5729 	}
5730 	if (extinfo->flag & DL_EXT_WRITE_RELRO) {
5731 		LD_LOGD("Serializing GNU_RELRO %{public}s", p->name);
5732 		if (serialize_gnu_relro(extinfo->relro_fd, p, relro_fd_offset) < 0) {
5733 			LD_LOGE("Error serializing GNU_RELRO %{public}s", p->name);
5734 			error("Error serializing GNU_RELRO");
5735 			if (runtime) longjmp(*rtld_fail, 1);
5736 		}
5737 	} else if (extinfo->flag & DL_EXT_USE_RELRO) {
5738 		LD_LOGD("Mapping GNU_RELRO %{public}s", p->name);
5739 		if (map_gnu_relro(extinfo->relro_fd, p, relro_fd_offset) < 0) {
5740 			LD_LOGE("Error mapping GNU_RELRO %{public}s", p->name);
5741 			error("Error mapping GNU_RELRO");
5742 			if (runtime) longjmp(*rtld_fail, 1);
5743 		}
5744 	}
5745 }
5746 
set_bss_vma_name(char * path_name,void * addr,size_t zeromap_size)5747 static void set_bss_vma_name(char *path_name, void *addr, size_t zeromap_size)
5748 {
5749 	char so_bss_name[ANON_NAME_MAX_LEN];
5750 	if (path_name == NULL) {
5751 		snprintf(so_bss_name, ANON_NAME_MAX_LEN, ".bss");
5752 	} else {
5753 		char *t = strrchr(path_name, '/');
5754 		if (t) {
5755 			snprintf(so_bss_name, ANON_NAME_MAX_LEN, "%s.bss", ++t);
5756 		} else {
5757 			snprintf(so_bss_name, ANON_NAME_MAX_LEN, "%s.bss", path_name);
5758 		}
5759 	}
5760 
5761 	prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, addr, zeromap_size, so_bss_name);
5762 }
5763 
find_and_set_bss_name(struct dso * p)5764 static void find_and_set_bss_name(struct dso *p)
5765 {
5766 	size_t  cnt;
5767 	Phdr *ph = p->phdr;
5768 	for (cnt = p->phnum; cnt--; ph = (void *)((char *)ph + p->phentsize)) {
5769 		if (ph->p_type != PT_LOAD) continue;
5770 		size_t seg_start = p->base + ph->p_vaddr;
5771 		size_t seg_file_end = seg_start + ph->p_filesz + PAGE_SIZE - 1 & -PAGE_SIZE;
5772 		size_t seg_max_addr = seg_start + ph->p_memsz + PAGE_SIZE - 1 & -PAGE_SIZE;
5773 		size_t zeromap_size = seg_max_addr - seg_file_end;
5774 		if (zeromap_size > 0 && (ph->p_flags & PF_W)) {
5775 			set_bss_vma_name(p->name, (void *)seg_file_end, zeromap_size);
5776 		}
5777 	}
5778 }
5779 
sync_with_debugger(void)5780 static void sync_with_debugger(void)
5781 {
5782 	debug.ver = 1;
5783 	debug.bp = dl_debug_state;
5784 	debug.head = NULL;
5785 	debug.base = ldso.base;
5786 
5787 	add_dso_info_to_debug_map(head);
5788 
5789 	debug.state = RT_CONSISTENT;
5790 	_dl_debug_state();
5791 }
5792 
notify_addition_to_debugger(struct dso * p)5793 static void notify_addition_to_debugger(struct dso *p)
5794 {
5795 	debug.state = RT_ADD;
5796 	_dl_debug_state();
5797 
5798 	add_dso_info_to_debug_map(p);
5799 
5800 	debug.state = RT_CONSISTENT;
5801 	_dl_debug_state();
5802 }
5803 
notify_remove_to_debugger(struct dso * p)5804 static void notify_remove_to_debugger(struct dso *p)
5805 {
5806 	debug.state = RT_DELETE;
5807 	_dl_debug_state();
5808 
5809 	remove_dso_info_from_debug_map(p);
5810 
5811 	debug.state = RT_CONSISTENT;
5812 	_dl_debug_state();
5813 }
5814 
add_dso_info_to_debug_map(struct dso * p)5815 static void add_dso_info_to_debug_map(struct dso *p)
5816 {
5817 	for (struct dso *so = p; so != NULL; so = so->next) {
5818 		struct dso_debug_info *debug_info = malloc(sizeof(struct dso_debug_info));
5819 		if (debug_info == NULL) {
5820 			LD_LOGE("malloc error! dso name: %{public}s.", so->name);
5821 			continue;
5822 		}
5823 #if DL_FDPIC
5824 		debug_info->loadmap = so->loadmap;
5825 #else
5826 		debug_info->base = so->base;
5827 #endif
5828 		debug_info->name = so->name;
5829 		debug_info->dynv = so->dynv;
5830 		if (debug.head == NULL) {
5831 			debug_info->prev = NULL;
5832 			debug_info->next = NULL;
5833 			debug.head = debug_tail = debug_info;
5834 		} else {
5835 			debug_info->prev = debug_tail;
5836 			debug_info->next = NULL;
5837 			debug_tail->next = debug_info;
5838 			debug_tail = debug_info;
5839 		}
5840 		so->debug_info = debug_info;
5841 	}
5842 }
5843 
remove_dso_info_from_debug_map(struct dso * p)5844 static void remove_dso_info_from_debug_map(struct dso *p)
5845 {
5846 	struct dso_debug_info *debug_info = p->debug_info;
5847 	if (debug_info == debug_tail) {
5848 		debug_tail = debug_tail->prev;
5849 		debug_tail->next = NULL;
5850 	} else {
5851 		debug_info->next->prev = debug_info->prev;
5852 		debug_info->prev->next = debug_info->next;
5853 	}
5854 	free(debug_info);
5855 }
5856