diff options
author | Florian Weimer <fweimer@redhat.com> | 2019-12-13 10:18:46 +0100 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2019-12-13 10:18:46 +0100 |
commit | f8ed116aa574435c6e28260f21963233682d3b57 (patch) | |
tree | 859f2077eec2bc1e19f99e4853c4a8bf1c2f7848 /elf/get-dynamic-info.h | |
parent | 365624e2d2a342cdb693b4cc35d2312169959e28 (diff) | |
download | glibc-f8ed116aa574435c6e28260f21963233682d3b57.tar.gz glibc-f8ed116aa574435c6e28260f21963233682d3b57.tar.xz glibc-f8ed116aa574435c6e28260f21963233682d3b57.zip |
dlopen: Rework handling of pending NODELETE status
Commit a2e8aa0d9ea648068d8be52dd7b15f1b6a008e23 ("Block signals during the initial part of dlopen") was deemed necessary because of read-modify-write operations like the one in add_dependency in elf/dl-lookup.c. In the old code, we check for any kind of NODELETE status and bail out: /* Redo the NODELETE check, as when dl_load_lock wasn't held yet this could have changed. */ if (map->l_nodelete != link_map_nodelete_inactive) goto out; And then set pending status (during relocation): if (flags & DL_LOOKUP_FOR_RELOCATE) map->l_nodelete = link_map_nodelete_pending; else map->l_nodelete = link_map_nodelete_active; If a signal arrives during relocation and the signal handler, through lazy binding, adds a global scope dependency on the same map, it will set map->l_nodelete to link_map_nodelete_active. This will be overwritten with link_map_nodelete_pending by the dlopen relocation code. To avoid such problems in relation to the l_nodelete member, this commit introduces two flags for active NODELETE status (irrevocable) and pending NODELETE status (revocable until activate_nodelete is invoked). As a result, NODELETE processing in dlopen does not introduce further reasons why lazy binding from signal handlers is unsafe during dlopen, and a subsequent commit can remove signal blocking from dlopen. This does not address pre-existing issues (unrelated to the NODELETE changes) which make lazy binding in a signal handler during dlopen unsafe, such as the use of malloc in both cases. Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Diffstat (limited to 'elf/get-dynamic-info.h')
-rw-r--r-- | elf/get-dynamic-info.h | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h index 075683d729..ea4e304bef 100644 --- a/elf/get-dynamic-info.h +++ b/elf/get-dynamic-info.h @@ -164,7 +164,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) { l->l_flags_1 = info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val; if (l->l_flags_1 & DF_1_NODELETE) - l->l_nodelete = link_map_nodelete_pending; + l->l_nodelete_pending = true; /* Only DT_1_SUPPORTED_MASK bits are supported, and we would like to assert this, but we can't. Users have been setting |