diff options
author | Florian Weimer <fweimer@redhat.com> | 2023-11-16 19:55:35 +0100 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2023-11-16 20:16:05 +0100 |
commit | 849274d48fc59bfa6db3c713c8ced8026b20f3b7 (patch) | |
tree | 2f92737d63b3b236acd167df35a6d2556bea4c07 /elf/dl-close.c | |
parent | a8dcffb30680d6db5704f9ce2fc30621ceb454e7 (diff) | |
download | glibc-849274d48fc59bfa6db3c713c8ced8026b20f3b7.zip glibc-849274d48fc59bfa6db3c713c8ced8026b20f3b7.tar.gz glibc-849274d48fc59bfa6db3c713c8ced8026b20f3b7.tar.bz2 |
elf: Fix force_first handling in dlclose (bug 30981)
The force_first parameter was ineffective because the dlclose'd
object was not necessarily the first in the maps array. Also
enable force_first handling unconditionally, regardless of namespace.
The initial object in a namespace should be destructed first, too.
The _dl_sort_maps_dfs function had early returns for relocation
dependency processing which broke force_first handling, too, and
this is fixed in this change as well.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Diffstat (limited to 'elf/dl-close.c')
-rw-r--r-- | elf/dl-close.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/elf/dl-close.c b/elf/dl-close.c index 1c7a861..a97a1ef 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -153,6 +153,16 @@ _dl_close_worker (struct link_map *map, bool force) } assert (idx == nloaded); + /* Put the dlclose'd map first, so that its destructor runs first. + The map variable is NULL after a retry. */ + if (map != NULL) + { + maps[map->l_idx] = maps[0]; + maps[map->l_idx]->l_idx = map->l_idx; + maps[0] = map; + maps[0]->l_idx = 0; + } + /* Keep track of the lowest index link map we have covered already. */ int done_index = -1; while (++done_index < nloaded) @@ -226,9 +236,10 @@ _dl_close_worker (struct link_map *map, bool force) } } - /* Sort the entries. We can skip looking for the binary itself which is - at the front of the search list for the main namespace. */ - _dl_sort_maps (maps, nloaded, (nsid == LM_ID_BASE), true); + /* Sort the entries. Unless retrying, the maps[0] object (the + original argument to dlclose) needs to remain first, so that its + destructor runs first. */ + _dl_sort_maps (maps, nloaded, /* force_first */ map != NULL, true); /* Call all termination functions at once. */ bool unload_any = false; @@ -732,7 +743,11 @@ _dl_close_worker (struct link_map *map, bool force) /* Recheck if we need to retry, release the lock. */ out: if (dl_close_state == rerun) - goto retry; + { + /* The map may have been deallocated. */ + map = NULL; + goto retry; + } dl_close_state = not_pending; } |