discard dso descriptors after performing relocations
[musl] / src / ldso / dynlink.c
index b444425..105ed3d 100644 (file)
@@ -35,7 +35,7 @@ struct dso
        int refcnt;
        size_t *dynv;
        Sym *syms;
-       size_t *hashtab;
+       uint32_t *hashtab;
        char *strings;
        unsigned char *base;
        unsigned char *map;
@@ -48,6 +48,7 @@ struct dso
 };
 
 static struct dso *head, *tail, *libc;
+static int trust_env;
 
 #define AUX_CNT 15
 #define DYN_CNT 34
@@ -71,7 +72,7 @@ static uint32_t hash(const char *s)
        return h & 0xfffffff;
 }
 
-static Sym *lookup(const char *s, uint32_t h, Sym *syms, size_t *hashtab, char *strings)
+static Sym *lookup(const char *s, uint32_t h, Sym *syms, uint32_t *hashtab, char *strings)
 {
        size_t i;
        for (i=hashtab[2+h%hashtab[0]]; i; i=hashtab[2+hashtab[0]+i]) {
@@ -317,6 +318,17 @@ static void reloc_all(struct dso *p)
                        2, p->syms, p->strings, p);
                do_relocs(p->base, (void *)(p->base+dyn[DT_RELA]), dyn[DT_RELASZ],
                        3, p->syms, p->strings, p);
+               p->relocated = 1;
+       }
+}
+
+static void free_all(struct dso *p)
+{
+       struct dso *n;
+       while (p) {
+               n = p->next;
+               if (p->map) free(p);
+               p = n;
        }
 }
 
@@ -373,6 +385,11 @@ void *__dynlink(int argc, char **argv, size_t *got)
 
        /* At this point the standard library is fully functional */
 
+       /* Only trust user/env if kernel says we're not suid/sgid */
+       trust_env = (aux[0]&0x7800)==0x7800
+               && aux[AT_UID]==aux[AT_EUID]
+               && aux[AT_GID]==aux[AT_EGID];
+
        head = tail = &app;
        libc = &lib;
        app.next = 0;
@@ -380,6 +397,8 @@ void *__dynlink(int argc, char **argv, size_t *got)
 
        reloc_all(head);
 
+       free_all(head);
+
        errno = 0;
        return (void *)aux[AT_ENTRY];
 }