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