X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=src%2Fldso%2Fdynlink.c;h=7a26e9ed7ba21c6645860ac747138e999d39d2e9;hb=8aeee8db21858becb45a8e9f6b5bc23109638bcb;hp=33937e7627e460328979a1ff809af94e2e0f3b98;hpb=2fdea17c3da17f6ae96601283b28d025ed4d4cee;p=musl diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index 33937e76..7a26e9ed 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -92,10 +92,12 @@ static Sym *lookup(const char *s, uint32_t h, Sym *syms, uint32_t *hashtab, char } #define OK_TYPES (1<next) { @@ -103,10 +105,14 @@ static void *find_sym(struct dso *dso, const char *s, int need_def) if (!dso->global) continue; sym = lookup(s, h, dso->syms, dso->hashtab, dso->strings); if (sym && (!need_def || sym->st_shndx) && sym->st_value - && (1<<(sym->st_info&0xf) & OK_TYPES)) - return dso->base + sym->st_value; + && (1<<(sym->st_info&0xf) & OK_TYPES) + && (1<<(sym->st_info>>4) & OK_BINDS)) { + if (def && sym->st_info>>4 == STB_WEAK) continue; + def = dso->base + sym->st_value; + if (sym->st_info>>4 == STB_GLOBAL) break; + } } - return 0; + return def; } static void do_relocs(unsigned char *base, size_t *rel, size_t rel_size, size_t stride, Sym *syms, char *strings, struct dso *dso) @@ -298,7 +304,7 @@ static struct dso *load_library(const char *name) if (!libc->prev) { tail->next = libc; libc->prev = tail; - tail = libc; + tail = libc->next ? libc->next : libc; } return libc; } @@ -440,10 +446,15 @@ void *__dynlink(int argc, char **argv, size_t *got) size_t *auxv, aux[AUX_CNT] = {0}; size_t app_dyn[DYN_CNT] = {0}; size_t lib_dyn[DYN_CNT] = {0}; + size_t vdso_dyn[DYN_CNT] = {0}; size_t i; Phdr *phdr; Ehdr *ehdr; - struct dso lib, app; + static struct dso builtin_dsos[3]; + struct dso *const app = builtin_dsos+0; + struct dso *const lib = builtin_dsos+1; + struct dso *const vdso = builtin_dsos+2; + size_t vdso_base=0; /* Find aux vector just past environ[] */ for (i=argc+1; argv[i]; i++) @@ -453,6 +464,13 @@ void *__dynlink(int argc, char **argv, size_t *got) decode_vec(auxv, aux, AUX_CNT); + for (i=0; auxv[i]; i+=2) { + if (auxv[i]==AT_SYSINFO_EHDR) { + vdso_base = auxv[i+1]; + break; + } + } + /* Only trust user/env if kernel says we're not suid/sgid */ if ((aux[0]&0x7800)!=0x7800 || aux[AT_UID]!=aux[AT_EUID] || aux[AT_GID]!=aux[AT_EGID]) { @@ -471,7 +489,7 @@ void *__dynlink(int argc, char **argv, size_t *got) } } - app = (struct dso){ + *app = (struct dso){ .base = 0, .strings = (void *)(app_dyn[DT_STRTAB]), .hashtab = (void *)(app_dyn[DT_HASH]), @@ -479,10 +497,10 @@ void *__dynlink(int argc, char **argv, size_t *got) .dynv = (void *)(phdr->p_vaddr), .name = argv[0], .global = 1, - .next = &lib + .next = lib }; - lib = (struct dso){ + *lib = (struct dso){ .base = (void *)aux[AT_BASE], .strings = (void *)(aux[AT_BASE]+lib_dyn[DT_STRTAB]), .hashtab = (void *)(aux[AT_BASE]+lib_dyn[DT_HASH]), @@ -493,41 +511,53 @@ void *__dynlink(int argc, char **argv, size_t *got) .relocated = 1 }; + if (vdso_base) { + ehdr = (void *)vdso_base; + phdr = (void *)(vdso_base + ehdr->e_phoff); + for (i=ehdr->e_phnum; i; i--, phdr=(void *)((char *)phdr + ehdr->e_phentsize)) { + if (phdr->p_type == PT_DYNAMIC) + vdso->dynv = (void *)(vdso_base + phdr->p_offset); + if (phdr->p_type == PT_LOAD) + vdso->base = (void *)(vdso_base - phdr->p_vaddr + phdr->p_offset); + } + decode_vec(vdso->dynv, vdso_dyn, DYN_CNT); + vdso->syms = (void *)(vdso->base + vdso_dyn[DT_SYMTAB]); + vdso->hashtab = (void *)(vdso->base + vdso_dyn[DT_HASH]); + vdso->strings = (void *)(vdso->base + vdso_dyn[DT_STRTAB]); + vdso->name = "linux-gate.so.1"; + vdso->global = 1; + + vdso->prev = lib; + lib->next = vdso; + } + /* Relocate the dynamic linker/libc */ do_relocs((void *)aux[AT_BASE], (void *)(aux[AT_BASE]+lib_dyn[DT_REL]), - lib_dyn[DT_RELSZ], 2, lib.syms, lib.strings, &app); + lib_dyn[DT_RELSZ], 2, lib->syms, lib->strings, app); do_relocs((void *)aux[AT_BASE], (void *)(aux[AT_BASE]+lib_dyn[DT_RELA]), - lib_dyn[DT_RELASZ], 3, lib.syms, lib.strings, &app); + lib_dyn[DT_RELASZ], 3, lib->syms, lib->strings, app); /* At this point the standard library is fully functional */ - reclaim_gaps(app.base, (void *)aux[AT_PHDR], aux[AT_PHENT], aux[AT_PHNUM]); - ehdr = (void *)lib.base; - reclaim_gaps(lib.base, (void *)(lib.base+ehdr->e_phoff), + reclaim_gaps(app->base, (void *)aux[AT_PHDR], aux[AT_PHENT], aux[AT_PHNUM]); + ehdr = (void *)lib->base; + reclaim_gaps(lib->base, (void *)(lib->base+ehdr->e_phoff), ehdr->e_phentsize, ehdr->e_phnum); - head = tail = &app; - libc = &lib; - app.next = 0; + head = tail = app; + libc = lib; + app->next = 0; load_deps(head); make_global(head); reloc_all(head->next); reloc_all(head); - if (rtld_used) { - runtime = 1; - head->next->prev = malloc(sizeof *head); - *head->next->prev = *head; - head = head->next->prev; - libc->prev->next = malloc(sizeof *libc); - *libc->prev->next = *libc; - libc = libc->prev->next; - if (libc->next) libc->next->prev = libc; - if (tail == &lib) tail = libc; - } else { + runtime = 1; + if (!rtld_used) { free_all(head); free(sys_path); + reclaim((void *)builtin_dsos, 0, sizeof builtin_dsos); } errno = 0;