aboutsummaryrefslogtreecommitdiff
path: root/elf/dl-close.c
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2023-11-16 19:55:35 +0100
committerFlorian Weimer <fweimer@redhat.com>2023-11-16 20:16:05 +0100
commit849274d48fc59bfa6db3c713c8ced8026b20f3b7 (patch)
tree2f92737d63b3b236acd167df35a6d2556bea4c07 /elf/dl-close.c
parenta8dcffb30680d6db5704f9ce2fc30621ceb454e7 (diff)
downloadglibc-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.c23
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;
}