From 2f1f51ae7b2d78247568e7fdb8462f3c19e469a4 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sun, 3 Mar 2019 09:57:19 -0500 Subject: [PATCH] fix malloc misuse for startup ctor queue, breakage on fdpic archs in the case where malloc is being replaced, it's not valid to call malloc between final relocations and main app's crt1 entry point; on fdpic archs the main app's entry point will not yet have performed the self-fixups necessary to call its code. to fix, reorder queue_ctors before final relocations. an alternative solution would be doing the allocation from __libc_start_init, after the entry point but before any ctors run. this is less desirable, since it would leave a call to malloc that might be provided by the application happening at startup when doing so can be easily avoided. --- ldso/dynlink.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/ldso/dynlink.c b/ldso/dynlink.c index 20328285..a2f059cb 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -1479,9 +1479,7 @@ static void do_init_fini(struct dso **queue) void __libc_start_init(void) { do_init_fini(main_ctor_queue); - /* This is valid because the queue was allocated after redoing - * relocations with any interposed malloc having taken effect. */ - free(main_ctor_queue); + if (!__malloc_replaced) free(main_ctor_queue); main_ctor_queue = 0; } @@ -1851,6 +1849,14 @@ _Noreturn void __dls3(size_t *sp) } } + /* This must be done before final relocations, since it calls + * malloc, which may be provided by the application. Calling any + * application code prior to the jump to its entry point is not + * valid in our model and does not work with FDPIC, where there + * are additional relocation-like fixups that only the entry point + * code can see to perform. */ + main_ctor_queue = queue_ctors(&app); + /* The main program must be relocated LAST since it may contin * copy relocations which depend on libraries' relocations. */ reloc_all(app.next); @@ -1879,8 +1885,6 @@ _Noreturn void __dls3(size_t *sp) } static_tls_cnt = tls_cnt; - main_ctor_queue = queue_ctors(&app); - if (ldso_fail) _exit(127); if (ldd_mode) _exit(0);