From 0479b305c5b7c8e3fa8e3002982cf8cac02b842e Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Fri, 22 Jun 2012 11:10:31 -0700 Subject: Fix invalid memory access in do_lookup_x. [BZ #13579] Do not free l_initfini and allow it to be reused on subsequent dl_open calls for the same library. This fixes the invalid memory access in do_lookup_x when the previously free'd l_initfini was accessed through l_searchlist when a library had been opened for the second time. --- ChangeLog | 11 +++++++++++ NEWS | 25 +++++++++++++------------ elf/dl-close.c | 15 +++------------ elf/dl-deps.c | 7 ++++--- elf/dl-libc.c | 9 ++++++--- elf/rtld.c | 2 ++ include/link.h | 8 ++++---- 7 files changed, 43 insertions(+), 34 deletions(-) diff --git a/ChangeLog b/ChangeLog index b7f1699..8999784 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2012-06-22 Andreas Schwab + + [BZ #13579] + * include/link.h (struct link_map): Add l_free_initfini. + * elf/dl-deps.c (_dl_map_object_deps): Set it when assigning + l_initfini. + * elf/dl-close.c (_dl_close_worker): Don't free l_initfini. + * elf/rtld.c (dl_main): Clear it on all objects loaded on startup. + * elf/dl-libc.c (free_mem): Free l_initfini if l_free_initfini is + set. + 2012-06-22 Carlos O'Donell * configure.in: Use AC_LANG_SOURCE. diff --git a/NEWS b/NEWS index 1ce8ee3..a9500fa 100644 --- a/NEWS +++ b/NEWS @@ -19,18 +19,19 @@ Version 2.16 12193, 12194, 12297, 12298, 12301, 12340, 12354, 12416, 12495, 13058, 13223, 13361, 13525, 13526, 13527, 13528, 13529, 13530, 13531, 13532, 13533, 13547, 13551, 13552, 13553, 13555, 13556, 13559, 13563, 13566, - 13576, 13583, 13592, 13594, 13613, 13618, 13637, 13656, 13658, 13673, - 13691, 13695, 13704, 13705, 13706, 13718, 13726, 13738, 13739, 13743, - 13750, 13758, 13760, 13761, 13775, 13786, 13787, 13792, 13806, 13824, - 13840, 13841, 13844, 13846, 13848, 13851, 13852, 13854, 13871, 13872, - 13873, 13879, 13882, 13883, 13884, 13885, 13886, 13892, 13895, 13908, - 13910, 13911, 13912, 13913, 13914, 13915, 13916, 13917, 13918, 13919, - 13920, 13921, 13922, 13923, 13924, 13926, 13927, 13928, 13938, 13941, - 13942, 13954, 13955, 13956, 13963, 13967, 13968, 13970, 13973, 13979, - 13983, 13986, 13996, 14012, 14027, 14033, 14034, 14036, 14040, 14043, - 14044, 14048, 14049, 14050, 14053, 14055, 14059, 14064, 14075, 14080, - 14083, 14103, 14104, 14109, 14112, 14117, 14122, 14123, 14134, 14153, - 14183, 14188, 14199, 14210, 14218, 14229, 14241, 14273, 14277, 14278 + 13576, 13579, 13583, 13592, 13594, 13613, 13618, 13637, 13656, 13658, + 13673, 13691, 13695, 13704, 13705, 13706, 13718, 13726, 13738, 13739, + 13743, 13750, 13758, 13760, 13761, 13775, 13786, 13787, 13792, 13806, + 13824, 13840, 13841, 13844, 13846, 13848, 13851, 13852, 13854, 13871, + 13872, 13873, 13879, 13882, 13883, 13884, 13885, 13886, 13892, 13895, + 13908, 13910, 13911, 13912, 13913, 13914, 13915, 13916, 13917, 13918, + 13919, 13920, 13921, 13922, 13923, 13924, 13926, 13927, 13928, 13938, + 13941, 13942, 13954, 13955, 13956, 13963, 13967, 13968, 13970, 13973, + 13979, 13983, 13986, 13996, 14012, 14027, 14033, 14034, 14036, 14040, + 14043, 14044, 14048, 14049, 14050, 14053, 14055, 14059, 14064, 14075, + 14080, 14083, 14103, 14104, 14109, 14112, 14117, 14122, 14123, 14134, + 14153, 14183, 14188, 14199, 14210, 14218, 14229, 14241, 14273, 14277, + 14278 * Support for the x32 ABI on x86-64 added. The x32 target is selected by configuring glibc with: diff --git a/elf/dl-close.c b/elf/dl-close.c index d232294..a250ea5 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -1,5 +1,5 @@ /* Close a shared object opened by `_dl_open'. - Copyright (C) 1996-2007, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1996-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -118,17 +118,8 @@ _dl_close_worker (struct link_map *map) if (map->l_direct_opencount > 0 || map->l_type != lt_loaded || dl_close_state != not_pending) { - if (map->l_direct_opencount == 0) - { - if (map->l_type == lt_loaded) - dl_close_state = rerun; - else if (map->l_type == lt_library) - { - struct link_map **oldp = map->l_initfini; - map->l_initfini = map->l_orig_initfini; - _dl_scope_free (oldp); - } - } + if (map->l_direct_opencount == 0 && map->l_type == lt_loaded) + dl_close_state = rerun; /* There are still references to this object. Do nothing more. */ if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0)) diff --git a/elf/dl-deps.c b/elf/dl-deps.c index 69aec46..2ae496d 100644 --- a/elf/dl-deps.c +++ b/elf/dl-deps.c @@ -1,6 +1,5 @@ /* Load the dependencies of a mapped object. - Copyright (C) 1996-2003, 2004-2007, 2010-2012 - Free Software Foundation, Inc. + Copyright (C) 1996-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -488,6 +487,7 @@ _dl_map_object_deps (struct link_map *map, nneeded * sizeof needed[0]); atomic_write_barrier (); l->l_initfini = l_initfini; + l->l_free_initfini = 1; } /* If we have no auxiliary objects just go on to the next map. */ @@ -688,6 +688,7 @@ Filters not supported with LD_TRACE_PRELINKING")); l_initfini[nlist] = NULL; atomic_write_barrier (); map->l_initfini = l_initfini; + map->l_free_initfini = 1; if (l_reldeps != NULL) { atomic_write_barrier (); @@ -696,7 +697,7 @@ Filters not supported with LD_TRACE_PRELINKING")); _dl_scope_free (old_l_reldeps); } if (old_l_initfini != NULL) - map->l_orig_initfini = old_l_initfini; + _dl_scope_free (old_l_initfini); if (errno_reason) _dl_signal_error (errno_reason == -1 ? 0 : errno_reason, objname, diff --git a/elf/dl-libc.c b/elf/dl-libc.c index a58e216..af2e663 100644 --- a/elf/dl-libc.c +++ b/elf/dl-libc.c @@ -1,6 +1,5 @@ /* Handle loading and unloading shared objects for internal libc purposes. - Copyright (C) 1999-2002,2004-2006,2009,2010,2011 - Free Software Foundation, Inc. + Copyright (C) 1999-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Zack Weinberg , 1999. @@ -269,13 +268,13 @@ libc_freeres_fn (free_mem) for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns) { - /* Remove all additional names added to the objects. */ for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next) { struct libname_list *lnp = l->l_libname->next; l->l_libname->next = NULL; + /* Remove all additional names added to the objects. */ while (lnp != NULL) { struct libname_list *old = lnp; @@ -283,6 +282,10 @@ libc_freeres_fn (free_mem) if (! old->dont_free) free (old); } + + /* Free the initfini dependency list. */ + if (l->l_free_initfini) + free (l->l_initfini); } if (__builtin_expect (GL(dl_ns)[ns]._ns_global_scope_alloc, 0) != 0 diff --git a/elf/rtld.c b/elf/rtld.c index a5b0ab9..6bcf224 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -2292,6 +2292,8 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", lnp->dont_free = 1; lnp = lnp->next; } + /* Also allocated with the fake malloc(). */ + l->l_free_initfini = 0; if (l != &GL(dl_rtld_map)) _dl_relocate_object (l, l->l_scope, GLRO(dl_lazy) ? RTLD_LAZY : 0, diff --git a/include/link.h b/include/link.h index 2eb3179..f0c8ad5 100644 --- a/include/link.h +++ b/include/link.h @@ -1,6 +1,6 @@ /* Data structure for communication from the run-time dynamic linker for loaded ELF shared objects. - Copyright (C) 1995-2006, 2007, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1995-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -191,6 +191,9 @@ struct link_map during LD_TRACE_PRELINKING=1 contains any DT_SYMBOLIC libraries. */ + unsigned int l_free_initfini:1; /* Nonzero if l_initfini can be + freed, ie. not allocated with + the dummy malloc in ld.so. */ /* Collected information about own RPATH directories. */ struct r_search_path_struct l_rpath_dirs; @@ -239,9 +242,6 @@ struct link_map /* List of object in order of the init and fini calls. */ struct link_map **l_initfini; - /* The init and fini list generated at startup, saved when the - object is also loaded dynamically. */ - struct link_map **l_orig_initfini; /* List of the dependencies introduced through symbol binding. */ struct link_map_reldeps -- cgit v1.1