elf: Signal LA_ACT_CONSISTENT to auditors after RT_CONSISTENT switch

Auditors can call into the dynamic loader again if
LA_ACT_CONSISTENT, and  those recursive calls could observe
r_state != RT_CONSISTENT.

We should consider failing dlopen/dlmopen/dlclose if
r_state != RT_CONSISTENT.  The dynamic linker is probably not
in a state in which it can handle reentrant calls.  This
needs further investigation.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
This commit is contained in:
Florian Weimer 2024-10-25 16:50:10 +02:00
parent 9897ced8e7
commit e096b7a189
3 changed files with 13 additions and 13 deletions

View File

@ -723,6 +723,11 @@ _dl_close_worker (struct link_map *map, bool force)
/* TLS is cleaned up for the unloaded modules. */ /* TLS is cleaned up for the unloaded modules. */
__rtld_lock_unlock_recursive (GL(dl_load_tls_lock)); __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
/* Notify the debugger those objects are finalized and gone. */
r->r_state = RT_CONSISTENT;
_dl_debug_state ();
LIBC_PROBE (unmap_complete, 2, nsid, r);
#ifdef SHARED #ifdef SHARED
/* Auditing checkpoint: we have deleted all objects. Also, do not notify /* Auditing checkpoint: we have deleted all objects. Also, do not notify
auditors of the cleanup of a failed audit module loading attempt. */ auditors of the cleanup of a failed audit module loading attempt. */
@ -735,11 +740,6 @@ _dl_close_worker (struct link_map *map, bool force)
--GL(dl_nns); --GL(dl_nns);
while (GL(dl_ns)[GL(dl_nns) - 1]._ns_loaded == NULL); while (GL(dl_ns)[GL(dl_nns) - 1]._ns_loaded == NULL);
/* Notify the debugger those objects are finalized and gone. */
r->r_state = RT_CONSISTENT;
_dl_debug_state ();
LIBC_PROBE (unmap_complete, 2, nsid, r);
/* Recheck if we need to retry, release the lock. */ /* Recheck if we need to retry, release the lock. */
out: out:
if (dl_close_state == rerun) if (dl_close_state == rerun)

View File

@ -628,17 +628,17 @@ dl_open_worker_begin (void *a)
#endif #endif
} }
#ifdef SHARED
/* Auditing checkpoint: we have added all objects. */
_dl_audit_activity_nsid (new->l_ns, LA_ACT_CONSISTENT);
#endif
/* Notify the debugger all new objects are now ready to go. */ /* Notify the debugger all new objects are now ready to go. */
struct r_debug *r = _dl_debug_update (args->nsid); struct r_debug *r = _dl_debug_update (args->nsid);
r->r_state = RT_CONSISTENT; r->r_state = RT_CONSISTENT;
_dl_debug_state (); _dl_debug_state ();
LIBC_PROBE (map_complete, 3, args->nsid, r, new); LIBC_PROBE (map_complete, 3, args->nsid, r, new);
#ifdef SHARED
/* Auditing checkpoint: we have added all objects. */
_dl_audit_activity_nsid (new->l_ns, LA_ACT_CONSISTENT);
#endif
_dl_open_check (new); _dl_open_check (new);
/* Print scope information. */ /* Print scope information. */

View File

@ -2369,9 +2369,6 @@ dl_main (const ElfW(Phdr) *phdr,
_dl_relocate_object might need to call `mprotect' for DT_TEXTREL. */ _dl_relocate_object might need to call `mprotect' for DT_TEXTREL. */
_dl_sysdep_start_cleanup (); _dl_sysdep_start_cleanup ();
/* Auditing checkpoint: we have added all objects. */
_dl_audit_activity_nsid (LM_ID_BASE, LA_ACT_CONSISTENT);
/* Notify the debugger all new objects are now ready to go. We must re-get /* Notify the debugger all new objects are now ready to go. We must re-get
the address since by now the variable might be in another object. */ the address since by now the variable might be in another object. */
r = _dl_debug_update (LM_ID_BASE); r = _dl_debug_update (LM_ID_BASE);
@ -2379,6 +2376,9 @@ dl_main (const ElfW(Phdr) *phdr,
_dl_debug_state (); _dl_debug_state ();
LIBC_PROBE (init_complete, 2, LM_ID_BASE, r); LIBC_PROBE (init_complete, 2, LM_ID_BASE, r);
/* Auditing checkpoint: we have added all objects. */
_dl_audit_activity_nsid (LM_ID_BASE, LA_ACT_CONSISTENT);
#if defined USE_LDCONFIG && !defined MAP_COPY #if defined USE_LDCONFIG && !defined MAP_COPY
/* We must munmap() the cache file. */ /* We must munmap() the cache file. */
_dl_unload_cache (); _dl_unload_cache ();