fix dynamic linker not to depend on DYNAMIC ptr in 0th entry of GOT
[musl] / src / ldso / dynlink.c
index 390f50b..b26992d 100644 (file)
@@ -1,3 +1,4 @@
+#ifdef __PIC__
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -72,8 +73,9 @@ static void decode_vec(size_t *v, size_t *a, size_t cnt)
        }
 }
 
-static uint32_t hash(const char *s)
+static uint32_t hash(const char *s0)
 {
+       const unsigned char *s = (void *)s0;
        uint_fast32_t h = 0;
        while (*s) {
                h = 16*h + *s++;
@@ -465,6 +467,7 @@ void *__dynlink(int argc, char **argv, size_t *got)
        size_t i;
        Phdr *phdr;
        Ehdr *ehdr;
+       size_t *lib_dynv;
        static struct dso builtin_dsos[3];
        struct dso *const app = builtin_dsos+0;
        struct dso *const lib = builtin_dsos+1;
@@ -482,6 +485,13 @@ void *__dynlink(int argc, char **argv, size_t *got)
 
        decode_vec(auxv, aux, AUX_CNT);
 
+       /* 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] || aux[AT_SECURE]) {
+               env_path = 0;
+               env_preload = 0;
+       }
+
        for (i=0; auxv[i]; i+=2) {
                if (auxv[i]==AT_SYSINFO_EHDR) {
                        vdso_base = auxv[i+1];
@@ -489,16 +499,17 @@ void *__dynlink(int argc, char **argv, size_t *got)
                }
        }
 
-       /* 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] || aux[AT_SECURE]) {
-               env_path = 0;
-               env_preload = 0;
+       /* Find the dynamic linker's DYNAMIC section and decode it */
+       ehdr = (void *)aux[AT_BASE];
+       phdr = (void *)(aux[AT_BASE] + ehdr->e_phoff);
+       for (i=ehdr->e_phnum; i--; phdr=(void *)((char *)phdr + ehdr->e_phentsize)) {
+               if (phdr->p_type == PT_DYNAMIC) {
+                       lib_dynv = (void *)(aux[AT_BASE] + phdr->p_vaddr);
+                       decode_vec(lib_dynv, lib_dyn, DYN_CNT);
+                       break;
+               }
        }
 
-       /* Relocate ldso's DYNAMIC pointer and load vector */
-       decode_vec((void *)(got[0] += aux[AT_BASE]), lib_dyn, DYN_CNT);
-
        /* Find the program image's DYNAMIC section and decode it */
        phdr = (void *)aux[AT_PHDR];
        for (i=aux[AT_PHNUM]; i--; phdr=(void *)((char *)phdr + aux[AT_PHENT])) {
@@ -524,7 +535,7 @@ void *__dynlink(int argc, char **argv, size_t *got)
                .strings = (void *)(aux[AT_BASE]+lib_dyn[DT_STRTAB]),
                .hashtab = (void *)(aux[AT_BASE]+lib_dyn[DT_HASH]),
                .syms = (void *)(aux[AT_BASE]+lib_dyn[DT_SYMTAB]),
-               .dynv = (void *)(got[0]),
+               .dynv = lib_dynv,
                .name = "libc.so",
                .global = 1,
                .relocated = 1
@@ -681,3 +692,4 @@ int dlclose(void *p)
 {
        return 0;
 }
+#endif