Recently I tried to build a complex C++ application. App was built. But when I tried to launch it it crashed with illegal memory access. Actually it was null pointer with offset.
I started to investigate the reason. Crash happens while dynamically loading a library (libXcursor.so) with dlopen. So the reason was null pointer link_map->l_versions which wasn't checked in the process of relocation inside elf_machine_rela function (particularry in RESOLVE_MAP macro). This happens here: map->l_versions[ndx]
ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
&map->l_versions[ndx],
(void *) (l_addr + r->r_offset), skip_ifunc);
Aforementioned link_map is a dependency description of a library in loading process. This dependency was not completely initialized as I can see. But what is more strange is that this is not actually a dependency: it's a libgthread library DSO. And libXcursor.so indeed does not depend on it.
The mentioned link_map of libgthread is passed for relocation from dl_open_worker:
_dl_relocate_object (l, l->l_scope, reloc_mode, 0);
Beeing collected to the list of dependecies this way:
l = new;
do
{
if (! l->l_real->l_relocated)
maps[nmaps++] = l;
l = l->l_next;
}
while (l != NULL);
Here new is the found link_map of libXcursor.so itself.
And this piece of code is very strange IMHO.
Because at the same time other deps are actually initialized with this code:
/* Load that object's dependencies. */
_dl_map_object_deps (new, NULL, 0, 0,
mode & (__RTLD_DLOPEN | RTLD_DEEPBIND | __RTLD_AUDIT));
/* So far, so good. Now check the versions. */
for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
if (new->l_searchlist.r_list[i]->l_real->l_versions == NULL)
(void) _dl_check_map_versions (new->l_searchlist.r_list[i]->l_real,
0, 0);
So question is why is other list of dependencies passed and no additional checks are made in such an important place (system loader). And probably where to fix the crash.
Used libdl's version is /lib64/libdl-2.27.so from glibc-2.27-38.fc28.x86_64
Seems like problem was fixed in here, here, there and there. It does not reproduces. Small app can't reproduce original crash with version 2.27 either.