From f55727ca53308a206cf00d0442f8c57c73761899 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Thu, 31 Aug 2000 02:27:07 +0000 Subject: Update. * sysdeps/generic/ldsodefs.h: Add declaration for _dl_all_dirs and _dl_all_init_dirs. * include/link.h (struct r_search_path_struct): New. (struct link_map): Use it for l_rpath_dirs and l_runpath_dirs. * elf/Versions [ld] (GLIBC_2.2): Add _dl_all_dirs and _dl_all_init_dirs. * elf/dl-close.c (_dl_close): Free l_rpath_dirs and l_runpath_dirs. * elf/dl-libc.c (free_mem): Free _dl_all_dirs list except elements added at startup time. * elf/dl-load.c: Fix memory handling. r_search_path_struct contains element to remember fact that we can free memory. (all_dirs): Renamed to _dl_all_dirs. Made global. (_dl_init_all_dirs): New variable. (fillin_rpath): Save one malloc call. (decompose_rpath): Change interface. New first parameter points to r_search_path_struct. (_dl_init_paths): Adjust for changes. Mark all memory as not deletable. Set _dl_init_all_paths value. (open_path): Remove may_free_dirs parameter. r_search_path_elem *** parameter replaced with r_search_path_struct *. Information about freeing now contained in r_search_path_struct. (_dl_map_object): Adjust for above changes. * elf/dl-open.c (dl_open_worker): Change format of debug info a bit. --- ChangeLog | 25 +++++++ elf/Versions | 2 +- elf/dl-close.c | 5 ++ elf/dl-libc.c | 10 +++ elf/dl-load.c | 168 +++++++++++++++++++++++++-------------------- elf/dl-open.c | 8 +-- include/link.h | 12 +++- sysdeps/generic/ldsodefs.h | 4 ++ 8 files changed, 154 insertions(+), 80 deletions(-) diff --git a/ChangeLog b/ChangeLog index bffcc60956..57ed7cfced 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,30 @@ 2000-08-30 Ulrich Drepper + * sysdeps/generic/ldsodefs.h: Add declaration for _dl_all_dirs and + _dl_all_init_dirs. + * include/link.h (struct r_search_path_struct): New. + (struct link_map): Use it for l_rpath_dirs and l_runpath_dirs. + * elf/Versions [ld] (GLIBC_2.2): Add _dl_all_dirs and + _dl_all_init_dirs. + * elf/dl-close.c (_dl_close): Free l_rpath_dirs and l_runpath_dirs. + * elf/dl-libc.c (free_mem): Free _dl_all_dirs list except elements + added at startup time. + * elf/dl-load.c: Fix memory handling. r_search_path_struct + contains element to remember fact that we can free memory. + (all_dirs): Renamed to _dl_all_dirs. Made global. + (_dl_init_all_dirs): New variable. + (fillin_rpath): Save one malloc call. + (decompose_rpath): Change interface. New first parameter points to + r_search_path_struct. + (_dl_init_paths): Adjust for changes. Mark all memory as not + deletable. Set _dl_init_all_paths value. + (open_path): Remove may_free_dirs parameter. r_search_path_elem *** + parameter replaced with r_search_path_struct *. Information about + freeing now contained in r_search_path_struct. + (_dl_map_object): Adjust for above changes. + + * elf/dl-open.c (dl_open_worker): Change format of debug info a bit. + * elf/dl-load.c (fillin_rpath): Only check for trusted directories when adding new entries. diff --git a/elf/Versions b/elf/Versions index 09f3d2513d..06bcb03f95 100644 --- a/elf/Versions +++ b/elf/Versions @@ -60,6 +60,6 @@ ld { _dl_init_first; # variables used elsewhere - _dl_out_of_memory; + _dl_out_of_memory; _dl_all_dirs; _dl_init_all_dirs; } } diff --git a/elf/dl-close.c b/elf/dl-close.c index 70fcb1b719..40bc6f7202 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -215,6 +215,11 @@ _dl_close (void *_map) if (imap->l_phdr_allocated) free ((void *) imap->l_phdr); + if (imap->l_rpath_dirs.dirs != (void *) -1) + free (imap->l_rpath_dirs.dirs); + if (imap->l_runpath_dirs.dirs != (void *) -1) + free (imap->l_runpath_dirs.dirs); + free (imap); } } diff --git a/elf/dl-libc.c b/elf/dl-libc.c index 7d2b3608b2..dc47851803 100644 --- a/elf/dl-libc.c +++ b/elf/dl-libc.c @@ -126,6 +126,16 @@ static void free_mem (void) { struct link_map *l; + struct r_search_path_elem *d; + + /* Remove all search directories. */ + d = _dl_all_dirs; + while (d != _dl_init_all_dirs) + { + struct r_search_path_elem *old = d; + d = d->next; + free (old); + } /* Remove all additional names added to the objects. */ for (l = _dl_loaded; l != NULL; l = l->l_next) diff --git a/elf/dl-load.c b/elf/dl-load.c index 21c3274ae9..9dfa482b62 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -98,7 +98,7 @@ extern const char *_dl_platform; extern size_t _dl_platformlen; /* This is the decomposed LD_LIBRARY_PATH search path. */ -static struct r_search_path_elem **env_path_list; +static struct r_search_path_struct env_path_list; /* List of the hardware capabilities we might end up using. */ static const struct r_strlenpair *capstr; @@ -329,10 +329,13 @@ add_name_to_object (struct link_map *l, const char *name) } /* All known directories in sorted order. */ -static struct r_search_path_elem *all_dirs; +struct r_search_path_elem *_dl_all_dirs; + +/* All directories after startup. */ +struct r_search_path_elem *_dl_init_all_dirs; /* Standard search directories. */ -static struct r_search_path_elem **rtld_search_dirs; +static struct r_search_path_struct rtld_search_dirs; static size_t max_dirnamelen; @@ -365,7 +368,7 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep, cp[len++] = '/'; /* See if this directory is already known. */ - for (dirp = all_dirs; dirp != NULL; dirp = dirp->next) + for (dirp = _dl_all_dirs; dirp != NULL; dirp = dirp->next) if (dirp->dirnamelen == len && memcmp (cp, dirp->dirname, len) == 0) break; @@ -389,12 +392,14 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep, /* It's a new directory. Create an entry and add it. */ dirp = (struct r_search_path_elem *) malloc (sizeof (*dirp) + ncapstr * sizeof (enum r_dir_status) - + where_len); + + where_len + len + 1); if (dirp == NULL) _dl_signal_error (ENOMEM, NULL, N_("cannot create cache for search path")); - dirp->dirname = cp; + dirp->dirname = ((char *) dirp + sizeof (*dirp) + + ncapstr * sizeof (enum r_dir_status)); + memcpy ((char *) dirp->dirname, cp, len + 1); dirp->dirnamelen = len; if (len > max_dirnamelen) @@ -440,14 +445,14 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep, dirp->what = what; if (__builtin_expect (where != NULL, 1)) - dirp->where = memcpy ((char *) dirp + sizeof (*dirp) + dirp->where = memcpy ((char *) dirp + sizeof (*dirp) + len + 1 + ncapstr * sizeof (enum r_dir_status), where, where_len); else dirp->where = NULL; - dirp->next = all_dirs; - all_dirs = dirp; + dirp->next = _dl_all_dirs; + _dl_all_dirs = dirp; /* Put it in the result array. */ result[nelems++] = dirp; @@ -461,9 +466,10 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep, } -static struct r_search_path_elem ** +static void internal_function -decompose_rpath (const char *rpath, struct link_map *l, const char *what) +decompose_rpath (struct r_search_path_struct *sps, + const char *rpath, struct link_map *l, const char *what) { /* Make a copy we can work with. */ const char *where = l->l_name; @@ -474,7 +480,7 @@ decompose_rpath (const char *rpath, struct link_map *l, const char *what) /* First see whether we must forget the RUNPATH and RPATH from this object. */ - if (_dl_inhibit_rpath != NULL && !__libc_enable_secure) + if (__builtin_expect (_dl_inhibit_rpath != NULL, 0) && !__libc_enable_secure) { const char *found = strstr (_dl_inhibit_rpath, where); if (found != NULL) @@ -492,7 +498,10 @@ decompose_rpath (const char *rpath, struct link_map *l, const char *what) N_("cannot create cache for search path")); result[0] = NULL; - return result; + sps->dirs = result; + sps->malloced = 1; + + return; } } } @@ -516,7 +525,15 @@ decompose_rpath (const char *rpath, struct link_map *l, const char *what) if (result == NULL) _dl_signal_error (ENOMEM, NULL, N_("cannot create cache for search path")); - return fillin_rpath (copy, result, ":", 0, what, where); + fillin_rpath (copy, result, ":", 0, what, where); + + /* Free the copied RPATH string. `fillin_rpath' make own copies if + necessary. */ + free (copy); + + sps->dirs = result; + /* The caller will change this value if we haven't used a real malloc. */ + sps->malloced = 1; } @@ -540,22 +557,23 @@ _dl_init_paths (const char *llp) &ncapstr, &max_capstrlen); /* First set up the rest of the default search directory entries. */ - aelem = rtld_search_dirs = (struct r_search_path_elem **) + aelem = rtld_search_dirs.dirs = (struct r_search_path_elem **) malloc ((nsystem_dirs_len + 1) * sizeof (struct r_search_path_elem *)); - if (rtld_search_dirs == NULL) + if (rtld_search_dirs.dirs == NULL) _dl_signal_error (ENOMEM, NULL, N_("cannot create search path array")); round_size = ((2 * sizeof (struct r_search_path_elem) - 1 + ncapstr * sizeof (enum r_dir_status)) / sizeof (struct r_search_path_elem)); - rtld_search_dirs[0] = (struct r_search_path_elem *) + rtld_search_dirs.dirs[0] = (struct r_search_path_elem *) malloc ((sizeof (system_dirs) / sizeof (system_dirs[0])) * round_size * sizeof (struct r_search_path_elem)); - if (rtld_search_dirs[0] == NULL) + if (rtld_search_dirs.dirs[0] == NULL) _dl_signal_error (ENOMEM, NULL, N_("cannot create cache for search path")); - pelem = all_dirs = rtld_search_dirs[0]; + rtld_search_dirs.malloced = 0; + pelem = _dl_all_dirs = rtld_search_dirs.dirs[0]; strp = system_dirs; idx = 0; @@ -572,12 +590,10 @@ _dl_init_paths (const char *llp) pelem->dirnamelen = system_dirs_len[idx]; strp += system_dirs_len[idx] + 1; - if (pelem->dirname[0] != '/') - for (cnt = 0; cnt < ncapstr; ++cnt) - pelem->status[cnt] = existing; - else - for (cnt = 0; cnt < ncapstr; ++cnt) - pelem->status[cnt] = unknown; + /* System paths must be absolute. */ + assert (pelem->dirname[0] == '/'); + for (cnt = 0; cnt < ncapstr; ++cnt) + pelem->status[cnt] = unknown; pelem->next = (++idx == nsystem_dirs_len ? NULL : (pelem + round_size)); @@ -599,27 +615,30 @@ _dl_init_paths (const char *llp) { /* Allocate room for the search path and fill in information from RUNPATH. */ - l->l_runpath_dirs = - decompose_rpath ((const void *) (D_PTR (l, l_info[DT_STRTAB]) - + l->l_info[DT_RUNPATH]->d_un.d_val), - l, "RUNPATH"); + decompose_rpath (&l->l_runpath_dirs, + (const void *) (D_PTR (l, l_info[DT_STRTAB]) + + l->l_info[DT_RUNPATH]->d_un.d_val), + l, "RUNPATH"); /* The RPATH is ignored. */ - l->l_rpath_dirs = (void *) -1; + l->l_rpath_dirs.dirs = (void *) -1; } else { - l->l_runpath_dirs = (void *) -1; + l->l_runpath_dirs.dirs = (void *) -1; if (l->l_info[DT_RPATH]) - /* Allocate room for the search path and fill in information - from RPATH. */ - l->l_rpath_dirs = - decompose_rpath ((const void *) (D_PTR (l, l_info[DT_STRTAB]) + { + /* Allocate room for the search path and fill in information + from RPATH. */ + decompose_rpath (&l->l_rpath_dirs, + (const void *) (D_PTR (l, l_info[DT_STRTAB]) + l->l_info[DT_RPATH]->d_un.d_val), l, "RPATH"); + l->l_rpath_dirs.malloced = 0; + } else - l->l_rpath_dirs = (void *) -1; + l->l_rpath_dirs.dirs = (void *) -1; } } #endif /* SHARED */ @@ -639,23 +658,28 @@ _dl_init_paths (const char *llp) ++cp; } - env_path_list = (struct r_search_path_elem **) + env_path_list.dirs = (struct r_search_path_elem **) malloc ((nllp + 1) * sizeof (struct r_search_path_elem *)); - if (env_path_list == NULL) + if (env_path_list.dirs == NULL) _dl_signal_error (ENOMEM, NULL, N_("cannot create cache for search path")); - (void) fillin_rpath (local_strdup (llp), env_path_list, ":;", + (void) fillin_rpath (strdupa (llp), env_path_list.dirs, ":;", __libc_enable_secure, "LD_LIBRARY_PATH", NULL); - if (env_path_list[0] == NULL) + if (env_path_list.dirs[0] == NULL) { - free (env_path_list); - env_path_list = (void *) -1; + free (env_path_list.dirs); + env_path_list.dirs = (void *) -1; } + + env_path_list.malloced = 0; } else - env_path_list = (void *) -1; + env_path_list.dirs = (void *) -1; + + /* Remember the last search directory added at startup. */ + _dl_init_all_dirs = _dl_all_dirs; } @@ -1224,10 +1248,9 @@ print_search_path (struct r_search_path_elem **list, static int open_path (const char *name, size_t namelen, int preloaded, - struct r_search_path_elem ***dirsp, int may_free_dirs, - char **realname) + struct r_search_path_struct *sps, char **realname) { - struct r_search_path_elem **dirs = *dirsp; + struct r_search_path_elem **dirs = sps->dirs; char *buf; int fd = -1; const char *current_what = NULL; @@ -1341,9 +1364,9 @@ open_path (const char *name, size_t namelen, int preloaded, { /* Paths which were allocated using the minimal malloc() in ld.so must not be freed using the general free() in libc. */ - if (may_free_dirs) - free (*dirsp); - *dirsp = (void *) -1; + if (sps->malloced) + free (sps->dirs); + sps->dirs = (void *) -1; } return -1; @@ -1415,68 +1438,67 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded, to be loaded. Then that object's dependent, and on up. */ for (l = loader; fd == -1 && l; l = l->l_loader) { - if (l->l_rpath_dirs == NULL) + if (l->l_rpath_dirs.dirs == NULL) { if (l->l_info[DT_RPATH] == NULL) /* There is no path. */ - l->l_rpath_dirs = (void *) -1; + l->l_rpath_dirs.dirs = (void *) -1; else { /* Make sure the cache information is available. */ size_t ptrval = (D_PTR (l, l_info[DT_STRTAB]) + l->l_info[DT_RPATH]->d_un.d_val); - l->l_rpath_dirs = - decompose_rpath ((const char *) ptrval, l, - "RPATH"); + decompose_rpath (&l->l_rpath_dirs, + (const char *) ptrval, l, "RPATH"); - if (l->l_rpath_dirs != (void *) -1) + if (l->l_rpath_dirs.dirs != (void *) -1) fd = open_path (name, namelen, preloaded, - &l->l_rpath_dirs, 1, &realname); + &l->l_rpath_dirs, &realname); } } - else if (l->l_rpath_dirs != (void *) -1) + else if (l->l_rpath_dirs.dirs != (void *) -1) fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs, - 0, &realname); + &realname); } /* If dynamically linked, try the DT_RPATH of the executable itself. */ l = _dl_loaded; if (fd == -1 && l && l->l_type != lt_loaded && l != loader - && l->l_rpath_dirs != (void *) -1) - fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs, 0, + && l->l_rpath_dirs.dirs != (void *) -1) + fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs, &realname); } /* Try the LD_LIBRARY_PATH environment variable. */ - if (fd == -1 && env_path_list != (void *) -1) - fd = open_path (name, namelen, preloaded, &env_path_list, 0, + if (fd == -1 && env_path_list.dirs != (void *) -1) + fd = open_path (name, namelen, preloaded, &env_path_list, &realname); /* Look at the RUNPATH informaiton for this binary. */ - if (loader != NULL && loader->l_runpath_dirs != (void *) -1) + if (loader != NULL && loader->l_runpath_dirs.dirs != (void *) -1) { - if (loader->l_runpath_dirs == NULL) + if (loader->l_runpath_dirs.dirs == NULL) { if (loader->l_info[DT_RUNPATH] == NULL) /* No RUNPATH. */ - loader->l_runpath_dirs = (void *) -1; + loader->l_runpath_dirs.dirs = (void *) -1; else { /* Make sure the cache information is available. */ size_t ptrval = (D_PTR (loader, l_info[DT_STRTAB]) + loader->l_info[DT_RUNPATH]->d_un.d_val); - loader->l_runpath_dirs = - decompose_rpath ((const char *) ptrval, loader, "RUNPATH"); + decompose_rpath (&loader->l_runpath_dirs, + (const char *) ptrval, loader, "RUNPATH"); - if (loader->l_runpath_dirs != (void *) -1) + if (loader->l_runpath_dirs.dirs != (void *) -1) fd = open_path (name, namelen, preloaded, - &loader->l_runpath_dirs, 1, &realname); + &loader->l_runpath_dirs, &realname); } } - else if (loader->l_runpath_dirs != (void *) -1) + else if (loader->l_runpath_dirs.dirs != (void *) -1) fd = open_path (name, namelen, preloaded, - &loader->l_runpath_dirs, 0, &realname); + &loader->l_runpath_dirs, &realname); } if (fd == -1) @@ -1536,8 +1558,8 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded, if (fd == -1 && (l == NULL || __builtin_expect (!(l->l_flags_1 & DF_1_NODEFLIB), 1)) - && rtld_search_dirs != (void *) -1) - fd = open_path (name, namelen, preloaded, &rtld_search_dirs, 0, + && rtld_search_dirs.dirs != (void *) -1) + fd = open_path (name, namelen, preloaded, &rtld_search_dirs, &realname); /* Add another newline when we a tracing the library loading. */ diff --git a/elf/dl-open.c b/elf/dl-open.c index a128b343d2..a618ca0470 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -166,11 +166,11 @@ dl_open_worker (void *a) buf[sizeof buf - 1] = '\0'; - _dl_debug_message (1, "\nopening file=", new->l_name, + _dl_debug_message (1, "opening file=", new->l_name, "; opencount == ", _itoa_word (new->l_opencount, buf + sizeof buf - 1, 10, 0), - "\n", NULL); + "\n\n", NULL); } /* It was already open. */ return; @@ -325,11 +325,11 @@ dl_open_worker (void *a) buf[sizeof buf - 1] = '\0'; - _dl_debug_message (1, "\nopening file=", new->l_name, + _dl_debug_message (1, "opening file=", new->l_name, "; opencount == ", _itoa_word (new->l_opencount, buf + sizeof buf - 1, 10, 0), - "\n", NULL); + "\n\n", NULL); } } diff --git a/include/link.h b/include/link.h index 681b6542f3..0eab781428 100644 --- a/include/link.h +++ b/include/link.h @@ -101,6 +101,14 @@ struct r_scope_elem }; +/* Structure to record search path and allocation mechanism. */ +struct r_search_path_struct + { + struct r_search_path_elem **dirs; + int malloced; + }; + + /* Structure describing a loaded shared object. The `l_next' and `l_prev' members form a chain of all the shared objects loaded at startup. @@ -176,7 +184,7 @@ struct link_map struct r_found_version *l_versions; /* Collected information about own RPATH directories. */ - struct r_search_path_elem **l_rpath_dirs; + struct r_search_path_struct l_rpath_dirs; /* Collected results of relocation while profiling. */ ElfW(Addr) *l_reloc_result; @@ -205,7 +213,7 @@ struct link_map ino64_t l_ino; /* Collected information about own RUNPATH directories. */ - struct r_search_path_elem **l_runpath_dirs; + struct r_search_path_struct l_runpath_dirs; /* List of object in order of the init and fini calls. */ struct link_map **l_initfini; diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index 4cb4472ca1..b93482c6d3 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -200,6 +200,10 @@ extern const char _dl_out_of_memory[]; /* Nonzero if runtime lookups should not update the .got/.plt. */ extern int _dl_bind_not; +/* List of search directories. */ +extern struct r_search_path_elem *_dl_all_dirs; +extern struct r_search_path_elem *_dl_init_all_dirs; + /* OS-dependent function to open the zero-fill device. */ extern int _dl_sysdep_open_zero_fill (void); /* dl-sysdep.c */ -- cgit 1.4.1