fix regression in dlsym: rejection of special RTLD_* handles as invalid
[musl] / src / ldso / dynlink.c
index 2524205..e73806c 100644 (file)
@@ -102,7 +102,6 @@ static int ldso_fail;
 static jmp_buf rtld_fail;
 static pthread_rwlock_t lock;
 static struct debug debug;
-static size_t *auxv;
 static size_t tls_cnt, tls_offset, tls_align = 4*sizeof(size_t);
 static pthread_mutex_t init_fini_lock = { ._m_type = PTHREAD_MUTEX_RECURSIVE };
 
@@ -434,7 +433,7 @@ static struct dso *load_library(const char *name)
 {
        char buf[2*NAME_MAX+2];
        const char *pathname;
-       unsigned char *base, *map;
+       unsigned char *map;
        size_t map_len;
        struct dso *p, temp_dso = {0};
        int fd;
@@ -479,13 +478,16 @@ static struct dso *load_library(const char *name)
                        if (!sys_path) {
                                FILE *f = fopen(ETC_LDSO_PATH, "rbe");
                                if (f) {
-                                       if (getline(&sys_path, (size_t[1]){0}, f) > 0)
-                                               sys_path[strlen(sys_path)-1]=0;
+                                       if (getline(&sys_path, (size_t[1]){0}, f) > 0) {
+                                               size_t l = strlen(sys_path);
+                                               if (l && sys_path[l-1]=='\n')
+                                                       sys_path[l-1] = 0;
+                                       }
                                        fclose(f);
                                }
                        }
-                       if (sys_path) fd = path_open(name, sys_path, buf, sizeof buf);
-                       else fd = path_open(name, "/lib:/usr/local/lib:/usr/lib", buf, sizeof buf);
+                       if (!sys_path) sys_path = "/lib:/usr/local/lib:/usr/lib";
+                       fd = path_open(name, sys_path, buf, sizeof buf);
                }
                pathname = buf;
        }
@@ -564,7 +566,7 @@ static struct dso *load_library(const char *name)
        p->prev = tail;
        tail = p;
 
-       if (ldd_mode) dprintf(1, "\t%s => %s (%p)\n", name, pathname, base);
+       if (ldd_mode) dprintf(1, "\t%s => %s (%p)\n", name, pathname, p->base);
 
        return p;
 }
@@ -798,6 +800,7 @@ void *__dynlink(int argc, char **argv)
        struct dso *const vdso = builtin_dsos+2;
        char *env_preload=0;
        size_t vdso_base;
+       size_t *auxv;
 
        /* Find aux vector just past environ[] */
        for (i=argc+1; argv[i]; i++)
@@ -924,7 +927,8 @@ void *__dynlink(int argc, char **argv)
                        if (phdr->p_type == PT_LOAD)
                                vdso->base = (void *)(vdso_base - phdr->p_vaddr + phdr->p_offset);
                }
-               vdso->name = vdso->shortname = "linux-gate.so.1";
+               vdso->name = "";
+               vdso->shortname = "linux-gate.so.1";
                vdso->global = 1;
                decode_dyn(vdso);
                vdso->prev = lib;
@@ -995,13 +999,16 @@ void *__dynlink(int argc, char **argv)
 
        if (ssp_used) __init_ssp((void *)aux[AT_RANDOM]);
 
-       atexit(do_fini);
-       do_init_fini(tail);
-
        errno = 0;
        return (void *)aux[AT_ENTRY];
 }
 
+void __init_ldso_ctors(void)
+{
+       atexit(do_fini);
+       do_init_fini(tail);
+}
+
 void *dlopen(const char *file, int mode)
 {
        struct dso *volatile p, *orig_tail, *next;
@@ -1071,7 +1078,7 @@ void *dlopen(const char *file, int mode)
 
        update_tls_size();
 
-       if (ssp_used) __init_ssp(auxv);
+       if (ssp_used) __init_ssp(libc.auxv);
 
        _dl_debug_state();
        orig_tail = tail;
@@ -1084,6 +1091,15 @@ end:
        return p;
 }
 
+static int invalid_dso_handle(void *h)
+{
+       struct dso *p;
+       for (p=head; p; p=p->next) if (h==p) return 0;
+       snprintf(errbuf, sizeof errbuf, "Invalid library handle %p", (void *)h);
+       errflag = 1;
+       return 1;
+}
+
 static void *do_dlsym(struct dso *p, const char *s, void *ra)
 {
        size_t i;
@@ -1103,6 +1119,8 @@ static void *do_dlsym(struct dso *p, const char *s, void *ra)
                        return __tls_get_addr((size_t []){def.dso->tls_id, def.sym->st_value});
                return def.dso->base + def.sym->st_value;
        }
+       if (p != RTLD_DEFAULT && p != RTLD_NEXT && invalid_dso_handle(p))
+               return 0;
        if (p->ghashtab) {
                gh = gnu_hash(s);
                sym = gnu_lookup(s, gh, p);
@@ -1171,7 +1189,7 @@ int __dladdr(void *addr, Dl_info *info)
        }
 
        for (; nsym; nsym--, sym++) {
-               if (sym->st_shndx && sym->st_value
+               if (sym->st_value
                 && (1<<(sym->st_info&0xf) & OK_TYPES)
                 && (1<<(sym->st_info>>4) & OK_BINDS)) {
                        void *symaddr = p->base + sym->st_value;
@@ -1229,6 +1247,12 @@ int dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size_t size, void
        return ret;
 }
 #else
+static int invalid_dso_handle(void *h)
+{
+       snprintf(errbuf, sizeof errbuf, "Invalid library handle %p", (void *)h);
+       errflag = 1;
+       return 1;
+}
 void *dlopen(const char *file, int mode)
 {
        return 0;
@@ -1252,5 +1276,5 @@ char *dlerror()
 
 int dlclose(void *p)
 {
-       return 0;
+       return invalid_dso_handle(p);
 }