Created attachment 6096 [details] Invoke pthread_atfork handler cleanup when removing the associated DSO... If a program loads a DSO (dlopen) that sets up a pthread_atfork handler(s), and then subsequently closes the DSO, the handler(s) are left in place. If fork() is subsequently called, the handlers are invoked even though the DSO has been removed causing crashes or unpredictable code execution. This is because the code in __cxa_finalize(atexit.c)to invoke the unregister_atfork() routine is ifdef'd out with the comment that it hasn't been "looked into this yet...". I have added the code in and it seems to work properly. --- libc/stdlib/_atexit.c 2015-07-09 13:08:22.080550119 -040 0 +++ libc/stdlib/_atexit.c 2015-07-08 18:12:06.476077 601 -0400 @@ -42,6 +42,7 @@ #include <stdlib.h> #include <errno.h> #include <atomic.h> +#include <fork.h> #include <bits/uClibc_mutex.h> __UCLIBC_MUTEX_EXTERN(__atexit_lock); @@ -207,17 +208,15 @@ } } -#if 0 /* haven't looked into this yet... */ /* * Remove the registered fork handlers. We do not have to * unregister anything if the program is going to terminate anyway. */ #ifdef UNREGISTER_ATFORK - if (d != NULL) { - UNREGISTER_ATFORK(d); + if (dso_handle != NULL) { + UNREGISTER_ATFORK(dso_handle); } #endif -#endif } #endif
Test-case can be taken from http://sourceware.org/bugzilla/show_bug.cgi?id=13502
Proposed patch breaks build both LT.old & LT.new. NPTL is fine. Jonh, can you fix it?
Our toolchain was converted to use nptl along with out kernel, I no longer have a convenient way to build with any of the linux_threads versions... :-( If you post an output script with the errors for the linux_thread.old and linux_thread, I'll take a look but don't think I could test...
The problem is simple: 1) LT.old hasn't fork.h & __unregister_atfork() at all. 2) in LT.new __register_atfork()/__unregister_atfork() functions resides in libpthread and not accessible from libc directly. So, my suggestion, since rework LT.old & LT.new is a large separate task, simply to enable pthread_atfork handlers cleanup for NPTL only. i.e. first hunk of your patch should be changed to: @@ -42,6 +42,9 @@ #include <stdlib.h> #include <errno.h> #include <atomic.h> +#if defined __UCLIBC_HAS_THREADS__ && defined __UCLIBC_HAS_THREADS_NATIVE__ +# include <fork.h> +#endif #include <bits/uClibc_mutex.h> __UCLIBC_MUTEX_EXTERN(__atexit_lock) attribute_hidden;
Created attachment 6276 [details] Invoke pthread_atfork handler cleanup when removing the associated DSO... Takes into account both old and new linuxthreads and seems to continue working fine with ntpl.