fix malloc misuse for startup ctor queue, breakage on fdpic archs
authorRich Felker <dalias@aerifal.cx>
Sun, 3 Mar 2019 14:57:19 +0000 (09:57 -0500)
committerRich Felker <dalias@aerifal.cx>
Sun, 3 Mar 2019 17:06:44 +0000 (12:06 -0500)
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

index 203282858c66f48361f52407556d344f51cd332d..a2f059cbc9941513435aa847200767cd2b8f9ada 100644 (file)
@@ -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);