Skip to content

Commit

Permalink
i#5133: Call __libc_eary_init for private libc (#5134)
Browse files Browse the repository at this point in the history
Mirrors the glibc 2.32+ behavior where ld.so has a hardcoded call to
"__libc_eary_init" before it calls the regular ELF constructors.

This fixes crashes in clients on Ubuntu 21.
Tested in Dr. Memory on Ubuntu 21.

Fixes #5133
  • Loading branch information
derekbruening authored Sep 30, 2021
1 parent 26b5fb4 commit f3d907d
Showing 1 changed file with 26 additions and 12 deletions.
38 changes: 26 additions & 12 deletions core/unix/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ stdfile_t **privmod_stdin;
#define LIBC_STDOUT_NAME "stdout"
#define LIBC_STDERR_NAME "stderr"
#define LIBC_STDIN_NAME "stdin"
#define LIBC_EARLY_INIT_NAME "__libc_early_init"

/* We save the original sp from the kernel, for use by TLS setup on Android */
void *kernel_init_sp;
Expand Down Expand Up @@ -657,9 +658,32 @@ privload_redirect_setup(privmod_t *privmod)
}

void
privload_os_finalize(privmod_t *privmod_t)
privload_os_finalize(privmod_t *privmod)
{
/* nothing */
#ifndef LINUX
return; /* Nothing to do. */
#else
if (strstr(privmod->name, "libc.so") != privmod->name)
return;
os_privmod_data_t *opd = (os_privmod_data_t *)privmod->os_privmod_data;
/* Special handling for standard I/O file descriptors. */
privmod_stdout = (FILE **)get_proc_address_from_os_data(
&opd->os_data, opd->load_delta, LIBC_STDOUT_NAME, NULL);
privmod_stdin = (FILE **)get_proc_address_from_os_data(&opd->os_data, opd->load_delta,
LIBC_STDIN_NAME, NULL);
privmod_stderr = (FILE **)get_proc_address_from_os_data(
&opd->os_data, opd->load_delta, LIBC_STDERR_NAME, NULL);
/* i#5133: glibc 2.32+ has ld.so call a hardcoded initializer before calling the
* regular ELF constructors.
*/
void (*libc_early_init)(bool) = (void (*)(bool))get_proc_address_from_os_data(
&opd->os_data, opd->load_delta, LIBC_EARLY_INIT_NAME, NULL);
if (libc_early_init != NULL) {
LOG(GLOBAL, LOG_LOADER, 2, "%s: calling %s\n", __FUNCTION__,
LIBC_EARLY_INIT_NAME);
(*libc_early_init)(true);
}
#endif
}

static void
Expand Down Expand Up @@ -1174,16 +1198,6 @@ privload_relocate_mod(privmod_t *mod)
*/
if (opd->tls_block_size != 0)
privload_mod_tls_primary_thread_init(mod);

/* special handling on I/O file */
if (strstr(mod->name, "libc.so") == mod->name) {
privmod_stdout = (FILE **)get_proc_address_from_os_data(
&opd->os_data, opd->load_delta, LIBC_STDOUT_NAME, NULL);
privmod_stdin = (FILE **)get_proc_address_from_os_data(
&opd->os_data, opd->load_delta, LIBC_STDIN_NAME, NULL);
privmod_stderr = (FILE **)get_proc_address_from_os_data(
&opd->os_data, opd->load_delta, LIBC_STDERR_NAME, NULL);
}
#else
/* XXX i#1285: implement MacOS private loader */
#endif
Expand Down

0 comments on commit f3d907d

Please sign in to comment.