OSDN Git Service

mkostemp: fix implementation
[uclinux-h8/uClibc.git] / ldso / ldso / ldso.c
index 775acdd..5619629 100644 (file)
 #include LDSO_ELFINTERP
 
 /* Global variables used within the shared library loader */
+#ifdef __LDSO_LD_LIBRARY_PATH__
 char *_dl_library_path         = NULL; /* Where we look for libraries */
+#endif
 #ifdef __LDSO_PRELOAD_ENV_SUPPORT__
 char *_dl_preload              = NULL; /* Things to be loaded before the libs */
 #endif
-char *_dl_ldsopath             = NULL; /* Location of the shared lib loader */
 int _dl_errno                  = 0;    /* We can't use the real errno in ldso */
 size_t _dl_pagesize            = 0;    /* Store the page size for use later */
 struct r_debug *_dl_debug_addr = NULL; /* Used to communicate with the gdb debugger */
@@ -63,7 +64,7 @@ struct elf_resolve *_dl_trace_prelink_map    = NULL;  /* Library module for preli
 bool _dl_verbose                               = true;                                 /* On by default */
 bool prelinked                                 = false;
 #endif
-static int _dl_secure = 1; /* Are we dealing with setuid stuff? */
+int _dl_secure = 1; /* Are we dealing with setuid stuff? */
 
 #ifdef __SUPPORT_LD_DEBUG__
 char *_dl_debug           = NULL;
@@ -76,17 +77,11 @@ char *_dl_debug_bindings  = NULL;
 int   _dl_debug_file      = 2;
 #endif
 
-#if defined (__LDSO_STANDALONE_SUPPORT__) && defined (__sh__)
-/* Not hidden, needed for standalone execution. */
-/*
- * FIXME: align dl_start for SH to other archs so that we can keep this symbol
- *        hidden and we don't need to handle in __uClibc_main
- */
+#ifdef __DSBT__
+void **_dl_ldso_dsbt = NULL;
+#endif
 
-unsigned long _dl_skip_args = 0;
-#else
 unsigned long attribute_hidden _dl_skip_args = 0;
-#endif
 
 const char *_dl_progname = UCLIBC_LDSO;      /* The name of the executable being run */
 #include "dl-startup.c"
@@ -130,6 +125,40 @@ uintptr_t __guard attribute_relro;
 # endif
 #endif
 
+#ifdef __LDSO_SEARCH_INTERP_PATH__
+const char *_dl_ldsopath = NULL;       /* Location of the shared lib loader */
+
+static void _dl_ldsopath_init(struct elf_resolve *tpnt)
+{
+       char *ldsopath, *ptmp;
+
+       /*
+        * Store the path where the shared lib loader was found for later use.
+        * Note that this logic isn't bullet proof when it comes to relative
+        * paths: if you use "./lib/ldso.so", and then the app does chdir()
+        * followed by dlopen(), the old ldso path won't get searched.  But
+        * that is a fairly pathological use case, so if you don't like that,
+        * then set a full path to your interp and be done :P.
+        */
+       ldsopath = _dl_strdup(tpnt->libname);
+       ptmp = _dl_strrchr(ldsopath, '/');
+       /*
+        * If there is no "/", then set the path to "", and the code
+        * later on will take this to implicitly mean "search $PWD".
+        */
+       if (!ptmp)
+               ptmp = ldsopath;
+       *ptmp = '\0';
+
+       _dl_ldsopath = ldsopath;
+       _dl_debug_early("Lib Loader: (%x) %s: using path: %s\n",
+               (unsigned) DL_LOADADDR_BASE(tpnt->loadaddr), tpnt->libname,
+               _dl_ldsopath);
+}
+#else
+#define _dl_ldsopath_init(tpnt)
+#endif
+
 char *_dl_getenv(const char *symbol, char **envp)
 {
        char *pnt;
@@ -210,9 +239,9 @@ void *_dl_malloc(size_t size)
 
                _dl_debug_early("mmapping more memory\n");
                _dl_mmap_zero = _dl_malloc_addr = _dl_mmap((void *) 0, rounded_size,
-                               PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZE, -1, 0);
+                               PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZED, -1, 0);
                if (_dl_mmap_check_error(_dl_mmap_zero)) {
-                       _dl_dprintf(_dl_debug_file, "%s: mmap of a spare page failed!\n", _dl_progname);
+                       _dl_dprintf(2, "%s: mmap of a spare page failed!\n", _dl_progname);
                        _dl_exit(20);
                }
        }
@@ -304,22 +333,26 @@ static void trace_objects(struct elf_resolve *tpnt, char *str_name)
                                        tpnt->mapaddr, DL_LOADADDR_BASE(tpnt->loadaddr));
        }
 
+#if defined USE_TLS && USE_TLS
        if ((tpnt->libtype != program_interpreter) && (tpnt->l_tls_modid))
                _dl_dprintf (1, " TLS(%x, %x)\n", tpnt->l_tls_modid,
                                        (size_t) tpnt->l_tls_offset);
        else
+#endif
                _dl_dprintf (1, "\n");
 }
 #endif
 
 static struct elf_resolve * add_ldso(struct elf_resolve *tpnt,
                                                                         DL_LOADADDR_TYPE load_addr,
+                                                                        ElfW(Addr) ldso_mapaddr,
                                                                         ElfW(auxv_t) auxvt[AT_EGID + 1],
                                                                         struct dyn_elf *rpnt)
 {
                ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;
                ElfW(Phdr) *myppnt = (ElfW(Phdr) *)
-                                                               DL_RELOC_ADDR(load_addr, epnt->e_phoff);
+                               DL_RELOC_ADDR(DL_GET_RUN_ADDR(load_addr, ldso_mapaddr),
+                                                         epnt->e_phoff);
                int j;
                struct stat st;
 
@@ -327,7 +360,7 @@ static struct elf_resolve * add_ldso(struct elf_resolve *tpnt,
                                              tpnt->dynamic_info, (unsigned long)tpnt->dynamic_addr,
                                              0);
 
-               tpnt->mapaddr = load_addr;
+               tpnt->mapaddr = ldso_mapaddr;
                if (_dl_stat(tpnt->libname, &st) >= 0) {
                        tpnt->st_dev = st.st_dev;
                        tpnt->st_ino = st.st_ino;
@@ -374,7 +407,7 @@ void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
                          ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv
                          DL_GET_READY_TO_RUN_EXTRA_PARMS)
 {
-       ElfW(Addr) app_mapaddr = 0;
+       ElfW(Addr) app_mapaddr = 0, ldso_mapaddr = 0;
        ElfW(Phdr) *ppnt;
        ElfW(Dyn) *dpnt;
        char *lpntstr;
@@ -425,9 +458,14 @@ void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
                _dl_progname = argv[0];
        }
 
+#ifdef __DSBT__
+       _dl_ldso_dsbt = (void *)tpnt->dynamic_info[DT_DSBT_BASE_IDX];
+       _dl_ldso_dsbt[tpnt->dynamic_info[DT_DSBT_INDEX_IDX]] = _dl_ldso_dsbt;
+#endif
+
 #ifndef __LDSO_STANDALONE_SUPPORT__
        if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) {
-               _dl_dprintf(_dl_debug_file, "Standalone execution is not enabled\n");
+               _dl_dprintf(2, "Standalone execution is not enabled\n");
                _dl_exit(1);
        }
 #endif
@@ -453,7 +491,9 @@ void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
 #ifdef __LDSO_PRELOAD_ENV_SUPPORT__
                _dl_preload = _dl_getenv("LD_PRELOAD", envp);
 #endif
+#ifdef __LDSO_LD_LIBRARY_PATH__
                _dl_library_path = _dl_getenv("LD_LIBRARY_PATH", envp);
+#endif
        } else {
                static const char unsecure_envvars[] =
 #ifdef EXTRA_UNSECURE_ENVVARS
@@ -463,16 +503,18 @@ void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
                const char *nextp;
                _dl_secure = 1;
 
+#ifdef __LDSO_PRELOAD_ENV_SUPPORT__
+               _dl_preload = _dl_getenv("LD_PRELOAD", envp);
+#endif
                nextp = unsecure_envvars;
                do {
                        _dl_unsetenv (nextp, envp);
                        /* We could use rawmemchr but this need not be fast.  */
                        nextp = _dl_strchr(nextp, '\0') + 1;
                } while (*nextp != '\0');
-#ifdef __LDSO_PRELOAD_ENV_SUPPORT__
-               _dl_preload = NULL;
-#endif
+#ifdef __LDSO_LD_LIBRARY_PATH__
                _dl_library_path = NULL;
+#endif
                /* SUID binaries can be exploited if they do LAZY relocation. */
                unlazy = RTLD_NOW;
        }
@@ -484,14 +526,15 @@ void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
 
 #ifdef __LDSO_STANDALONE_SUPPORT__
        if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) {
-               char *ptmp;
-               unsigned int *aux_dat = (unsigned int *) argv;
-               int argc = aux_dat[-1];
+               ElfW(Addr) *aux_dat = (ElfW(Addr) *) argv;
+               int argc = (int) aux_dat[-1];
 
                tpnt->libname = argv[0];
                while (argc > 1)
                        if (! _dl_strcmp (argv[1], "--library-path") && argc > 2) {
+#ifdef __LDSO_LD_LIBRARY_PATH__
                                _dl_library_path = argv[2];
+#endif
                                _dl_skip_args += 2;
                                argc -= 2;
                                argv += 2;
@@ -536,7 +579,7 @@ of this helper program; chances are you did not intend to run this program.\n\
                 */
                app_tpnt = _dl_load_elf_shared_library(_dl_secure, &rpnt, _dl_progname);
                if (!app_tpnt) {
-                       _dl_dprintf(_dl_debug_file, "can't load '%s'\n", _dl_progname);
+                       _dl_dprintf(2, "can't load '%s'\n", _dl_progname);
                        _dl_exit(16);
                }
                /*
@@ -563,15 +606,7 @@ of this helper program; chances are you did not intend to run this program.\n\
                        }
                }
 
-               /* Store the path where the shared lib loader was found
-                * for later use
-                */
-               _dl_ldsopath = _dl_strdup(tpnt->libname);
-               ptmp = _dl_strrchr(_dl_ldsopath, '/');
-               if (ptmp != _dl_ldsopath)
-                       *ptmp = '\0';
-
-               _dl_debug_early("Lib Loader: (%x) %s\n", (unsigned) DL_LOADADDR_BASE(tpnt->loadaddr), tpnt->libname);
+               _dl_ldsopath_init(tpnt);
        } else {
 #endif
 
@@ -639,7 +674,7 @@ of this helper program; chances are you did not intend to run this program.\n\
                        }
 #else
                        if (app_tpnt->dynamic_info[DT_TEXTREL]) {
-                               _dl_dprintf(_dl_debug_file, "Can't modify application's text section; use the GCC option -fPIE for position-independent executables.\n");
+                               _dl_dprintf(2, "Can't modify application's text section; use the GCC option -fPIE for position-independent executables.\n");
                                _dl_exit(1);
                        }
 #endif
@@ -662,6 +697,11 @@ of this helper program; chances are you did not intend to run this program.\n\
                        app_tpnt->mapaddr = app_mapaddr;
                        app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL;
                        app_tpnt->usage_count++;
+#ifdef __DSBT__
+                       _dl_ldso_dsbt[0] = app_tpnt->dsbt_table;
+                       _dl_memcpy(app_tpnt->dsbt_table, _dl_ldso_dsbt,
+                                  app_tpnt->dsbt_size * sizeof(tpnt->dsbt_table[0]));
+#endif
                        lpnt = (unsigned long *) (app_tpnt->dynamic_info[DT_PLTGOT]);
 #ifdef ALLOW_ZERO_PLTGOT
                        if (lpnt)
@@ -672,19 +712,8 @@ of this helper program; chances are you did not intend to run this program.\n\
                /* OK, fill this in - we did not have this before */
                if (ppnt->p_type == PT_INTERP) {
                        tpnt->libname = (char *) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr);
-#ifdef __LDSO_SEARCH_INTERP_PATH__
-                       {
-                               char *ptmp;
-                               /* Store the path where the shared lib loader was found
-                                * for later use
-                                */
-                               _dl_ldsopath = _dl_strdup(tpnt->libname);
-                               ptmp = _dl_strrchr(_dl_ldsopath, '/');
-                               if (ptmp != _dl_ldsopath)
-                                       *ptmp = '\0';
-                       }
-                       _dl_debug_early("Lib Loader: (%x) %s\n", (unsigned) DL_LOADADDR_BASE(tpnt->loadaddr), tpnt->libname);
-#endif
+
+                       _dl_ldsopath_init(tpnt);
                }
 
                /* Discover any TLS sections if the target supports them. */
@@ -705,10 +734,10 @@ of this helper program; chances are you did not intend to run this program.\n\
                                _dl_tls_max_dtv_idx = app_tpnt->l_tls_modid = 1;
 
                        }
-                       _dl_debug_early("Found TLS header for appplication program\n");
+                       _dl_debug_early("Found TLS header for application program\n");
                        break;
 #else
-                       _dl_dprintf(_dl_debug_file, "Program uses unsupported TLS data!\n");
+                       _dl_dprintf(2, "Program uses unsupported TLS data!\n");
                        _dl_exit(1);
 #endif
                }
@@ -722,7 +751,8 @@ of this helper program; chances are you did not intend to run this program.\n\
         * case the executable is actually an ET_DYN object.
         */
        if (app_tpnt->l_tls_initimage != NULL) {
-               unsigned int tmp = (unsigned int) app_tpnt->l_tls_initimage;
+               char *tmp attribute_unused =
+                       (char *) app_tpnt->l_tls_initimage;
                app_tpnt->l_tls_initimage =
                        (char *) app_tpnt->l_tls_initimage + app_tpnt->loadaddr;
                _dl_debug_early("Relocated TLS initial image from %x to %x (size = %x)\n",
@@ -798,11 +828,12 @@ of this helper program; chances are you did not intend to run this program.\n\
 
 #ifndef __LDSO_LDD_SUPPORT__
        if (trace_loaded_objects) {
-               _dl_dprintf(_dl_debug_file, "Use the ldd provided by uClibc\n");
+               _dl_dprintf(2, "Use the ldd provided by uClibc\n");
                _dl_exit(1);
        }
 #endif
 
+       ldso_mapaddr = (ElfW(Addr)) auxvt[AT_BASE].a_un.a_val;
        /*
         * OK, fix one more thing - set up debug_addr so it will point
         * to our chain.  Later we may need to fill in more fields, but this
@@ -810,7 +841,8 @@ of this helper program; chances are you did not intend to run this program.\n\
         */
        debug_addr->r_map = (struct link_map *) _dl_loaded_modules;
        debug_addr->r_version = 1;
-       debug_addr->r_ldbase = (ElfW(Addr)) DL_LOADADDR_BASE(load_addr);
+       debug_addr->r_ldbase = (ElfW(Addr))
+               DL_LOADADDR_BASE(DL_GET_RUN_ADDR(load_addr, ldso_mapaddr));
        debug_addr->r_brk = (unsigned long) &_dl_debug_state;
        _dl_debug_addr = debug_addr;
 
@@ -842,7 +874,9 @@ of this helper program; chances are you did not intend to run this program.\n\
                        if (!_dl_secure || _dl_strchr(str, '/') == NULL) {
                                _dl_if_debug_dprint("\tfile='%s';  needed by '%s'\n", str, _dl_progname);
 
-                               tpnt1 = _dl_load_shared_library(_dl_secure, &rpnt, NULL, str, trace_loaded_objects);
+                               tpnt1 = _dl_load_shared_library(
+                                       _dl_secure ? DL_RESOLVE_SECURE : 0,
+                                       &rpnt, NULL, str, trace_loaded_objects);
                                if (!tpnt1) {
 #ifdef __LDSO_LDD_SUPPORT__
                                        if (trace_loaded_objects || _dl_trace_prelink)
@@ -850,8 +884,9 @@ of this helper program; chances are you did not intend to run this program.\n\
                                        else
 #endif
                                        {
-                                               _dl_dprintf(_dl_debug_file, "%s: can't load " "library '%s'\n", _dl_progname, str);
-                                               _dl_exit(15);
+                                               _dl_dprintf(2, "%s: library '%s' "
+                                                       "from LD_PRELOAD can't be preloaded: ignored.\n",
+                                                       _dl_progname, str);
                                        }
                                } else {
                                        tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
@@ -887,13 +922,14 @@ of this helper program; chances are you did not intend to run this program.\n\
                char *preload;
                int fd;
                char c, *cp, *cp2;
+               struct stat st;
 
                if (_dl_stat(LDSO_PRELOAD, &st) || st.st_size == 0) {
                        break;
                }
 
                if ((fd = _dl_open(LDSO_PRELOAD, O_RDONLY, 0)) < 0) {
-                       _dl_dprintf(_dl_debug_file, "%s: can't open file '%s'\n",
+                       _dl_dprintf(2, "%s: can't open file '%s'\n",
                                    _dl_progname, LDSO_PRELOAD);
                        break;
                }
@@ -902,7 +938,7 @@ of this helper program; chances are you did not intend to run this program.\n\
                                             PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
                _dl_close(fd);
                if (preload == (caddr_t) -1) {
-                       _dl_dprintf(_dl_debug_file, "%s:%i: can't map '%s'\n",
+                       _dl_dprintf(2, "%s:%i: can't map '%s'\n",
                                    _dl_progname, __LINE__, LDSO_PRELOAD);
                        break;
                }
@@ -941,7 +977,7 @@ of this helper program; chances are you did not intend to run this program.\n\
                                else
 # endif
                                {
-                                       _dl_dprintf(_dl_debug_file, "%s: can't load library '%s'\n", _dl_progname, cp2);
+                                       _dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, cp2);
                                        _dl_exit(15);
                                }
                        } else {
@@ -986,7 +1022,8 @@ of this helper program; chances are you did not intend to run this program.\n\
                                if (_dl_strcmp(name, UCLIBC_LDSO) == 0) {
                                                if (!ldso_tpnt) {
                                                        /* Insert the ld.so only once */
-                                                       ldso_tpnt = add_ldso(tpnt, load_addr, auxvt, rpnt);
+                                                       ldso_tpnt = add_ldso(tpnt, load_addr,
+                                                                                                ldso_mapaddr, auxvt, rpnt);
                                                }
                                                ldso_tpnt->usage_count++;
                                                tpnt1 = ldso_tpnt;
@@ -1001,7 +1038,7 @@ of this helper program; chances are you did not intend to run this program.\n\
                                        } else
 #endif
                                        {
-                                               _dl_dprintf(_dl_debug_file, "%s: can't load library '%s'\n", _dl_progname, lpntstr);
+                                               _dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, lpntstr);
                                                _dl_exit(16);
                                        }
                                }
@@ -1086,7 +1123,7 @@ of this helper program; chances are you did not intend to run this program.\n\
         * again once all libs are loaded.
         */
        if (!ldso_tpnt) {
-               tpnt = add_ldso(tpnt, load_addr, auxvt, rpnt);
+               tpnt = add_ldso(tpnt, load_addr, ldso_mapaddr, auxvt, rpnt);
                tpnt->usage_count++;
                nscope_elem++;
        } else