Bug 8211 - pthread_atfork handlers not removed during dlclose
Summary: pthread_atfork handlers not removed during dlclose
Status: NEW
Alias: None
Product: uClibc
Classification: Unclassified
Component: Threads (show other bugs)
Version: 0.9.33.2
Hardware: PC Other
: P5 minor
Target Milestone: ---
Assignee: unassigned
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-07-09 23:08 UTC by John Ata
Modified: 2016-01-05 19:53 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:


Attachments
Invoke pthread_atfork handler cleanup when removing the associated DSO... (722 bytes, patch)
2015-07-09 23:08 UTC, John Ata
Details
Invoke pthread_atfork handler cleanup when removing the associated DSO... (807 bytes, patch)
2016-01-05 19:53 UTC, John Ata
Details

Note You need to log in before you can comment on or make changes to this bug.
Description John Ata 2015-07-09 23:08:32 UTC
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
Comment 1 Leonid 2015-12-22 18:46:11 UTC
Test-case can be taken from
 http://sourceware.org/bugzilla/show_bug.cgi?id=13502
Comment 2 Leonid 2016-01-02 11:56:49 UTC
Proposed patch breaks build both LT.old & LT.new. NPTL is fine.

Jonh, can you fix it?
Comment 3 John Ata 2016-01-05 01:32:35 UTC
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...
Comment 4 Leonid 2016-01-05 07:48:36 UTC
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;
Comment 5 John Ata 2016-01-05 19:53:00 UTC
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.