rtld: avoid recursing on rtld_bind_lock for write

This fixes a regression in d36d681615, where the call to
__tls_get_address() was performed under rtld_bind_lock write-locked.
Instead use tls_get_addr_slow() directly, with locked = true.

Reported by:	jkim, many others
Tested by:	jkim, bdragon (powerpc), mhorne (riscv)
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D29623
This commit is contained in:
Konstantin Belousov 2021-04-06 22:02:23 +03:00
parent 8950804842
commit 7cb32a0d03
3 changed files with 7 additions and 4 deletions

View File

@ -67,6 +67,8 @@ _libc_other_objects+=syncicache abs
_libc_other_objects+=syncicache
.endif
_libc_other_objects+=_get_tp
# Extract all the .o files from libc_nossp_pic.a. This ensures that
# we don't accidentally pull in the interposing table or similar by linking
# directly against libc_nossp_pic.a

View File

@ -3910,16 +3910,16 @@ dlinfo(void *handle, int request, void *p)
static void
rtld_fill_dl_phdr_info(const Obj_Entry *obj, struct dl_phdr_info *phdr_info)
{
tls_index ti;
Elf_Addr **dtvp;
phdr_info->dlpi_addr = (Elf_Addr)obj->relocbase;
phdr_info->dlpi_name = obj->path;
phdr_info->dlpi_phdr = obj->phdr;
phdr_info->dlpi_phnum = obj->phsize / sizeof(obj->phdr[0]);
phdr_info->dlpi_tls_modid = obj->tlsindex;
ti.ti_module = obj->tlsindex;
ti.ti_offset = 0;
phdr_info->dlpi_tls_data = __tls_get_addr(&ti);
dtvp = _get_tp();
phdr_info->dlpi_tls_data = (char *)tls_get_addr_slow(dtvp,
obj->tlsindex, 0, true) + TLS_DTV_OFFSET;
phdr_info->dlpi_adds = obj_loads;
phdr_info->dlpi_subs = obj_loads - obj_count;
}

View File

@ -401,6 +401,7 @@ bool allocate_tls_offset(Obj_Entry *obj);
void free_tls_offset(Obj_Entry *obj);
const Ver_Entry *fetch_ventry(const Obj_Entry *obj, unsigned long);
int convert_prot(int elfflags);
void *_get_tp(void); /* libc implementation */
/*
* MD function declarations.